从找到空格和标点符号的数组中删除字符[重复]

Posted

技术标签:

【中文标题】从找到空格和标点符号的数组中删除字符[重复]【英文标题】:Remove character from array where spaces and punctuation marks are found [duplicate] 【发布时间】:2014-02-13 18:53:11 【问题描述】:

在我的程序中,我正在检查整个 cstring,如果发现任何空格或标点符号,只需在该位置添加空字符,但编译器给我一个错误:空字符常量。

请帮帮我,在我的循环中我是这样检查的

if(ispunct(str1[start])) 
    str1[start]=''; // << empty character constant. 

if(isspace(str1[start])) 
    str1[start]=''; // << empty character constant. 

这是我的错误,请纠正我。

例如,单词是str,, ing,,输出应该是string

【参考方案1】:

没有空字符这样的东西。

如果您指的是空格,请将'' 更改为' '(其中包含空格)。

如果您的意思是NUL,请将其更改为'\0'

【讨论】:

不,我不是指空字符,我只是想用空格替换空格和标点符号。 @user3215228 什么是“空白空间”?你是说空格字符吗?还是您真的想删除字符串中的空格和标点符号? 您的意思是要删除这些字符吗?你不能通过给它们赋值来做到这一点。您需要将该位置之后的字符串中的所有字符移回一个位置或其他位置。 例如单词是str,,ing,输出应该是字符串 @user3215228 正如 paulpro 提到的,您想要 删除 字符。这是一个完全不同的操作,我建议使用std::string 来执行此操作,否则将字符串的其余部分复制到您找到问题字符的位置。【参考方案2】:

编辑:既然 OP 已经编辑了问题,答案就不再相关了。为了子孙后代而离开。

如果要添加空字符,请使用“\0”。如果您想使用不同的字符,请使用适当的字符。你不能分配任何东西。那是没有意义的。就像在说

int myHexInt = 0x;

long long myIndeger = L;

编译器会出错。输入你想要的值。在 char 的情况下,这是一个从 0 到 255 的值。

【讨论】:

不,我不是指空字符,我只是想用空格替换空格和标点符号。 好的,那就用空格符吧。 str1[start]=' '; 只是不要试图给任何东西分配一个字符。这就像说 int x = ; 并希望它编译。 @m24p OP 想要用空格字符替换空格字符?? 我认为“isspace”功能正在检查所有类型的空白,例如制表符等。此后,OP 明确表示真正的问题应该是如何删除字符。 @m24p 我一直在澄清,但没关系......【参考方案3】:

更新:

从编辑到 OP 的问题,很明显他/她想修剪一串标点和空格字符。

如标记的可能重复项中所述,一种方法是使用remove_copy_if

string test = "THisisa test;;';';';";
string temp, finalresult;

remove_copy_if(test.begin(), test.end(), std::back_inserter(temp), ptr_fun<int, int>(&ispunct));
remove_copy_if(temp.begin(), temp.end(), std::back_inserter(finalresult), ptr_fun<int, int>(&isspace));

原创

检查你的问题,用空格替换空格是多余的,所以你真的需要弄清楚如何用空格替换标点符号。您可以使用比较函数(通过包装 std::ispunct)与来自 STL 的 std::replace_if 一起使用:

#include <string>
#include <algorithm>
#include <iostream>
#include <cctype>
using namespace std;

bool is_punct(const char& c) 
    return ispunct(c);


int main() 
    string test = "THisisa test;;';';';";
    char test2[] = "THisisa test;;';';'; another";

    size_t size = sizeof(test2)/sizeof(test2[0]);

    replace_if(test.begin(), test.end(), is_punct, ' ');//for C++ strings
    replace_if(&test2[0], &test2[size-1], is_punct, ' ');//for c-strings

    cout << test << endl;
    cout << test2 << endl;

这个输出:

THisisa test
THisisa test         another

【讨论】:

对于反对者,有什么可以改进的吗?如果是这样,我欢迎任何反馈。 @πάνταῥεῖ:没问题。这是一个诚实的错误:这些事情确实发生了。 'To the downvoter ..' 抱歉,这不是一个错误:问题要求删除该字符,而不是用空格替换( '\0x32')!你最好提到std::remove_if ... @πάνταῥεῖ:我现在才看到那个编辑:我正在处理它。谢谢! 这个问题不是重复的,至少接受的答案不适用......【参考方案4】:

试试这个(正如你明确要求的cstring):

char str1[100] = "str,, ing";

if(ispunct(str1[start]) || isspace(str1[start])) 
    strncpy(str1 + start, str1 + start + 1, strlen(str1) - start + 1);

好吧,仅使用纯 c 语言执行此操作,还有更有效的解决方案(有关详细信息,请查看 @MichaelPlotke 的答案)。

但由于您也明确要求c++,我建议如下解决方案:

注意可以将standard c++ algorithms 用于“普通”c 样式字符数组。您只需将要移除的谓词条件放入一个小的辅助函子中,并将其与std::remove_if() 算法一起使用:

struct is_char_category_in_question 
    bool operator()(const char& c) const;
;

然后像这样使用它:

#include <string>
#include <algorithm>
#include <iostream>
#include <cctype>
#include <cstring>

// Best chance to have the predicate elided to be inlined, when writing 
// the functor like this:
struct is_char_category_in_question 
    bool operator()(const char& c) const 
        return std::ispunct(c) || std::isspace(c);
    
;

int main() 
    static char str1[100] = "str,, ing";
    size_t size = strlen(str1);

    // Using std::remove_if() is likely to provide the best balance from perfor-
    // mance  and code size efficiency you can expect from your compiler 
    // implementation.
    std::remove_if(&str1[0], &str1[size + 1], is_char_category_in_question());

    // Regarding specification of the range definitions end of the above state-
    // ment, note we have to add 1 to the strlen() calculated size, to catch the 
    // closing `\0` character of the c-style string being copied correctly and
    // terminate the result as well!

    std::cout << str1 << endl; // Prints: string

另请参阅此可编译和工作示例here。

【讨论】:

我不是反对者,但我可以推测这可能与这个答案有关:***.com/a/6987247/866930。 在c++ 中使用strncpy() 有什么不好??我有很多情况,我根本无法承受std::string 的便利和使用... 您在 C 字符串上使用 remove_if完全错误的,因为 remove_if 不会从静态分配的数组中删除字符,而只会保留内容在字符串的其余部分中未替换的内存中。 @jrd1 至少this 工作正常?数组是否是静态分配的都没关系,恕我直言(您的意思是 const 输入吗??)! 以前没见过remove_if。看起来很酷。不过,我发现我的 c 风格答案更具可读性。【参考方案5】:

因为我不喜欢接受的答案,所以这是我的:

#include <stdio.h>
#include <string.h>
#include <cctype>

int main() 
    char str[100] = "str,, ing";
    int bad = 0;
    int cur = 0;
    while (str[cur] != '\0') 
        if (bad < cur && !ispunct(str[cur]) && !isspace(str[cur])) 
                str[bad] = str[cur];
        
        if (ispunct(str[cur]) || isspace(str[cur])) 
            cur++;
        
        else 
            cur++;
            bad++;
        
    
    str[bad] = '\0';
    fprintf(stdout, "cur = %d; bad = %d; str = %s\n", cur, bad, str);
    return 0;

哪个输出cur = 18; bad = 14; str = string

这样做的好处是更高效、更易读,嗯,嗯,是我碰巧更喜欢的风格(请参阅 cmets 进行冗长的辩论/解释)。

【讨论】:

是的,在稍微修正了您的代码it works fine 并且效率更高(至少与strncpy() 版本相比)。很高兴得到确认,remove_if() 示例确实不如您的答案中给出的有效。 @πάνταῥεῖ 是的,您的代码确实明显效率较低。效率降低了大约 16 倍(在我的机器上)。我只是对每个进行了基准测试。随意复制我的发现。 好点,那么!你能多介绍一下你的基准测试方法吗?我很担心,因为remove_if() 可以很容易地以与您类似的方式实现,而且我通常假设标准实现 尽可能高效地涵盖适用的用例。遗憾的是,对于 all 编译器和 c++ 标准库实现来说,这可能不是真的! 基准测试只使用the top answer's method 来为每个方法的 10000000 次迭代计时,并使用字符串“str,, ing”。 FWIW 我的 C 风格解决方案类似于 char *dst = str, *src = str; while (*src) if !ispunct(*src) &amp;&amp; !isspace(*src) *dst++ = *src; ++src; *dst = 0;。这几乎正​​是remove_if 所做的如果您可以正确内联所有内容,当然它不知道以 nul 结尾的字符串。

以上是关于从找到空格和标点符号的数组中删除字符[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从数据框中删除所有标点符号,除了一些字符[重复]

删除标点查询

RegEx Tokenizer:将文本拆分为单词、数字、标点和空格(不要删除任何内容)

将字符串转换为数组后从字符串中删除特定项目

java:获取字符串中第一个不是数字或者标点符号或者空格的位置

用于匹配空格或标点符号和非字母数字的正则表达式