在C中过滤字符串中的字符

所以下面是一个函数,它应该从字符串中过滤出给定的字符ch,并将过滤后的版本放在结果中。 底部的puts语句最终会输出与原始字符串相同的字符串,而不管过滤后的字符是什么,结果最终为空。

void filter_ch_index(char string[], char result[], char ch) { result[0] = NUL ; // placeholder int i; for(i = 0; i < strlen(string); i++) { if(string[i] != ch) { result[i] = string[i]; } } puts(result); } 

其中一个问题是你的复制逻辑。

当字符不同时,您不会将其复制到result但无论如何都会增加 。 这会在result字符串中留下漏洞 。 要解决这个问题,您可以使用指针(引用和增量)。

我看到的另一个问题是你如何调用这个函数。 你为这两个分配了足够的内存空间吗?

我将放置一个非常不安全的函数实现来展示你如何做到这一点。 您应该修改函数以考虑字符串大小。

 #include  void filter(char *a, char *b, char c) { char *aux = b; while(*a) { if(*a != c) *b++ = *a; a++; } *b = 0x0; // thx to @PaulRoub for pointing it out puts(aux); } int main(int argc, char *argv[]) { char buffer[100]; if(argc < 3) { printf("Usage: %s  \n", argv[0]); return 0; } filter(argv[1], buffer, argv[2][0]); return 0; } 

在上面的代码中, aux用作b的起始地址的备份。 while循环将继续,而当前a字符不是\0 (您可以将其读作while (*a != '\0') )。 条件也非常简单。 复制部分是我之前谈到的。

如果我们将一些东西复制到它中,我们只增加b字符串 ,否则,它的引用保持不变。 该过程将继续,直到循环在字符串中找到\0终止字符。

产出:

 [ ~/src/test ] $ ./filter "Stack Overflow Questions" e Stack Ovrflow Qustions [ ~/src/test ] $ ./filter "Stack Overflow Questions" S tack Overflow Questions [ ~/src/test ] $ ./filter "Stack Overflow Questions" s Stack Overflow Quetion [ ~/src/test ] $ ./filter "aaa bbb ccc abc cba" a bbb ccc bc cb [ ~/src/test ] $ ./filter "aaa bbb ccc abc cba" b aaa ccc ac ca [ ~/src/test ] $ ./filter "aaa bbb ccc abc cba" c aaa bbb ab ba [ ~/src/test ] $ 

您需要两个索引,即您正在阅读的索引和您要写入的索引:

 void filter_ch_index(char string[], char result[], char ch) { int j = 0; for (int i = 0; string[i] != '\0'; i++) { if (string[i] != ch) result[j++] = string[i]; } result[j] = '\0' puts(result); } 

这假设result足够大。 请注意,复制函数中参数的最常见顺序是“destination,source”(请参阅strcpy()memmove() ,…),但您的顺序是相反的。

请注意,使用原始for(i = 0; i < strlen(string); i++)是一个坏主意。 在循环条件中使用strlen()将线性算法转换为二次算法,除非您有足够复杂的编译器来发现字符串的长度在循环的每次迭代中都不会改变。 (战争故事:一个又一个千年,有一个strstr()的实现,包括一个类似的循环条件。它在小字符串上工作正常 - 比如100字节以下;当用于20 KiB及更多的字符串时,这是一个灾难大多数平台都很好 - 这个没有。这个bug早就修好了。)

请注意,您可以安全地修改源字符串; 输出字符串永远不会长于源字符串。 这可以避免缓冲区溢出,除非源字符串本身无效(不是以null结尾)。 void replace_ch(char *string, char ch)是接口。 上面的函数可以使用void filter_ch_index(const char string[], char result[], char ch)编写, const指示源函数不会被函数修改。