2016-03-01 99 views
0

因此,下面是一个函数,用于从字符串中过滤出给定的字符ch,并将结果放入过滤后的版本。底部的puts语句最终输出与原始字符串相同的字符串,无论过滤后的字符如何,结果都是空的。从C中的字符串中过滤字符C

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); 
} 

回答

1

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

当字符不同时,您不会将其复制到result,,但您仍然增量i。在result字符串中留下。为了解决这个问题,你可以使用指针(引用和增量)。

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

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

#include <stdio.h> 

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 <string> <character>\n", argv[0]); 
     return 0; 
    } 

    filter(argv[1], buffer, argv[2][0]); 
    return 0; 
} 

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

我们只会增加b字符串如果我们复制一些东西,否则它的引用保持不变。该过程将继续,直到循环找到a字符串中的\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 ] $ 
+0

这清理了很多,非常感谢。 –

+0

@PaulRoub噢,谢谢! –

1

需要两个指标,一个你正在阅读和你写的一个:

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足够大。请注意,复制函数中参数的最常见顺序是'目的地,源'(请参阅strcpy(),memmove(),...),但您的顺序相反。

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

请注意,你可以在原地安全地修改源字符串;输出字符串永远不会比源字符串长。这样可以避免缓冲区溢出,除非源字符串本身无效(不是空终止)。接口是void replace_ch(char *string, char ch)。上面的函数可以使用void filter_ch_index(const char string[], char result[], char ch)const来表示源字符串不会被函数修改。