【问题标题】:Do not understand this Infinite While loop不明白这个 Infinite While 循环
【发布时间】:2018-08-16 03:44:52
【问题描述】:

有人可以用外行的话向我解释一下这段sn-p代码是怎么回事吗?我知道这是一个用于获取第一个字符然后丢弃剩余输入的函数,但我对最后一个 while 循环感到困惑。当我用谷歌搜索它时,我发现非常复杂的解释超出了我的想象。有一种解释是有道理的,但它是一个汇编代码解释,处理输入在内存中的堆栈上,然后我的豌豆大脑麻木了。 ???

int get_First(void)
{
     int ch, garbage;

     do
     {
          ch = getchar();
     }while(isspace(ch));

    while((garbage = getchar()) != '\n' && garbage != EOF)
                ;
    return ch;
}

【问题讨论】:

    标签: c while-loop infinite-loop do-while


    【解决方案1】:

    第二个while 循环继续读取字符,直到它读取换行符 (\n) 或到达文件末尾 (EOF)。

    【讨论】:

      【解决方案2】:

      您的第二个 while 循环没有任何主体,它将不断从标准输入中读取。如果您按Enter 这是一个换行符,它将中断,因为它将不断检查输入的值是否不是换行符而不是文件结尾字符。

      【讨论】:

        【解决方案3】:

        此函数首先返回输入中的空格,而不是空格。然后忽略所有内容,直到行尾或文件结尾。它写得很糟糕,因为如果行中没有非空格,它将读取下一行,或者如果 EOF 后面的第一个字符会导致错误。

        【讨论】:

        • ¿ “写得很糟糕”的评论对我来说似乎并不准确。如果输入中的下一个字符是空格(包括换行符),它将被读取,直到 ch 包含 EOF 或不是空格的字符。如果空格后面的字符是EOF,则返回EOF;吞噬循环将立即检测到 EOF — 假设 getchar() 在报告一次后继续返回 EOF。 (当输入来自终端时,Linux 上的某些版本的 GlibC 似乎已损坏,但这是一个不同的错误,而不是问题代码中的错误。)
        • 我忘记了 \n 也是一个空格。但正如我理解这段代码的想法 - 它应该首先返回而不是行中的空格。这个将返回只会返回第一个不是空白字符,它可以是文件中的任何位置。
        • 职位描述中的代码在哪里说“行中的第一个非空白字符”?它返回“第一个非空白字符”句点——无论它必须读取多少行才能找到它。您的假设要求是一个合理的替代规范;它只是不是代码实现的,问题是代码实现了什么,而不是它应该实现什么。
        【解决方案4】:
        while((garbage = getchar()) != '\n' && garbage != EOF) ;

        基本上是一个非常压缩的版本:

        garbage = getchar();
        while ( garbage != '\n' && garbage != EOF )
          garbage = getchar();
        

        基本上,读取并丢弃标准输入中的任何字符,直到我们看到换行符或文件结束信号。

        C 条件表达式可以包含赋值:

        while ( x = foo() ) // assign result of foo() to x, loop if non-zero
        {
          // do something
        }
        

        由于 很多 人在意为 == 时不小心输入了 =,因此大多数编译器都会警告条件表达式中的赋值表达式除非该表达式是用括号括起来:

        while ( (x = foo()) ) // assign result of foo() to x, loop if non-zero
        {
          // do something
        }
        

        这告诉编译器“是的,我打算foo()的结果分配给x并根据结果循环,闭嘴。”

        C 中的赋值表达式可以作为更大表达式的一部分出现。赋值表达式的结果是经过任何适当转换后存储在目标中的值。因此,赋值表达式的结果也可以与其他内容进行比较,因此您可以编写

        while ( (x = foo()) > 0 ) // assign result of foo() to x, loop while result is positive
        {
          // do something
        }
        

        您可以进行多重比较:

        while ( (x = foo()) > 0 && x < 100 )
        {
          // do something
        }
        

        &amp;&amp; 运算符强制从左到右评估 - (x = foo()) &gt; 0 将首先评估,为 x 分配一个新值作为副作用。如果结果非零(x 为正),则将评估 x &lt; 100。同样,这是一种简洁的写作方式:

        x = foo();
        
        if ( x > 0 && x < 100 )
        {
          // do something
          x = foo();
        }
        

        【讨论】:

          【解决方案5】:

          while 循环不是无限循环:它的主体为空,但会继续执行其条件,直到返回零值。

          如果&amp;&amp; 的第一个操作数的计算结果为0 或第二个操作数的计算结果为0,则条件将计算为0

          第一个操作数(garbage = getchar()) != '\n 首先从标准输入读取一个字节并将其存储到garbage 并与换行符'\n' 进行比较。如果读取的字节确实是换行符,则循环停止,否则将garbage(读取的字节)与EOF进行比较,如果流位于文件末尾,则循环停止,其中getchar的返回值为特殊值EOF

          这个while 循环的目的只是消耗当前输入行的其余部分。但请注意,该函数可能会读取一行或多行,直到找到非空白字符为止。

          【讨论】:

          • 第一个循环只会读取多行,如果它们都是空的。
          • @Barmar:是的,但是 empty 不够精确:第一个循环将使用不包含字符或仅包含空白字符的行。换行符 '\n' 是一个空白字符。
          • 由于此函数的目的似乎是返回第一个非空白字符,然后跳到包含该字符的行尾,因此跳过全白行似乎是合适的。跨度>
          猜你喜欢
          • 1970-01-01
          • 2020-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-27
          • 2015-03-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多