《The C Programming Language》第一章1.9节字符数组示例程序的一个小问题

kk5171 2009-04-11 09:06:37
#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)
if(len > max)
{
max = len;
copy(longest, line);
}
if(max > 0) /*存在这样的行*/
printf("%s", longest);

return 0;
}

/*getline函数:将一行读入到s并返回其长度*/
int getline(char s[],int lim)/*这里s的长度是由相应的实参数组决定的*/
{
int c,i;

for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n';++i)/*这里只能是i<lim-1,因为要考虑到存放'\n'*/
s[i] = c;
if(c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}

/*copy函数,将from复制到to,这里假定to足够大*/
void copy(char to[], char from[])
{
int i;

i = 0;
while((to[i] = from[i]) != '\0')
++i;
}
请问程序中标红的i < lim -1是否有问题?我认为在数组末尾应该留出两个字符位置,一个给'\n',另一个给'\0',所以我认为应该是i < lim -2。不知哪位大虾能解释一下?
...全文
194 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
futurephillip 2012-05-01
  • 打赏
  • 举报
回复
刚刚通过编程发现我的说法中有错误也有正确的地方。当长度溢出时那个'\n'确实没有加上,但是不能去掉if判断,原因还不知道,好困啊,今晚先睡觉去,明天接着看。
futurephillip 2012-05-01
  • 打赏
  • 举报
回复
不知道我的看法对不对,char line[1000]定义了字符串的最大长度应为1000, 因为结束符'\0'不包括在字符串长度内,它只是加在一个字符串的末尾表示这个字符串结束了,前面的所有内容都是这个字符串的内容,包括'\n'.
其实还可以详细讨论这个问题,假设某行字符串长度(包括结尾的\n,下同)小于999,则i<lim-1始终不会满足,for循环结束是因为c='\n'或者EOF,字符串最后一个有效字符总是这个'\n';但是当字符串长度为999,当i=999时,i<lim-1不满足,c内存储的是第998个字符,不是'\n',c=='\n'不满足,if内的s[999]='\n'不会执行,但是'\0'还是会被放在s[999].我感觉这和作者的意图不一致,作者的意思应该是在每行字符串后面都加一个'\n',但是当长度>=999时这个'\n'没有加上去,要保证每个字符串后面都有'\n',应该去掉if判断,直接使用s[i++]='\n'。
说了这么多也不知道说清楚没。



[Quote=引用 11 楼 的回复:]

我的10楼帖子第一句话好像不对。怎么没法编辑呢?
更正如下:
char line[1000]定义了字符串的最大长度是999,因为还有一个系统加的结束符'\0'。如果输入的字符串字符数超过999个,系统会截取999个,并在第1000的位置上加一个'\0'。
从line[0]开始遍历, i<lim-1即i<=998,刚好遍历到'\0'之前那个字符,line[999]='\0'。
[/Quote]
burner 2012-01-13
  • 打赏
  • 举报
回复
我的10楼帖子第一句话好像不对。怎么没法编辑呢?
更正如下:
char line[1000]定义了字符串的最大长度是999,因为还有一个系统加的结束符'\0'。如果输入的字符串字符数超过999个,系统会截取999个,并在第1000的位置上加一个'\0'。
从line[0]开始遍历, i<lim-1即i<=998,刚好遍历到'\0'之前那个字符,line[999]='\0'。
burner 2012-01-13
  • 打赏
  • 举报
回复
输入字符串常量后系统自动加\0,行尾一定有\n,由于遍历是从i=0开始,所以lim-1已经遍历包括\0和\n的一行内容了。

另外,四楼说:“条件语句i <lim-1 && (c=getchar())!=EOF && c!='\n'当是i < lim - 1不符合时,(c=getchar())!=EOF 和下面的if语句不会执行”

条件语句i <lim-1 && (c=getchar())!=EOF && c!='\n'当i < lim - 1不符合时,(c=getchar())!=EOF不会执行,是对的。可是下面的if语句不受影响,因为for (i=0; i < lim-1&& (c=getchar())!=EOF && c!='\n'; ++i)这个循环只有一条循环语句s[i]=c;。
henyi2211 2011-04-11
  • 打赏
  • 举报
回复
我在ubuntu中输入这个示例程序,按ctrl+d结束,但是没输出结果!怎么样才能正常结束,看结果呢??
xiandatian 2009-12-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 xiandatian 的回复:]
还有
我在运行这个程序时,尝试在屏幕上敲入一行半多一点字符时,屏幕就停住了。反复按CTRL+Z键才可以退出全屏。

MAXLINE不是说限制为一行最多1000个字符吗?为什么输入不到两行,就停住了呢?

为什么?
请教!!!
[/Quote]是没有回车的自动换行
xiandatian 2009-12-06
  • 打赏
  • 举报
回复
还有
我在运行这个程序时,尝试在屏幕上敲入一行半多一点字符时,屏幕就停住了。反复按CTRL+Z键才可以退出全屏。

MAXLINE不是说限制为一行最多1000个字符吗?为什么输入不到两行,就停住了呢?

为什么?
请教!!!
xiandatian 2009-12-06
  • 打赏
  • 举报
回复
还是这个题目,请教一下:
MAXLINE是符号常量,也是实参,数值是1000.
可不可以理解为在调用getline函数时,lim是1000,lim-1=999 ?

可以这样理解吗?
kk5171 2009-04-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 tianya0609 的回复:]
C/C++ code
//书上是对的,因为不需要预留两个位置
//条件语句i <lim-1 && (c=getchar())!=EOF && c!='\n'当是i < lim - 1不符合时,(c=getchar())!=EOF 和下
//面的if语句不会执行,当是c!='\n'不符合时,说明i <= lim - 2时,所以下面的空间也够的,返回值也正确

int getline(char s[],int lim)/*这里s的长度是由相应的实参数组决定的*/
{
int c,i;

for(i=0; i <lim-1 && (c=getchar())!=EOF && c!='…
[/Quote]
非常感谢4楼!同时也感谢2楼、3楼!理解了,确实是这个问题,老外的程序还真是严丝合缝。当i < lim - 1为假时整个表达式为假,后面的(c=getchar())!=EOF 和c!='\n'将不再执行,也就是不再读字符,空间就够用了。再次感谢
tianya0609 2009-04-11
  • 打赏
  • 举报
回复

//书上是对的,因为不需要预留两个位置
//条件语句i <lim-1 && (c=getchar())!=EOF && c!='\n'当是i < lim - 1不符合时,(c=getchar())!=EOF 和下
//面的if语句不会执行,当是c!='\n'不符合时,说明i <= lim - 2时,所以下面的空间也够的,返回值也正确

int getline(char s[],int lim)/*这里s的长度是由相应的实参数组决定的*/
{
int c,i;

for(i=0; i <lim-1 && (c=getchar())!=EOF && c!='\n';++i)/*这里只能是i <lim-1,因为要考虑到存放'\n'*/
s[i] = c;
if(c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}


liliangbao 2009-04-11
  • 打赏
  • 举报
回复
你考虑的是对的~
我支持你!
mengde007 2009-04-11
  • 打赏
  • 举报
回复
楼主的意图是对的
morris88 2009-04-11
  • 打赏
  • 举报
回复
貌似你是对的...

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧