有关K&R书一道例题的疑问

sunyuqian 2009-02-03 07:41:03
大家好,我在看K&R书的一道例题时,发现有一个地方跟书后的习题有差别,书后习题有一个地方没明白,用/*...*/标出,请高手解答


例题:

#include <stdio.h>
#define MAXLINE 1000 /*允许输入行的最大长度*/
int getline(char s[],int lim);
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;
}

int getline(char s[],int lim)
{
int c,i;
for(i=0; i<lim-1 && (c=getchar()) != EOF && c != '\n'; ++i)
/*
为什么是lim-1,定义lim最大为1000,那lim-1=999,i最大为998,从0到998有999个字符,假设我输入了999个字符,还剩一个,底下的\n则是等第1000个字符,那\0怎么办呢?

跟它相关的习题解答写的是lim-2,似乎更合理一些,在这道例题底下,到底哪个对呢?
*/
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;
}


习题:

/*习题说“使之可以打印任意长度的输入行的长度”,但我看它的答案还是限制最大为1000的字符,怎么体现出它说的要求了?*/

//修改打印最长文本行的程序的主程序main,使之可以打印任意长度的输入行的长度,并尽可能多地打印文本
#include <stdio.h>
#define MAXLINE 1000 /*允许输入行的最大长度*/ /*已经限制最大为1000,怎么可能任意输出长度?*/
int getline(char s[],int lim);
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);
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) /*这里写的是lim-2,似乎更合理*/

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

void copy(char to[],char from[])
{
int i;
i=0;
while((to[i] = from[i]) != '\0')
++i;
}
...全文
132 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
lxlnemo 2009-02-19
  • 打赏
  • 举报
回复
我觉得关键是 i<lim-1 没有验证成功后, c=getchar() 便不再执行因此即使第1000个字符为 '\n' 也不会赋值到c上,因此c上还保留着第999个字符的值,
if(c == '\n')
{
s[i] = c;
++i;
}
也肯定不会执行了
所以在执行
s[i] = '\0';
时。i=999
sunyuqian 2009-02-03
  • 打赏
  • 举报
回复
谢谢了
sunyuqian 2009-02-03
  • 打赏
  • 举报
回复
谢谢了
xidianxiancai 2009-02-03
  • 打赏
  • 举报
回复
若在i<=998退出程序,是没有关系的;若i>998,这时候会自动跳出循环,s[i] = '\0';由该语句来结尾,保证是总共有1000个数据
waizqfor 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 sunyuqian 的回复:]
引用 3 楼 waizqfor 的回复:
引用 2 楼 waizqfor 的回复:
C/C++ code
#define MAXLINE 1000 //首先说一下 这个任意长度其实都有确切的数的 只是大概的说一下就是任意长度 LZ不用深究它
for(i=0; i <lim-1 && (c=getchar()) != EOF && c != '\n'; ++i)//这里的循环是从0-998 当i=999的时候就退出循环
//因for中的判断顺序是
i <lim-1 && (c=getchar()) != EOF && c != '\n' 所以C保留的应该还是i=998的数据 所以if 99…
[/Quote]
我想知道你定义了10个数组的长度 比如a[10] 你赋值a[10]=1; 能正确输出吗 声明的时候是a[10]代表的是10个长度 到赋值的时候就应该是从0~9啊 到10就溢出了啊
sunyuqian 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 waizqfor 的回复:]
引用 2 楼 waizqfor 的回复:
C/C++ code
#define MAXLINE 1000 //首先说一下 这个任意长度其实都有确切的数的 只是大概的说一下就是任意长度 LZ不用深究它
for(i=0; i <lim-1 && (c=getchar()) != EOF && c != '\n'; ++i)//这里的循环是从0-998 当i=999的时候就退出循环
//因for中的判断顺序是
i <lim-1 && (c=getchar()) != EOF && c != '\n' 所以C保留的应该还是i=998的数据 所以if 998==‘\n’ 那么就给999的数据赋…
[/Quote]

这位朋友,我以前的想法是:

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;
}


i最大是998,但我觉得998是i的下标,而for循环是从0开始的,下标为998,实际上应该是第999个字符,总共是1000个字符,for循环执行后,应该只剩一个字符,当没有换行符的时候,直接把\0赋给第1000个字符;但如果输入下标为998的字符(也就是第999个数)后,又输入了换行符\n,那它应该是第1000个字符,接着又把\0赋给i,\0应该是第1001个,但最大定义了1000个。

==================================================

但是我看了你的留言,我把定义最大1000个数改成了10,我试了试,发现我输入8个字符后回车,然后结束,正常,"Press any key to continue"这句提示是在8个字符的下一行显示的;但我要是输入9个字符,回车,然后结束,"Press any key to continue"这句提示则在9个字符后显示,回车没有被加进去。

是不是\0是强制赋给最后一个字符,定义10个数,实际上只能输入9个,但我输入9个字符后,再输入\n,那么已经没有空间给它了,所以输入8个字符,再回车,就可以换行。如果是这样的话,那定义1000个字符,实际上就只能输入999个字符,第1000个给\0,第999个字符给\n,如果不是\n,则和定义10个字符,输入9个字符效果一样。
我用的是vc++6.0
vincent_1011 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 waizqfor 的回复:]
引用 1 楼 vincent_1011 的回复:
我菜菜,弱弱问下,为什么

for(i=0; (c=getchar()) != EOF && c != '\n'; ++i)

这里有这样判断的话,循环体里面 if(c == '\n')这个还行吗?照我理解,当c=='\n'的时候已经不能进去循环体了啊

兄弟 注意它的循环形式
C/C++ codefor(i=0; i<lim-1&&(c=getchar())!=EOF&&c!='\n';++i)
s[i]=c;//for因为他没加{}所以循环只执行for的下面一个语句 所以那个if不在…
[/Quote]
waizqfor可是相当的热心啊,哈。
zhshto886 2009-02-03
  • 打赏
  • 举报
回复
你误解作者的意思了
作者的意思是当字符串的长度超过1000,包括等于1000!这种情况下for结束的条件是i <lim-1。即for循环就没有读取到\n就直接在999的位置添加\0了!

数组中既有\n又有\0时,for循环是不会因为i <lim-1结束的,只能是(c=getchar()) != EOF && c != '\n'!这种情况1000的空间是没有用完的!
The_facE 2009-02-03
  • 打赏
  • 举报
回复
当i=999时是进不去循环的,要是写lim-2就得用i<=lim-2了。真的要完全实现任意长度(不考虑内存容量)z只能用堆内存才行。
waizqfor 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 vincent_1011 的回复:]
我菜菜,弱弱问下,为什么

for(i=0; (c=getchar()) != EOF && c != '\n'; ++i)

这里有这样判断的话,循环体里面 if(c == '\n')这个还行吗?照我理解,当c=='\n'的时候已经不能进去循环体了啊
[/Quote]
兄弟 注意它的循环形式

for(i=0; i<lim-1 && (c=getchar()) != EOF && c != '\n'; ++i)
s[i] = c;//for因为他没加{}所以循环只执行for的下面一个语句 所以那个if不在循环的范畴里
if(c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
waizqfor 2009-02-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 waizqfor 的回复:]
C/C++ code
#define MAXLINE 1000 //首先说一下 这个任意长度其实都有确切的数的 只是大概的说一下就是任意长度 LZ不用深究它
for(i=0; i<lim-1 && (c=getchar()) != EOF && c != '\n'; ++i)//这里的循环是从0-998 当i=999的时候就退出循环
//因for中的判断顺序是
i<lim-1 && (c=getchar()) != EOF && c != '\n' 所以C保留的应该还是i=998的数据 所以if 998==‘\n’ 那么就给999的数据赋值'\0'
[/Quote]
补充一下 for循环中 你是不可能输入第999个数的 因为到998就跳出了
waizqfor 2009-02-03
  • 打赏
  • 举报
回复

#define MAXLINE 1000 //首先说一下 这个任意长度其实都有确切的数的 只是大概的说一下就是任意长度 LZ不用深究它
for(i=0; i<lim-1 && (c=getchar()) != EOF && c != '\n'; ++i)//这里的循环是从0-998 当i=999的时候就退出循环
//因for中的判断顺序是
i<lim-1 && (c=getchar()) != EOF && c != '\n' 所以C保留的应该还是i=998的数据 所以if 998==‘\n’ 那么就给999的数据赋值'\0'

vincent_1011 2009-02-03
  • 打赏
  • 举报
回复
我菜菜,弱弱问下,为什么

for(i=0; (c=getchar()) != EOF && c != '\n'; ++i)

这里有这样判断的话,循环体里面 if(c == '\n')这个还行吗?照我理解,当c=='\n'的时候已经不能进去循环体了啊

69,381

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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