如何从 C 字符串中删除 'garbage input'?

How can I remove 'garbage input' from a C string?

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

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

我该怎么做才能解决这个问题?我觉得解决方案就在我眼皮底下,但我似乎找不到它。

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

另请记住,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--;
        }
    }
}

这是边走边删除的经典问题:在 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] = '[=10=]';

问题是您在删除字符后没有减少 i 的值。

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

让我们看看你的 string。输入后变成

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

现在,让我们跳过几次迭代,转到删除索引 3 处的 space 的部分。删除它后,您的字符串将看起来像

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

但是,您继续 i 的下一个索引,即 i = 4i = 3 处的 space 保持原样。而经过这次迭代,就变成了

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

如您所见,space 留在那里。这就是导致问题的原因。

因此,您需要递减 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]='[=13=]';
    printf("%s",string);
}

我也加了

    string[i]='[=14=]';

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

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 != '[=10=]'
    so no need to call strlen(),
    so no need to check for length,
    so no need to continually adjust the length