“修改最长行程序的主程序,以便正确打印任意长输入行的长度,并尽可能多地打印文本。”
以下是练习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){
这似乎没有任何用处。不应该在s [lim]而不是s [lim-1]或s [lim-2]处出现'\ 0'字符标记吗?
此外,该函数会跳过最新字符,如果超过字符限制,直到找到一个新行字符,并将换行符添加到char字符串,但跳过下一个“fittable”字符来自流程中的输入流。这个目的是什么?
我不确定作者在这里打算做什么,这本书没有提供任何解释。
编辑:使用像行[5]这样的数组,我的印象是字符数组中的NULL字符在行[5]中,我们可以在数组下标0-4中放置一些东西。这个假设是假的吗?
答案 0 :(得分:1)
这似乎没有任何用处。不应该'\ 0' 字符标记出现在s [lim]而不是s [lim-1]或s [lim-2]?
没有。 lim
是缓冲区的大小,因此数组的最后一个索引是lim-1。
代码使用lim-2
因为它保留了结束字符串字符('\ 0')和新行(“\ n”)的空间。
此外,该功能会跳过最新的角色,如果有的话 超过字符限制,直到找到一个新的行字符,然后它 将换行符添加到char字符串,但跳过任何内容 来自输入流的下一个“fittable”字符。 这个目的是什么?
getline
函数读取分成不同大小MAX_LINE的块的输入字符串,然后将这些块复制到longest
缓冲区中。由于longest
缓冲区具有固定大小,因此可以打印的字符串的最大长度是MAX_LINE(即仅第一个块)。因此,即使在输入中插入较长的字符串,longest
缓冲区的大小也是可以打印出来的字符串的实际限制。练习包括使longest
缓冲区动态化,以便应用程序能够读取和打印任意长字符串。您必须使用动态内存,因为您不知道输入字符串的大小。一种可能的解决方案是将每个块保存到临时缓冲区中,当所有缓冲区都在内存中时,您可以计算输入字符串的大小,然后将所有块复制到一个新的缓冲区中,该缓冲区的大小是输入字符串的长度。
答案 1 :(得分:0)
是的,我刚刚读了同一页并且也很困惑。在以下情况下,我认为这只是错误的:
lim
; \n
这样它只会将有意义的字符保存到s[lim-3]
,将\0
放入s[lim-2]
并使s[lim-1]
不使用。
然而在实践中(我使用OSx),EOF只能通过在行的开头键入control-D
来触发 - 这意味着所有行都以\n
结尾(特别是最后一行)线)。因此,无论它是否超过lim
,最后s[]
中保存的最后两个字符始终为\n
和\0
。
当输入是文件的一个主干而不是终端上的输入时,你可以阅读这个:Why should text files end with a newline?我今天也发现了这个问题,我认为这两个问题是高度相关的。
希望我的回答有所帮助! :)