深入解析为什么char c;c = fgetc是不对的

深入解析为什么char c;c = fgetc是不对的,第1张

我们先来看看下面这个程序在VC++6.0中的运行情况(说明,

我自己已经建立好了test.txt文件夹,

并写了一些内容):

[cpp]

view

plain

copy

#include

<stdio.h>

int

main()

{

char

c

FILE

*fp

=

fopen("test.txt",

"r")

if(NULL

==

fp)

{

return

1

}

while(EOF

!=

(c

=

fgetc(fp)))

{

putchar(c)

}

fclose(fp)

printf("\n")

return

0

}

在VC++6.0中运行的结果是:

abcdefg

看起来没有问题,

那么在其他系统中运行呢?厅竖棚

我试了几个环境,

发现都是OK的,

但是,

上面程序是有问题的。

先从逻辑上来说吧,

在正常情况下,

fgetc函数返回的范围就是char的范围,

因此正常情况下用char

c中的c去存这个返回的值,

是足够的。

但是,

当已经达到文件尾或者fgetc函数出错的时候,

就会返回一个错误值,

那怎么去存错误值呢?

显然c的范围必须必char的范围要大才可,

所以用char

c是不正确的。

从实际上来说,

我们知道,

在大多数系统中char被默认为signed

char,

所谓范围是-128-127.

所以,

如果已经达到文件尾或者fgetc函数出错,

则会返回-1,

而EOF的值也通常是-1,

所以,

在上面的程序中,

while循环可以顺利退出。

但是,

在有的系统中,

char被默认为unsigned

char,

此时,

如果fgetc函数返回-1,

一旦赋值给c后,

c就是个正值了,

于是上面的while陷入了死循环。因此,

应该用int

c来存-1.

要说明的是,

在所有系统中,

int被默认为signed

int,

但char却比较特别,

不一定是signed

char,

尽管绝大多是时候是。(这一论断在《C++编程思想》的第一卷中有介绍,

请参考第三章"C++中的C"中的叙述)

可见,

为了程序的可移植性,

应该用int

c

其实扮则,

你看看,

fgetc的原型中,

返回值的类型就是int.

“我的疑惑”:我们再来仔细思考一下,

比如在VC++6.0中,

改为int

c后就不会有问题吗?

我把char形的-1写入到文件中,

读取的也是-1,

那岂不是错判为“fgetc函数遇到了文件尾纤笑或者出错”了?

那while循环岂不是不正确地结束了?

带着这些疑问,

我们先来看看下面这个简单的程序

[cpp]

view

plain

copy

#include

<stdio.h>

int

main()

{

FILE

*fp

=

fopen("test.txt",

"w")

if(NULL

==

fp)

{

return

1

}

char

ch

=

-1

fputc(ch,

fp)

//

实际上fputc的原型要求ch为int,

不过不影响我做测试,

因为char在VC++6.0中的范围是-128-127.

fclose(fp)

int

c

fp

=

fopen("test.txt",

"r")

if(NULL

==

fp)

{

return

1

}

c

=

fgetc(fp)

printf("%d",

c)

//

是255,

而不是-1哈

fclose(fp)

printf("\n")

return

0

}

上述结果中,

c的值是255,

而不是-1,

这就说明,

在正常情况下,

fgetc从文件中读出的不可能是负值,

因为ascii值不可能是负值。

而我们知道,

一旦达到文件尾或者fgetc函数出错,

会返回-1,

可见,

正确的值和错误的值是完全区分开了的。

进而可知,

上面“我的疑惑”不再疑惑。

我们再来反思一下,

char

c

c

=

fgetc(fp)在VC++6.0中真的不存在问题吗?上菜:

[cpp]

view

plain

copy

#include

<stdio.h>

int

main()

{

FILE

*fp

=

fopen("test.txt",

"w")

if(NULL

==

fp)

{

return

1

}

fputc(128,

fp)

fclose(fp)

char

c

fp

=

fopen("test.txt",

"r")

if(NULL

==

fp)

{

return

1

}

c

=

fgetc(fp)

printf("%d",

c)

//

是-128,

而不是128哈,

所以即使在VC++6.0中,char

c也是错误的

fclose(fp)

printf("\n")

return

0

}

综上所述:

必须用int

c

而类似的函数还有getc,

getchar.

希望大家在以后的笔试面试中注意这点,

在实际项目中也多加注意。最后强调一句,

char可以为负,

但ascii值却没有负值

char *sgets(s)

上面这种写法是错误的.s定义成指针,需要有明确的冲晌指向.gets()函数是要求提供具体指针地址,从那个地址开始存储字符串,而如果简单定义char *ss是个野指针散数锋,无法提供具体指向。可以修改毕厅

成char *schar a[100]s=agets(s)这样让s指向数组a,确定地址方位。

char *ss="ABCDEF"

上面这种写法是可以的.让s指向字符串常量首地址。可以进行打印 *** 作puts(s)但不能进行修改 *** 作*s='a'因为常量字符串的限制。

建议你上机运行下这几句,编译都能通过.不过,执行时候,看看效果

不正确。x[4]也就是 *(x+4),是字符‘g',不能将一隐物个字符赋值给字灶慧液符串。

但可以这样写:strcpy(y,x+4),即碧盯,将"ghi"赋值给y字符串。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/yw/12567422.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存