代码之家  ›  专栏  ›  技术社区  ›  Haru Hoshizora

为什么一个整数的位置没有改变,但值却不同

  •  0
  • Haru Hoshizora  · 技术社区  · 6 月前

    我试图解决一个编码问题,上面写着:

    编写的替代版本 squeeze(s1, s2) 这将删除中的每个字符 s1 它匹配字符串中的任何字符 s2 .".

    我确实编写了代码,工作版本是。

    #include <stdio.h>
    
    char s1a[1001], s2a[1001];
    
    void squeeze() {
        int i, j, k;
        extern char s1a[], s2a[];
    
        for (i = 0; s2a[i] != '\0'; i++) {
            for (k = j = 0; s1a[j] != '\0'; j++) {
                if (s1a[j] != s2a[i]) s1a[k++] = s1a[j];
            }
            s1a[k] = '\0';
        }
        printf("%d/n", k); /*k's value*/
    }
    
    int main() {
        int c, s1 = 0, i = 0, j = 0;
        extern char s1a[], s2a[];
    
        while ((c = getchar()) != EOF && i < 1000) {
            if (c != '\n' && s1 == 0) {
                s1a[i++] = c;
            }
            else if (c == '\n' && s1 == 0) {
                s1a[i] = '\0';
                i = 0;
                s1++;
            }
            else if (c != '\n' && s1 == 1) {
                s2a[j++] = c;
            }
            else if (c == '\n' && s1 == 1) {
                s2a[j] = '\0';
                j = 0;
                squeeze();
                printf("%s\n", s1a);
                s1a[0] = '\0';
                s2a[0] = '\0';
                s1 = 0;
            }
        }
    }
    

    我确实输入了“hello”。

    它工作得很好,但这段代码中的第13行在之前的for循环之外,打印k(在第15行)在那里,所以当时它将k打印为5,当我在现在添加字符串终止符时,它将k显示为1。它工作得很好,可以打印“o”,但在打印“ooooo”之前。

    编辑:据我所知,问题在于s1a末尾有5个o,所以在收缩后不终止时k为5。

    2 回复  |  直到 6 月前
        1
  •  1
  •   Adrian McCarthy    6 月前

    这个问题很令人困惑,因为你只显示了工作代码。你好像在问为什么 k 当你终止时,给出了不同的答案 s1a 两个循环完成后的字符串与每次外循环结束后终止它的正确时间相比。

    原因是因为内部循环期望 s1a 以当前大小终止。

    如果 s1a 曾经是{ h , e , l , 字母 l(英语字母表中的第十二个字母) , o , \0 },你删除了 'h' 但没有写一个新的终结者,你留下了{ e , 字母 l(英语字母表中的第十二个字母) , 字母 l(英语字母表中的第十二个字母) , o , o , \0 }. 当你写一个新的终结者时,得到{ e , 字母 l(英语字母表中的第十二个字母) , 字母 l(英语字母表中的第十二个字母) , o , \0 , \0 }.

    因此,每次扫描以查看是否有字母的实例时,您只扫描字符串中仍然重要的部分,并且 k 永远无法找到最后剩下的垃圾的索引。

        2
  •  1
  •   Chris    6 月前

    作为额外的(长)注释,您的代码具有O(m*n)的运行时复杂性( m 即第一串的长度,以及 n 第二个的长度)。对于长字符串,可以通过为第二个列表创建一个查找表来检查第二个字符串中的字符是否为O(1)操作而不是O(n)来改进这一点。

    #include <stdbool.h>
    #include <string.h>
    
    void squeeze(char *s1, char *s2) {
        bool table[256] = {0};
    
        for (char *ch = s2; *ch; ch++) {
            table[(unsigned char)*ch] = true;
        }
    
        size_t j = 0;
        
        for (char *ch = s1; *ch; ch++) {
            if (!table[(unsigned char)*ch]) {
                s1[j++] = *ch;
            }
        }
    
        s1[j] = '\0';
    }