这段代码中的 for 循环有什么问题?

What's wrong with the for loops in this code?

我正在阅读 The C Programming Language 一书,我无法弄清楚我的代码在这个练习中有什么问题。

该练习要求您实现 squeeze() 函数的一个版本,删除 s1 中与字符串 s2 中的任何字符匹配的每个字符。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

int main ()
{
    char s1[100];
    char s2[100];
    int c;
    int i;
    int j;
    int flag=0;
    char s3[100];

    printf("TYPE THE FIRST STRING\n");
    for(i=0;s1[i-1]!='\n';i++)
    {
        scanf("%c", &s1[i]);
    }


    printf("\n\nTYPE THE SECOND STRING\n");
    for(i=0;s2[i-1]!='\n';i++)
    {
        scanf("%c", &s2[i]);
    }


    for(i=0;s1[i]!='\n';i++)/*sets the "i" character of s1 to be compared*/
    {
        for(j=0;s2[j]!='\n';j++)/*compares the "i" character in s1 with
        {                         every character on s2*/
            if(s1[i]==s2[j])
            {
                flag=1;/*sets the flag variable to one if it finds 2 equal 
                break;   characters and stops the loop*/
            }
        }
        if(flag!=1)/*if it have not found a matching pair of chacters,
        {            this part copies the s1 char to s3*/
            s3[i]=s1[i];
        }
        flag=0;
        printf("\n");
    }
    printf("\n\n%s",s3);

    return 0;
}

问题是,如果我在 s1 中输入“test”,在 s2 中输入“second”,它只会打印“t”。一旦找到匹配对,它就会停止。 flag 没有正常工作?我在这个练习中花费了 2 小时以上,无法解决它。

for (i = 0; s1[i-1] != '\n'; i++)

此循环第一次迭代的谓词将访问超出范围的 s1[-1],然后调用 undefined behavior。涉及 s2 的循环有同样的问题。

此外,您的字符串永远不会以 NUL 终止,并且它们的缓冲区很容易通过 scanf.

溢出。

您有多个跨越多行的 /* */ 注释实例,这会注释掉您的代码部分:两个开头 {break.

即使在通过评论解决问题后

if (flag != 1) {
    s3[i] = s1[i];
}

将在您的最终字符串中留下漏洞。 s3 需要一个单独的索引计数器,它只会随着字符串长度的增加而增加。

一个简单的例子,我们初始化我们的缓冲区(特别是这个 NUL 终止 s3),并使用 fgets 来限制我们的输入。

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char s1[100] = { 0 },
         s2[100] = { 0 },
         s3[100] = { 0 };
    int flag = 0;
    size_t k = 0;

    if (
        !fgets(s1, sizeof s1, stdin) ||
        !fgets(s2, sizeof s2, stdin)
    ) {
        fprintf(stderr, "Could not read input.\n");
        return EXIT_FAILURE;
    }

    for (size_t i = 0; s1[i] && s1[i] != '\n'; i++) {
        for (size_t j = 0; s2[j] && s2[j] != '\n'; j++) {
            if (s1[i] == s2[j]) {
                flag = 1;
                break;
            }
        }

        if (flag == 0)
            s3[k++] = s1[i];
        flag = 0;
    }

    printf("%s\n", s3);
}

或者,使用 strchr,我们可以编写一个整洁的函数:

#include <string.h>

void squeeze(char *dest, const char *source, const char *filter) {
    for (; *source; source++)
        if (!strchr(filter, *source))
            *dest++ = *source;

    *dest = '[=13=]';
}