【问题标题】:I don't understand how how this code works我不明白这段代码是如何工作的
【发布时间】:2021-11-03 07:46:30
【问题描述】:

我在 K&R Book 中做练习 1-9,在尝试寻找解决方案时遇到了以下代码:

int main()
{
    int c;
    while ((c = getchar()) != EOF) {
        if (c == ' ') {
            while ((c = getchar()) == ' ');
            putchar(' ');
            if (c == EOF) break;
        }
        putchar(c);
    }
}

即使我输入了一个字母,为什么第一个if 语句仍然有效。据我了解,只有当我输入的字符是空格时才会执行? 顺便说一句,练习是让程序将多个连续的空格替换为一个。

【问题讨论】:

  • 现在,我认为写while ((c = getchar()) == ' ') { } 而不是... ; 更常见,以表明循环没有主体,只执行其条件的副作用。
  • “第一个 if 语句起作用”是什么意思?我的意思是:你对“工作”的理解是什么。该语句,特别是它的条件将始终在外部 while 循环中进行评估。
  • "为什么即使我输入了一个字母,第一个 if 语句也能工作。" “工作”是什么意思?你认为应该发生什么?你认为到底发生了什么?
  • 这能回答你的问题吗? Clarifying K&R exercise 1-9
  • @KarlKnechtel 我认为它的工作原理首先是需要用户输入,然后如果我的输入包含多个空格,它将替换为一个空格。如果我的输入有字母,为什么if (c == ' ') 会起作用?我认为 c 等于我的输入。如果我输入 abc d,为什么 if 语句仍然被执行?不是只有输入一个空格才有效吗?

标签: c while-loop char whitespace getchar


【解决方案1】:

这个程序打印除空白字符''之外的任何输入字符,直到用户中断输入。

在这个while循环中

while ((c = getchar()) == ' ');

读取每个空白字符但不输出。并且在循环之后只输出一个空白字符

putchar(' ');

即程序删除相邻的空白字符,在用户输入的字符序列中只留下一个空白字符。

【讨论】:

    【解决方案2】:

    我已经格式化并注释了代码。希望这会有所帮助。代码实际上隐藏了所有 stdin 内的一系列空格合并为一个空格:

     "123    456 a  b c  " -> "123 456 a b c "
    

    代码:

    
    int main() {
        int c;
     
        /* we read stdin character after character */
        while ((c = getchar()) != EOF) {
            /* if we have read space */   
            if (c == ' ') {
                /* we skip ALL spaces */
                while ((c = getchar()) == ' ')
                    ; /* skipping ALL spaces: we do nothing */
    
                /* and then we print just ONE space instead of many skipped */
                putchar(' ');
    
                /* if we at the end of stdin, we have nothing more to print */
                if (c == EOF) 
                    break;
            }
    
            /* we print every non space character */
            putchar(c);
        }
    }
    

    【讨论】:

    • 我想澄清一下,getchar() 是否一次读取一个字母或数字?
    • @airismything: getchar() 从标准输入流(终端或其他来源)读取 byte。 byte 是输入的单个字符,或者在非 ASCII 字符的情况下是其表示的单个字节。如果你输入一个数字,每个数字都会按顺序返回。
    【解决方案3】:

    只要输入流没有结束,它就会循环(EOF = End Of File)。

    如果输入的字符是空格,则忽略后面的空格,之后只打印一个空格。

    否则会输出输入的字符。

    【讨论】:

      【解决方案4】:
      int main()
      {
          int c;
          while ((c = getchar()) != EOF) {
      

      对于输入的每个字符...

              if (c == ' ') {
      

      ...如果字符是空格...

                  while ((c = getchar()) == ' ');
      

      ...这个循环跳过第一个之后的所有空格...见右边的分号,它使它读取字符,检查它是否是一个空格,对它不做任何事情。 这样写是一件非常棘手的事情,因为通常认为循环体将是下面的下一个语句,而它根本没有循环体。在while 循环之后,您可以假设让您进入循环的条件为假,因此我们有一些正确的断言:在c 中肯定没有存储空间(它仍然可以是EOF,即不是字符,所以我们需要在打印之前对其进行测试,然后在下一条语句之后进行测试)

                  putchar(' ');
      

      ... 在循环之后,仅输出一个空格,对应于您在问题中提到的第一个 if 语句中测试的那个。认为c 不是空格字符(所以我们不能putchar(c);),因为我们跳过所有空格直到没有空格。它仍然可以是EOF 指标,如下所示。

                  if (c == EOF) break;
      

      如果字符不是空格,它只能是EOF 指示符。在这种情况下,我们需要跳出循环,所以我们不打印它,在下一条语句中......

              }
              putchar(c);
      

      ...因为我们一直在读取c 中的字符,直到我们得到一个非空格(也不是EOF 指示符,因为在这种情况下我们退出了上面的循环),所以无论如何我们都需要打印那个字符。这个putchar(c); 语句将始终打印一个非空格字符。它不在if 语句中,因为必须对所有最初为非空格的字符和一系列空格后的字符执行此操作。

          }
      

      ...如上,我们可以假设循环的测试条件为假,所以这里我们可以确保c得到了EOF(但只是因为循环内的break语句也发生在c == EOF)。

      }
      

      瞧瞧!!!

      注意

      在尝试寻找解决方案时,我遇到了这段代码:

      最后一点,如果您发布您尝试编写解决方案的尝试,而不是通过搜索找到已经制定的解决方案,这对您来说会更好。你会学到更多关于编程的知识,而不是谷歌搜索,恕我直言,这不是你的主要兴趣。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-01
        • 2017-06-14
        • 1970-01-01
        • 2020-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-14
        相关资源
        最近更新 更多