0
int getline(char s[], int lim) 
{
    int c, i;

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

return i;
}

这个例子来自 K&R 关于 C 的书,第 1.9 章关于数组。我不明白的是为什么我们必须接受++i内部if声明?在外面写应该做同样的工作。

    if(c=='\n')
        s[i] = c;
    ++i;
    s[i] = '\0'
return 0;
}

如果包含i程序按预期工作,但在第二种情况下(我认为它应该做同样的工作,这就是我编辑该部分的原因)它没有。我通过调试器运行它并观察i在这两种情况下都正确计算并返回。但是,如果不包含,程序仍然无法运行++i。我没有从printf语句中得到我的打印,而且 Ctrl+D 在终端或 XTerm 中不起作用(彻底的 CodeBlocks)我不知道为什么。请问有什么提示吗?我错过了一些合乎逻辑的步骤吗?这是一个完整的代码:

//Program that reads lines and prints the longest
/*----------------------------------------------------------------------------*/

#include <stdio.h>
#define MAXLINE 1000

int getline(char currentline[], int maxlinelenght);
void copy(char saveto[], char copyfrom[]);
/*----------------------------------------------------------------------------*/

int main(void)
{
    int len, max;
    char line[MAXLINE], longest[MAXLINE];

    max = 0;
    while( (len = getline(line, MAXLINE)) > 0 )
        if(len > max){
            max = len;
            copy(longest, line);
        }
    if(max > 0)
        printf("StrLength:%d\nString:%s", max, longest);

return 0;
}
/*----------------------------------------------------------------------------*/

int getline(char s[], int lim) 
{
    int c, i;

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

return i;
}
/*----------------------------------------------------------------------------*/

void copy(char to[], char from[])
{
    int i;

    i = 0;
    while( (to[i]=from[i]) != '\0')
        ++i;
}
/*----------------------------------------------------------------------------*/
4

5 回答 5

2

该行
if(c == '\n') 相当于
if(c != EOF)

这是否有助于解释为什么会发生拥抱?

于 2013-04-22T03:43:53.890 回答
1

指定的索引i是当该行没有更多输入时应放置终止空值的位置。索引之前的位置i包含字符串中的最后一个有效字符。

请记住,读取数据的循环可能会因读取字符stdin以外的原因而终止。\n

如果你有这个构造:

if(c=='\n')
    s[i] = c;
++i;

然后,如果从中读取的最后一个字符stdin不是换行符,您将索引加一,而无需将任何内容写入i. 您将有效地在结果中添加一个未指定的字符。

更糟糕的是(?),如果for循环由于i<lim-1条件而终止,您最终会在数组的指定结尾之后写入终止的空字符,从而导致未定义的行为(内存损坏)。

于 2013-04-22T06:22:08.163 回答
1

那里有一个逻辑:

if(c=='\n'){
    s[i] = c;
    ++i;
}

这意味着只有当您阅读额外的换行符时,您才需要再增加i一个以保留\0字符空间。如果你放在块++iif。这意味着即使没有,它也总是会i 增加,在这种情况下,由于已经在 中增加,因此已经有 的空间,因此,再次将是错误的。您可以打印 的值并查看它是如何工作的。1newline inputifor loop\0++ii

于 2013-04-22T03:41:46.877 回答
1

++iis 在语句中,因为如果我们不将字符放在当前索引中,我们if不想增加;这将导致在输入的最后一个字符和字符串的末尾之间留下一个索引。i\n\0

于 2013-04-22T03:41:27.713 回答
0

由于 3 个条件,for 循环可以退出 1. 达到读取字符限制或遇到 EOF 2. 遇到新行

对于第一种情况,我们需要将 Null 存储到字符串 s 中,因为 i 指向最后读取的有效字符的下一个位置,因此无需增加 i。但是对于第二种情况,当 i 指向最后读取的有效字符的下一个位置时,我们现在在该位置存储换行符,然后递增 i 以存储 NULL 字符。

这就是为什么我们需要在第二种情况下而不是在第一种情况下增加 i 。

 if(c=='\n'){
            s[i] = c;
            ++i;
        }
于 2013-04-22T03:46:20.863 回答