c语言getchar的不赋任何变量,C语言中getchar中的问题

许多初学者都习惯用 char型变量接收getchar、getc,fgetc等函数的返回值,其实这么做是不对的,并且隐含着足以致命的错误。getchar等函数的返回值类型都是int型

下面是getchar()的定义:

[html]view plaincopyprint?

1int

2getchar ()

3{

4  int result;

5  _IO_acquire_lock (_IO_stdin);

6  result = _IO_getc_unlocked (_IO_stdin);

7  _IO_release_lock (_IO_stdin);

8  return result;

9}

当这些函数读取出错或者读完文件后,会返回 EOF.EOF是一个宏,标准规定它的值必须是一个int型的负数常量。

通常编译器都会把 EOF定义为-1.问题就出在这里,使用char型变量接收getchar等函数的返回值会导致对EOF的辨认出错,或者错把好的数据误认为是EOF,或者把EOF误认为是好的数据。

Int c;

while ( (c = fgetc(fp)) != EOF )

Putchar=C;

如上例所示,我们很多时候都需要先用一个变量接收 fgetc等函数的返回值,然后再用这个变量和EOF比较,判断是否已经读完文件。

上面这个例子是正确的,把 c定义为int型保证了它能正确接收fgetc返回的EOF,从而保证了这个比较的正确性。但是,如果把c定义为char型,则会导致意想不到的后果。

首先,因为 fgetc等函数的返回值是int型的,当赋值给char型变量时,会发生降级,从而导致数据截断。

例如:

---------------------------------

|十进制|int|char |

|--------|--------------|-------|

|10| 00 00 00 0A|0A|

|-1| FF FF FF FF|FF|

|-2| FF FF FF FE|FE|

---------------------------------

在此,我们假设 int和char分别是32位和8位的。

由上表可得,从 int型到char型,损失了3个字节的数据。当我们要拿char型和int型比较的时候,char型会自动升级为int型。

char 型升级为int型后的值会因为它到底是signed char还是unsigned char而有所不同。

不幸的是,如果我们没有使用 signed或者unsigned来修饰char,那么我们无从知晓char到底是指unsigned char还是指signed char,因为这是由编译器决定的。

不过,无论 char是signed的也好,unsigned的也罢,都不能改变使用char型变量接收fgetc等函数的返回值是错误的这个事实。

唯一能改变的是该错误导致的后果。前面我们说了,char型和int型比较时,char会自动升级为int.

下面我们来看看 signed char和unsigned char在转换成int后,它们的值有什么不同:

---------------------------------------

|char |unsigned|signed|

|-------|---------------|-------------|

|10|00 00 00 0A| 00 00 00 0A |

|FF|00 00 00 FF| FF FF FF FF |

|FE|00 00 00 FE| FF FF FF FE |

---------------------------------------

由上表可知,当 char是unsigned的时候,其转换为int后的值是正数。也就是说,假如我们把c定义为char型变量,而编译器默认char为unsigned char,那么以下表达式将永远成立。

(c = fgetc(fp))!= EOF/* c的值永远为正数,而标准规定EOF为负数*/

也就是说以下循环是一个死循环。

while ( (c = fgetc(fp)) != EOF ){putchar(c);}

读到这里,可能有些读者朋友会说:“那么我明确把 c定义为signed char型的就没问题了吧!”很遗憾,就算把c定义为signed char,仍然是错误的。假设fgetc等函数读到一个字节的值为FF,那么返回值就是00 00 00 FF.把这个值赋值给c后,c的值变成FF.然后c的值为了和EOF比较,会自动升级为int型的值,也就是FF FF FF FF.从而导致以下表达式不成立。(c = fgetc(fp)) != EOF/*读到值为FF的字符,误认为EOF */

也就是说以下循环在没有读完文件的情况下提前退出。

while ( (c = fgetc(fp)) != EOF ){putchar(c);}

综上所述,使用 char型变量接收fgetc等函数的返回值是错误的,我们必须使用int型变量接收这些函数的返回值,然后判断接收到的值是否EOF.只有判断发现该返回值并非EOF,我们才可以把该值赋值给char型变量。

同理,C++中,用char型变量接收cin.get() 的返回值也是错误的。不过,把char型变量当作参数传递给cin.get则是正确的。

例如:

char c = cin.get();//错误,理由同上char c;cin.get(c);//正确

第一个getchar()时输入一个字符,按下回车,那么等于你输入了两个字符,一个是你输入的字符被c1读走,还有一个是回车的转义字符。它还在缓冲区中,那么你的第二个getchar()就读走这个回车的转义字符。所以会自己跳过去。你可以在第二个getchar()之前在放一个getchar(),让这个getchar()把缓冲区里的回车字符读掉。然后你就可以输入了。当然你也可以调用相关函数把输入缓冲区flush掉。

getchar有一个int型的返回值.当程序调用getchar时.

程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).

当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符.

getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.

如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.

也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键.

getch与getchar基本功能相同,差别是getch直接从键盘获取键值,不等待用户按回车,只要用户按一个键,getch就立刻返回, getch返回值是用户输入的ASCII码,出错返回-1.输入的字符不会回显在屏幕上.getch函数常用于程序调试中,在调试时,在关键位置显示有关的结果以待查看,然后用getch函数暂停程序运行,当按任意键后程序继续运行.

可以利用getchar()函数让程序调试运行结束后等待编程者按下键盘才返回编辑界面,用法:在主函数结尾,return 0;之前加上getchar();即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值