许多初学者都习惯用 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();即可

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

  1. c语言getchar函数的作用,c语言中getchar的用法函数用法

    当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止.下面小编就跟你们详细介绍下c语言中getchar的用法,希望对你们有用. c语言中getchar ...

  2. 关于C语言中getchar()函数的用法

    前言:ASCII码 ASCII码是现在通用的单字节编码系统,它使用7位或8位二进制数字的指定组合来表示128或256个可能的字符,其全称是美国信息交换标准代码.ASCII码对照表:ascii码对照表在 ...

  3. C语言一定要有函数声明吗,1 什么是C语言的隐式函数声明在C语言中,函数在调用前不一定非要声明。如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码。下...

    1 什么是C语言的隐式函数声明 在C语言中,函数在调用前不一定非要声明.如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码.下面是一个例子: int main(int ...

  4. C语言输入函数换行符赋给变量B,C语言程序设计第3章顺序结构程序设计.pptx-资源下载在线文库www.lddoc.cn...

    C语言程序设计第3章 顺序结构程序设计.pptx 第 6章 数组第 7章 函数第 8章 结构体.共用体和枚举类型第 9章 指针第 10章 文件目录页 Contents page第 1章 初识 C语言第 ...

  5. c语言将pwd结果赋给变量,《网络系统管理linux实训》全套PPT电子课件教案-第4章 shell编程.ppt...

    第4章shell编程 4 1shell编程简介4 2shell分类4 3shell基本语法4 4shell程序的变量和参数4 5shell的测试表达式4 6shell的控制结构4 7awk4 8sed ...

  6. c语言typeof 变量,c语言中typeof关键字

    为什么因为一个关键字而专门写一篇随笔呢?因为这个关键字在Linux里面地位非同一般!这个关键字typeof在linux内核里面使用非常广泛! 下面这两个等效声明,用于声明int类弄的变量a typeo ...

  7. c语言 文件名变量,C语言中,如何用根据不同的变量来更改文件名?

    C语言中,如何用根据不同的变量来更改文件名? 來源:互聯網  2009-07-10 01:37:33  評論 分類: 電腦/網絡 >> 程序設計 >> 其他編程語言 問題描述: ...

  8. c语言中区别一般变量,C语言中,为了区别一般的变量,符号常量必须用

    C语言中,为了区别一般的变量,符号常量必须用大写字母表示.(?) 答:错 ,维也纳古典乐派代表人物之一,欧洲古典主义时期作曲家.因其对古典音乐的重大贡献,对奏鸣曲式和交响曲套曲结构的发展和创新,而被后 ...

  9. c语言的字符串不是存放,在C语言中,字符串不存放在一个变量中,而是存放在一个中...

    在C语言中,字符串不存放在一个变量中,而是存放在一个中 答:数组 中国大学MOOC: 请选择恰当的选项填入划线的空白处.国 生活習慣が違います. 答:によって 中国大学MOOC: 下列项目中,不应作为 ...

最新文章

  1. cpu工作原理flash动画_cpu的基本结构及其工作原理
  2. java并发编程之Semaphore
  3. OpenGL使用深度剥离命令获得独立的透明度
  4. JTAG、JLINK、ULINK、ST-LINK的联系和区别
  5. 用iptables实现G1手机cmwap代理上http网站[转]
  6. Java笔记07-List、Set、数据结构、Collections
  7. 学习python入门的个人建议及资料
  8. TypeScript学习笔记(五) - 泛型
  9. 非平衡电桥电阻计算_绝缘检测电桥法中的几个重要概念
  10. 工程思想——关于串口通讯协议帧数据的一些想法
  11. excel实时获取基金信息的实现方法
  12. 持久层框架JPA与Mybatis该如何选型
  13. windows 20003 扩展安装后不成功的原因
  14. grub rescue救援模式的处理
  15. iOS视频播放全屏效果实现
  16. ES7210四通道ADC芯片电路PCB-LAYOUT注意
  17. html正则邮箱格式,JS正则表达式判断邮箱格式是否正确
  18. pip升级失败,pip拒绝访问
  19. java高级过滤器、baseServlet、log4j配置使用poi实现excel导入数据库
  20. NTP服务端和客户端的部署——Chrony

热门文章

  1. 4大案例分析金融机构的大数据应用
  2. MySQL复制经常使用拓扑结构具体解释
  3. [ linq2db ] 使用LoadWith()对外键进行查询
  4. maven搭建ssm框架
  5. java排序——插入排序
  6. win10运行在哪里_升级!Win10 2004版即将推送,减少CPU占用率,旧电脑也运行如飞...
  7. linux 内核模块 编写例子,Linux内核模块实例
  8. java pack unicode,汉字和Unicode码(utf-8)之间的转换(Pack/Unpack)
  9. java 时间间隔 工作日,计算Java中两个日期之间的工作日数
  10. 漏洞payload 靶机_【CS学习笔记】5、如何建立Payload处理器