我的 squeeze() 函数有什么问题?

What is wrong with my squeeze() function?

现在我正在努力完成“C 程序设计语言”一书,天哪,这是一次令人羞愧的经历。现在我正在做书中的练习 2-3,但我无法弄清楚我的 squeeze() 函数哪里出了问题。该函数的目的是删除字符串 1 中在字符串 2 中找到的任何字符。现在我的所有函数所做的就是删除 string1 的第一个字符(如果它在 string2 中找到),然后在这之后表现得很奇怪。我查看了答题簿和给出的答案让我很困惑。很难理解正在做的事情,所以我没有遵循答案书中的逻辑,而是想知道我自己的代码哪里出错了……下面是代码:

/* Write an alternate version of squeeze(s1, s2) that deletes each char in s1 that matches
*  any char in string s2 */

/* Here's a reference for squeeze(s1, s2):
*  squeeze: delete all c from s
*
*  void squeeze(char s[], int c)
*  {
*   int i, j;
*
*   for(i = j = 0; s[i] != '[=10=]'; i++)
*       if(s[i] != c)
*           s[j++] = s[i];
*   s[j] = '[=10=]';
*  }
*******************************************/

#include <stdio.h>
#include <string.h>
#define MAX_INPUT 100

void squeeze(char string1[], char string2[]);

int main()
{
    int c, i = 0, j = 0;
    char s1[MAX_INPUT + 2], s2[MAX_INPUT + 2];
    printf("\nPlease enter string1\n");
    while((c = getchar()) != '\n')
    {
        s1[i] = c;
        i++;
    }
    s1[i] = '[=10=]';
    /* test to see if above worked */
    printf("\ns1 = %s\n", s1);

        printf("\nPlease enter string2\n");
        while((c = getchar()) != '\n')
        {
                s2[j] = c;
                j++;
        }
    s2[j] = '[=10=]';
        /* test to see if above worked */
        printf("\ns2 = %s\n", s2);

    printf("\nWe will now apply the squeeze function to remove any chars");
    printf(" found in string2 from string1\n");
    squeeze(s1, s2);
    printf("Squeeze(s1, s2) = %s\n", s1);
}

void squeeze(char s1[], char s2[])
{
    int i = 0, j = 1;   /* for counters */
    char temp;  /* for char comparison */
    temp = s2[0];

    while(s2[i] != '[=10=]')
    {
        if(s1[i] == temp)
        {
            s1[i] = s1[i+1];
            j++;
        }
        else
        {
            j++;
        }
        temp = s2[j];
        i++;
    }
    s1[i+1] = '[=10=]';

}

我的输出如下:

Please enter string1
hello

s1 = hello

Please enter string2
help

s2 = help

We will now apply the squeeze function to remove any chars found in string2 from string1
Squeeze(s1, s2) = eello

谁能看出我的逻辑有什么问题?从答案书中我猜我需要第三个计数器,k,在某个地方,但我看不出我编程函数的方式的原因..我知道我遗漏了一些东西!非常感谢大家:)

回答(谢谢弗拉德!):

void squeeze(char s1[], char s2[])
{
        int i = 0, j = 0;

        do
        {
                int k = 0;
                while(s2[k] != '[=12=]' && s2[k] != s1[i])
                ++k;

                if (s2[k] == '[=12=]')
                {
                        if ( j != i)
                                s1[j] = s1[i];
                ++j;
                }
        } while (s1[i++] != '[=12=]');

}

你的函数没有意义。

while循环根据s2的长度执行

while(s2[i] != '[=10=]')

但是您使用相同的索引 i 来检查字符串 s1.

if(s1[i] == temp)

但是字符串 s1 通常可以比字符串 s2 更短或更大。所以函数可以调用未定义的行为。

s1 中的每个字符也应在字符串 s2 中从头开始检查。

函数可以声明和定义(不使用标准 C 字符串函数),如下面的演示程序所示。

#include <stdio.h>

char * squeeze( char s1[], const char s2[] )
{
    if ( *s2 != '[=12=]' )
    {
        size_t i = 0;
        size_t j = 0;

        do
        {
            size_t k = 0;
            while ( s2[k] != '[=12=]' && s2[k] != s1[i] ) ++k;
            
            if ( s2[k] == '[=12=]' )
            {
                if ( j != i ) s1[j] = s1[i];
                ++j;
            }
        } while ( s1[i++] != '[=12=]' );
    }
    
    return s1;
}

int main(void) 
{
    char s1[] = "Hello World!"; 
    const char *s2 = "aeiou";
    
    puts( s1 );
    puts( squeeze( s1, s2 ) );
    
    return 0;
}

程序输出为

Hello World!
Hll Wrld!

我使用 tmp 缓冲区来复制不包含字符。比较简单,大家可以看看

void squeeze(char s1[], char s2[]){
    int i, j, k = 0;
    char* tmp;
    
    // tmp buffer initial size can be maximum s1 length
    tmp = malloc(strlen(s1) + 1);
    
    // loop until s1 character is null
    i = 0;
    while(s1[i] != '[=10=]'){
        // loop until character is found or to the end.
        // break if s2 reached to the end or s1[i] == s2[j]
        j = 0;
        while(s2[j] != '[=10=]' && s2[j] != s1[i]){
            j++;
        }
        
        // if j reached to the end, add into tmp buffer
        if(s2[j] == '[=10=]'){
            // set current character
            tmp[k] = s1[i];
            // increase index
            k++;
        } else {
            printf("Found %c\n", s1[i]);
        }
        
        // next character
        i++;
    }
    // last character must be null
    tmp[k] = '[=10=]';
    
    // tmp copy to s1
    strcpy(s1, tmp);
    
    // free tmp buffer
    free(tmp);
}