C 编程语言练习 2-4 : I dont understand the answer

标签 c loops

我在网络上看到了一个答案,但不明白它如何与该循环一起工作。为什么我的不起作用。问题是:编写 squeeze(s1,s2) 的替代版本,删除字符串 s1 中与中的任何字符匹配的每个字符字符串s2。 我认为它应该检查 s1 中的每个字符与 s2 中的每个字符不匹配。就像您在 s1 中看到一个字符一样,您循环遍历 s2 以查看它是否与 s1 中的该字符匹配,然后继续处理中的下一个字符s1。因此,外部循环用于 s1,内部循环用于 s2。 这是他的代码,我将其放在整个代码中进行测试。他的输出是正确的。他的代码就是函数部分。我不明白的是为什么他将 s2 放在外部循环中并且它甚至可以工作。

#include <string.h>
#include <stdio.h>

void squeeze2(char s[], char t[]);

void squeeze2(char s[], char t[]) {
    int i, j, k;
    for (k = 0; t[k] != '\0'; k++) {
        for (i = j = 0; s[i] != '\0'; i++)
            if (s[i] != t[k])
                s[j++] = s[i];
        s[j] = '\0';
    }
}

int main() {
    char s1[] = "hello meow meow princess";
    char s2[] = { 'a', 'e', 'm' };
    squeeze2(s1, s2);
    int i = 0;
    while (s1[i] != '\0') {
        printf("%c", s1[i]);
        i++;
    }
}

这是我的。我将S2放入内部代码中,它的输出是hello meow meow princess..

#include <string.h>
#include <stdio.h>

void squeeze(char s1[],char s2[]);

int main() {
    char s1[] = "hello meow meow princess";
    char s2[] = { 'a', 'e', 'm' };
    squeeze(s1, s2);
    int l;
    for (l = 0; l < strlen(s1); l++)
        printf("%c", s1[l]);
}

void squeeze(char s1[], char s2[]) {
    int i = 0;
    int k = 0;
    while (s1[i] != '\0')
        for (int j = 0; s2[j] != '\0'; j++) {
            if (s1[i] != s2[j]) {
                s1[k] = s1[i];
                k++;
            }
            i++;
       }
}

最佳答案

只要您调整实际代码,无论您首先在 s1 上循环,然后在 s2 上循环,还是反过来,实际上并不重要。

两个版本都存在问题:main 中的字符串 s2 不是 null 终止的(它不是 C 字符串),因此 中的行为>squeeze 未定义,因为第二个字符串中的字符将在数组末尾之外取消引用。

您的版本还有更多问题:

  • 如果在 s2 中找到一个或多个字符,则不要以 null 终止 s1,以防它被缩短。
  • 该算法已被破坏:您可以多次复制 s1 中的每个字符,只要您在 s2 中发现与它不匹配的字符即可。

您应该通过调用 strchr(s2, s1[i]) 或手动枚举来验证该字符是否存在于 s2 中。

这是一个更正和简化的版本:

#include <string.h>
#include <stdio.h>

void squeeze(char *s1, const char *s2);

int main(void) {
    char s1[] = "hello meow meow princess";
    char s2[] = { 'a', 'e', 'm', '\0' };
    squeeze(s1, s2);
    printf("%s\n", s1);
    return 0;
}

void squeeze(char *s1, const char *s2) {
    int i, j, k;
    for (i = k = 0; s1[i] != '\0'; i++) {
        for (j = 0; s2[j] != '\0'; j++) {
            if (s1[i] == s2[j])
                break;
        }
        if (s2[j] == '\0') {  // character was not found in s2
            s1[k++] = s1[i];
        }
    }
    s1[k] = '\0'; // null terminate s1 of it was shortened
}

注释:

  • ifelseforwhile 之后始终使用大括号表示重要语句并做...而

  • 优先使用 for 而不是 while:对索引变量的初始化、增量和测试进行分组可以提高可读性并减少错误。

  • 避免命名变量l:使用等宽字体,它看起来与1太相似。

  • const 限定函数未修改的字符串参数。

关于C 编程语言练习 2-4 : I dont understand the answer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40442736/

相关文章:

使用 WSAWaitforMultipleEvents() 的非阻塞套接字函数的概念

android - 使用循环将按钮添加到android布局

java - Scanner 类 hasNextLine 无限循环

javascript - 将数组推送到一个数组,然后循环遍历新数组

c - 使用 C 语言的 GNU 科学库进行线性拟合

c - 使用 atoi 无法接受 char 类型 - 有什么办法解决这个问题吗?

c - Signed Short (Signed Int16) 乘法解释

c - 我在使用 strcat 时遇到段错误。请告诉我出了什么问题

java - 嵌套循环还是方法?

c# - Scala 最短相当于 c# LINQ