K& R C编程语言 - 练习2-2:检查我的工作?

时间:2014-10-30 05:05:55

标签: c kernighan-and-ritchie

我并没有完全挣扎于这个练习(神圣的废话,在1-20到1-24之后...),但我想知道我的解决方案是否有问题。练习要求您编写一个等效于以下内容的循环:

for (i=0; i<lim-1 && (c=getchar()) != '\n' && c!= EOF; ++i)
    s[i] = c;

不使用||或者&amp;&amp;我选择不使用之前没有介绍过的任何语言功能,我正在认真考虑每个练习都放在原处,因为用户的意图是使用提供的概念。因此,我想出了这个:

for (i=0; (i<lim-1) == ((c=getchar()) != EOF) == (c != '\n'); ++i)
    s[i] = c;

有一个很多更漂亮的解决方案,涉及一个简单的if / else if类型条件,但我想利用这一部分讨论的表达式具有基于其真实性或虚假性的数值等等。问题是,我的解决方案不在我通常检查有效运动解决方案的任何网站中,所以尽管看起来效果相同。我想知道我做的方式是否有什么问题,除了它丑陋之外?功能在某些方面有所不同吗?

3 个答案:

答案 0 :(得分:1)

除此之外,它是未定义的行为,因为它取决于评估顺序。 &&||肯定会首先评估他们的左操作数,但==没有。因此,无法保证第二次使用c将引用新值而不是前一个循环中的值(或第一次使用的单位化值。)

&&的短路评估是原始循环语义的重要部分。 &&如果第一个操作数为false则不评估其第二个操作数的事实意味着原始循环保证调用getchar不超过lim-1次。在没有&&的情况下重写,getchar将在i到达lim-1时被称为额外时间,然后将读取的字符(如果有的话)放入位桶中,这意味着下次尝试读取输入时会丢失它。

最后,a == ba && b不同。它适用于(c != EOF) == (c != '\n'),因为这两个条件都不可能是假的 - 这是一个有趣的观察 - 但它不能替代(i < lim-1) && ...

答案 1 :(得分:0)

您的代码可能存在未定义的行为。在GCC和Clang下编译它会给我类似的警告:

test.cpp:14:31: warning: unsequenced modification and access to 'c'
      [-Wunsequenced]
    for (i=0; (i<lim-1) == ((c=getchar()) != EOF) == (c != '\n'); ++i)

阅读sequence points in cc-faq question 3.8我不相信==是一个序列点,但&&是。#include <stdio.h> int main() { int lim = 512; int a = 1; char b = EOF; char c = '\n'; if ((a < lim) == (b != EOF) == (c != '\n')) { printf("True."); } else { printf("False."); } } 。其次,我不认为你的代码符合你的想法。如果我们采用以下示例:

while(i < lim-1) {
    c = getchar();
    if (c == '\n')
        lim = 0;    /* We haven't encountered breaks yet. */
    else if (c == EOF)
        lim = 0;
    else
        s[i++] = c;
}

输出“True”。所以它实际上是错误的。我建议尽量避免编写聪明的代码,而是坚持你提到的“if / else”solution

{{1}}

答案 2 :(得分:0)

// with the use of break statement and no else statements

for( i=0; i<(lim-1); ++i )
{
    c = getchar();
    if( '\n' == c ) break;
    if( EOF  == c ) break;
    s[i] = c;
}