修改最长行程序的main例程,使其能够正确打印任意长度的输入行,并尽可能多地打印文本。
以下是练习1.16的K&R答案手册中的完整代码:
#include <stdio.h>
#define MAXLINE 1000
int getline (char line[], int maxline);
void copy (char to[], char from[]);
main()
{
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while ((len = getline(line, MAXLINE)) > 0 ){
printf("%d %s", len, line);
if (len >max){
max = len;
copy (longest, line);
}
}
if (max > 0)
printf("%s", longest);
getchar();
return 0;
}
int getline(char s[], int lim)
{
int c, i, j;
j = 0;
for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i)
if (i < lim-2){
s[j] = c;
++j;
}
if (c == '\n'){
s[j] = c;
++j;
++i;
}
s[j] = '\0';
return i;
}
void copy (char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}查看getline函数,在以下行中使用lim-2而不是lim-1的目的是什么:
if (i < lim-2){这似乎没有任何用处。'\0‘字符标记不应该出现在slim,而不是slim-1或slim-2
此外,如果超过了字符限制,该函数将跳过最新的字符,直到找到新的行字符,并将换行符添加到char字符串中,但跳过进程中来自输入流的下一个“合适”字符。这样做的目的是什么?
我真的不确定作者在这里的意图,这本书也没有提供任何解释。
编辑:使用像line5这样的数组,我的印象是字符数组中的空字符放在line5中,我们可以将一些东西放在数组的下标0-4中。这个假设是错误的吗?
发布于 2013-12-29 01:23:40
这似乎没有任何用处。'\0‘字符标记不应该出现在slim,而不是slim-1或slim-2吗?
不是的。lim是缓冲区的大小,因此数组的最后一个索引是lim-1。代码使用lim-2,因为它为结束字符串字符('\0')和新行("\n")保留了空间。
此外,如果超过了字符限制,该函数将跳过最新的字符,直到找到新的行字符,并将换行符添加到字符字符串中,但跳过进程中来自输入流的下一个“合适”字符。这样做的目的是什么?
getline函数读取被分成大小为MAX_LINE的不同块的输入字符串,然后将这些块复制到longest缓冲区。由于longest缓冲区具有固定大小,因此可以打印的字符串的最大长度为MAX_LINE (即,仅第一个块)。因此,即使在输入中插入较长的字符串,longest缓冲区的大小也是可以打印的字符串的实际限制。本练习包括使longest缓冲区动态化,以便应用程序能够读取和打印任意长字符串。您必须使用动态内存,因为您不知道输入字符串的大小。一种可能的解决方案是将每个块保存到一个临时缓冲区中,当所有缓冲区都在内存中时,您可以计算输入字符串的大小,然后将所有块复制到一个大小为输入字符串长度的新缓冲区中。
发布于 2017-01-08 23:23:18
是的,我只是碰巧读到了同样的页面,也感到困惑。我认为只有在以下情况下才是错误的:
1.输入行超过lim;
2.输入行直接以EOF结尾,不带换行符\n
因此,它只将有意义的字符保存到s[lim-3],将\0放在s[lim-2]中,而不使用s[lim-1]。
然而,在practise(我使用的是OSx)中,EOF只能通过在行的开头键入control-D来触发-这意味着所有行都以\n结尾(特别是最后一行)。因此,无论是否超过lim,最后保存在s[]中的最后两个字符始终是\n和\0。
当输入是一些主干文件,而不是终端上的输入时,你可以读到这个:Why should text files end with a newline?,我今天也找到了,我认为这两个问题高度相关。
希望我的回答能有所帮助!:)
https://stackoverflow.com/questions/20817144
复制相似问题