简体   繁体   English

在经典书籍“C编程语言”的第1.9章中的示例代码中是否有错误?

[英]Is there an error in the example code in chapter 1.9 in the classic book “The C Programming Language”?

In the Chapter 1.9 in the classic book about C language "The C Programming Language" by Brian & Dennis, there is a bunk of code about a function 'getline' which is used to copy the next line of input text into a char type string and check the overflow. 在Brian&Dennis关于C语言“The C Programming Language”的经典着作的第1.9章中,有一个关于函数'getline'的代码,用于将下一行输入文本复制到char类型字符串中并检查溢出。 I quote the code below: 我引用下面的代码:

int getline(char line[], int maxline);
int getline(char s[], int limit)
{
    int c,i;
    for (i=0; i<limit-1 && (c=getchar())!=EOF && c!='\n'; ++i) /* ** */
        s[i]=c;
    if (c == '\n') {
        s[i]=c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

Here is the problem: the parameter 'limit' is the max length of the line, so the array s[] can only contain a collection of elements from s[0] to s[limit-1]. 这是问题:参数'limit'是行的最大长度,因此数组s []只能包含从s [0]到s [limit-1]的元素集合。 If the last character for the variable c to getchar() is '\\n' and this character's index is limit-1, then the judgement part in the 'for' loop will fail because of 'i==limit-1' but not 'c!='\\n' (according to the sequence from left to right). 如果变量c到getchar()的最后一个字符是'\\ n'并且此字符的索引是limit-1,那么'for'循环中的判断部分将因'i == limit-1'而失败但不会'c!='\\ n'(根据从左到右的顺序)。 Next, if clause will work, because of 'c=='\\n'', then s[limit-1]=c, then ++i will set the value of i into limit. 接下来,if子句将起作用,因为'c =='\\ n'',然后s [limit-1] = c,那么++ i将i的值设置为limit。 s[i]='\\0' will overflow, because s[limit] overrun the limit of string. s [i] ='\\ 0'将溢出,因为s [limit]超出了字符串的限制。 Is my analysis right or not? 我的分析是否合适? Thanks for any helpful answers. 谢谢你的任何有用的答案。

Your analysis is wrong. 你的分析是错误的。 If i == limit-1 , the loop breaks without reading into c , due to short-circuit evaluation. 如果i == limit-1 ,由于短路评估,循环中断而不读入c So, you never enter if (c == '\\n') . 所以,你永远不要输入if (c == '\\n') i remains limit-1 and there is no overflow. i仍然是limit-1并且没有溢出。

Conceptually, you can think of the loop condition like this: "If i is lower than limit-1 , read a character, and if it's not EOF or newline, enter the loop body." 从概念上讲,你可以想到这样的循环条件:“如果i低于limit-1 ,则读取一个字符,如果它不是EOF或换行符,则进入循环体。” Thus, if i is limit-1 , you never read. 因此,如果ilimit-1 ,你永远不会读。

There are two short circuited eval-points points in this code. 此代码中有两个短路的eval-points点。 See below 见下文

for (i=0; i<limit-1 && (c=getchar())!=EOF && c!='\n'; ++i)
//        (   A   )    (        B        )   (  C  )

All are separated with a chain of && . 所有都用&&链分开。 When this code executes, all three must be true or the loop will break. 执行此代码时,所有三个必须为true或循环将中断。 But with short circuit eval the following happens: 但随着短路评估,会发生以下情况:

  • If A is false, the condition is false, neither B nor C are evaluated. 如果A为假,则条件为假, 评估B和C.
  • Else if B is false, the condition is false and C is not evaluated. 否则,如果B为假,则条件为假,并且不评估C.
  • Else if C is false, the condition is false. 否则,如果C为假,则条件为假。

Therefore... 因此...

  • if i<limit-1 is false, neither the getchar() and comparison against EOF, nor the comparison against '\\n' are performed. 如果i<limit-1为false, 则不执行getchar()和与EOF的比较,也不执行与'\\n'的比较。
  • else if (c=getchar())!=EOF is false, then the comparison against '\\n' is not performed. else if (c=getchar())!=EOF为false,则不执行与'\\n'的比较。
  • else the comparison against '\\n' is performed. 否则执行与'\\n'的比较。

i hope that made sense. 我希望这是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM