| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 638 人关注过本帖
标题:对于标准库函数 fgets 和 getc 的疑问
只看楼主 加入收藏
mxd000000
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2012-12-26
结帖率:50%
收藏
已结贴  问题点数:20 回复次数:6 
对于标准库函数 fgets 和 getc 的疑问
<The C Programming Language>一书中提到了标准库中fgets函数的实现代码.如下:
程序代码:
char* fgets(char *s, int n, FILE *iop)
{
    register int c;
    register char *cs;
    cs = s;
    while(--n > 0 && (c = getc(iop)) != EOF )
        if((*cs++ = c) == '\n')
        break;
    *cs = '\0';
    return (c == EOF && cs == s) ? NULL : s;
}


我写了一段测试fgets的代码,如下:
程序代码:
#include<stdio.h>

int main()
{
    FILE* fin;
    char *p = NULL;
    char     s[100];
    fin  = fopen("Test.in","r");  /*test.in 文件中内容为 第一行:Hello 第二行:World 第三行:123*/
    p = fgets(s,6,fin);    /*p是为了测试fgets函数返回的是NULL还是数组s[100]的地址*/
    printf("%s\n%x\n%x\n",s,s,p);    /*三个输出分别是 读入的字符串,  字符串地址, fgets返回的值(char*型)*/
    system("pause");
    return 0;
}


输出截图:
图片附件: 游客没有浏览图片的权限,请 登录注册

我的疑惑如下:
    ❤为什么测试代码中fgets函数的返回值就是输入参数s的值.因为按照<The C Programming Language>一书中提到的fgets的返回语句是这么写的
        
return (c == EOF && cs == s) ? NULL : s;

      而我的测试语句是
        
        fin  = fopen("Test.in","r");  /*test.in 文件中内容为 第一行:Hello 第二行:World 第三行:123*/
        p = fgets(s,6,fin);    /*p是为了测试fgets函数返回的是NULL还是数组s[100]的地址*/
        

 按我的理解,fgets函数应该是读到了Test.in文件中的Hello这5个字符(第一行末尾的换行符没有读入)到数组s[]中,并且在其后添加了'\0'. 而此时fgets并没有读到文件尾,所以fgets定义中用到的c=getc(iop)这一句c应该不等于EOF.因此,返回语句
return (c == EOF && cs == s) ? NULL : s;
中c == EOF的值为0, 即fgets返回值应该为NULL
. 可是我上面的输出结果显示,fgets的返回值是数组s[]的首地址,并不是我想的NULL,这也就是说,fgets返回的是s而不是NULL.
      我是哪里错了嘛?
   
    ❤关于getc返回值何时为EOF,我在书中只找到这样的说明:"如果到达文件尾或者出现错误,该函数将返回EOF". 我上面的例子应该不是到达文件尾,那么难道是出错了??
    ❤我是在win7 64bit VS2010环境下测试的,又或者这是因为vs中的fgets函数不是按标准库的方法实现,而是略有出入,所以导致了上面的结果?我才疏学浅,找到了fgets的定义,无奈表示看不懂.像这样:
图片附件: 游客没有浏览图片的权限,请 登录注册
似乎看不到具体的定义.T_T

恳请各位不吝赐教,在此先谢过啦!~

[ 本帖最后由 mxd000000 于 2014-11-17 20:06 编辑 ]
搜索更多相关主题的帖子: color 
2014-11-17 20:01
soulmate1023
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:256
专家分:831
注 册:2014-9-23
收藏
得分:7 
原型是char *fgets(char *s, int n, FILE *stream);
参数:
*s: 字符型指针,指向将存储到的数据地址。
n:整型数据,将从流中读取 n - 1 个字符。
*stream: 指针数据,欲读取的流。
功能:
从文件指针stream中读取n-1个字符,存到以s为起始地址的空间里,直到读完一行,如果成功则返回s的指针,否则返回NULL。
你的测试函数成功了,就返回S的指针,有什么不对吗?
2014-11-17 20:29
mxd000000
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2012-12-26
收藏
得分:0 
谢谢楼上的朋友.
程序代码:
char* fgets(char *s, int n, FILE *iop)
{
    register int c;
    register char *cs;
    cs = s;
    while(--n > 0 && (c = getc(iop)) != EOF )
        if((*cs++ = c) == '\n')
        break;
    *cs = '\0';
    return (c == EOF && cs == s) ? NULL : s;
}

以上是<The C Programming Language>中提到的 标准库fgets中的具体实现代码.
我的问题是,我测试的时候,并没有让fgets中的getc读到文件末尾,那么getc的返回值应该不是EOF, 那么在fgets返回的语句中
return (c == EOF && cs == s) ? NULL : s;
条件c == EOF 就不成立,那么以上语句应该返回的结果是NULL。可是实际却是应该有效的地址.不知道这样讲,能不能把我的问题表述清楚.
2014-11-17 21:47
soulmate1023
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:256
专家分:831
注 册:2014-9-23
收藏
得分:0 
回复 3 楼 mxd000000
是不是EOF,但是你的--n>0这个条件不满足才跳出循环的,不是因为EOF,你输入的是6,就是读入只能是5个字符,
你把HELLO getchar()后,n不就已经减到0了。
2014-11-17 23:08
mxd000000
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2012-12-26
收藏
得分:0 
回复 4 楼 soulmate1023
让n减到0跳出循环是我故意的.我是想,n减到零了,但是getchar还没有读到文件尾,那么getchar()就不会返回EOF,所以在最后的返回语句中 c == EOF 这个条件就不成立,所以返回的应该是NULL而不是s.
可是,实际上返回的是s.
2014-11-20 22:52
liao06550107
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:2
帖 子:111
专家分:696
注 册:2011-10-2
收藏
得分:7 
问题的关键是楼主没理解条件表达式逻辑,(条件)?语句一:语句二。逻辑为,如果条件为真则执行语句一,否则执行语句二。上题中条件为假,执行语句二。即返回S。

听不同的音乐,看不同的书,游历不同的城市,邂逅不同的人,走的多了,站的高了,自然就看的远了。
2014-11-21 06:15
yahwei
Rank: 7Rank: 7Rank: 7
来 自:湖~
等 级:黑侠
威 望:3
帖 子:145
专家分:644
注 册:2011-11-10
收藏
得分:7 
以下是引用mxd000000在2014-11-20 22:52:20的发言:

让n减到0跳出循环是我故意的.我是想,n减到零了,但是getchar还没有读到文件尾,那么getchar()就不会返回EOF,所以在最后的返回语句中 c == EOF 这个条件就不成立,所以返回的应该是NULL而不是s.
可是,实际上返回的是s.

六楼的回答是对的,你没理解条件表达式的逻辑。C == EOF这个条件不成立,应该返回S,而不是NULL。

[qq]949654600[/qq]
2014-11-21 09:52
快速回复:对于标准库函数 fgets 和 getc 的疑问
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.043470 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved