如何删除垃圾输入'从C字符串?

时间:2015-04-08 10:00:30

标签: c c-strings character-arrays

我正在尝试编写一个删除数组中所有字符的函数,但'+''-''*''/'和数字除外。这是我提出的代码:

void eliminateJunk(char string[MAX]){
    int i,j;
    char stringOut[MAX];
    int length = strlen(string) - 1;

    for(i=0; i <= length; i++){
        if(string[i] != '+'
        && string[i] != '-'
        && string[i] != '*'
        && string[i] != '/'
        && !(isdigit(string[i]))){
            for(j=i; j < length; j++){
                string[j] = string[j+1];
            }
        }
    }
}

但是,该函数并不总是从c字符串中删除所有垃圾字符 - 它会占用大部分字符,但偶尔会留下一些。

示例输入:

123 123

数组修改后的输出示例:

123123

但是,在某些输入中,它会留下空格......

示例输入:

123   123

示例输出:

123 123

我该怎么做才能解决这个问题?我觉得解决方案就在我的鼻子底下,但我似乎无法找到它。

4 个答案:

答案 0 :(得分:10)

这是移除时的经典问题:在for循环后需要递减i,否则跳过下一个字符。

但是,嵌套的for循环是不必要的:您可以通过维护单独的readwrite索引来完成整个事务。当您看到有效字符时,将其从读取位置移动到写入位置,并递增两个索引。当您看到无效字符时,请在不移动字符的情况下递增读取索引。在循环结束时终止字符串 - 你完成了!

int r, w; // r for "read", w for "write"
for(r=0, w=0; r != length ; r++) {
    // Your condition is inverted
    if(string[r] == '+'
    || string[r] == '-'
    || string[r] == '*'
    || string[r] == '/'
    || (isdigit(string[r]))) {
        // No loop inside
        string[w++] = string[r];
    }
}
// Add null terminator at the end
string[w] = '\0';

答案 1 :(得分:3)

问题是删除字符后不会减少i的值。

让我们更好地解释一下。如果您发现某个字符不是您想要的字符之一并将其删除,则所有其他字符将移回一个索引。然后,您递增i,因此您不会检查在该迭代中移回的第一个字符是否正确,从而跳过该字符。

让我们看看你的string。输入后,它变为

1 2 3       1 2 3
^ ^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 7 8       // these are the indeces

现在,让我们跳过几次迭代,然后转到删除索引3处的空间的部分。删除后,您的字符串将显示为

1 2 3     1 2 3 3
^ ^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 7 8

然后,您继续查看下一个i索引,即i = 4i = 3处的空格保持不变。在此迭代之后,它变为

1 2 3   1 2 3 3 3
^ ^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 7 8

如你所见,空间留在那里。这就是导致问题的原因。

因此,您需要递减ilength,以便检查所有字符。

你应该做

void eliminateJunk(char string[MAX])
{
    int i,j;
    char stringOut[MAX];
    int length = strlen(string) - 1;

    for(i=0; i <= length; i++)
    {
        if( string[i] != '+' 
            && string[i] != '-' 
            && string[i] != '*' 
            && string[i] != '/' 
            && !( isdigit(string[i]) ) )
        {
               for(j=i; j < length; j++)
               {
                   string[j] = string[j+1];
               }
               i--;
               length--;
        }
    }
    string[i]='\0';
    printf("%s",string);
}

我还添加了

    string[i]='\0';

这样你就可以以正确的长度结束数组。

答案 2 :(得分:2)

当你从数组中删除一个字符时,你减少了长度,所以你需要将变量长度减一,以及将索引减一。

还要记住c中的字符串是空终止的,因此您还需要复制尾随空字符,否则您将跳过下一个字符。

如果您进行了这些更改,您的功能将如下所示:

void eliminateJunk(char string[MAX]){
    int i,j;
    char stringOut[MAX];
    int length = strlen(string) - 1;

    for(i=0; i <= length; i++){
        if(string[i] != '+'
        && string[i] != '-'
        && string[i] != '*'
        && string[i] != '/'
        && !(isdigit(string[i]))){
            for(j=i; j < length + 1; j++){
                string[j] = string[j+1];
            }
            length--;
            i--;
        }
    }
}

答案 3 :(得分:0)

there are a few problems with the code.  
1) the string actually gets shorter when ever a character is removed. 
2) when a character is removed, 
   i needs to point to the new current character, 
   not the next character.  The 'for' statement will increment 'i'
   the code needs to decrement 'i'.
3) the new string array is unused.
   suggest either copying the characters to keep to 
   successive positions in the new string array or 
   remove the new string array from the code. 
   suggest compiling with all warnings enabled
   so the compiler can tell you about problems in the code

   As it is, that unused new string array is 
   causing the compiler to raise a warning.
   for several reasons, the warning about the unused variable
   needs to be fixed.

 4) suggest having the for loop check for current char != '\0'
    so no need to call strlen(),
    so no need to check for length,
    so no need to continually adjust the length