2 hughkirk HughKirk 于 2016.09.19 22:05 提问

关于C语言中的getchar(),小白请教一个问题。

小白重新学C语言。
准备把K&R的The C programming language从头到尾学一遍。

然后今天敲到getchar()时,为了做练习1-6:验证getchar()!=EOF 是0还是1,我就写了下面的代码:

 main()
{
    int thischar,test=0;
    char flag = 0;

    while ((thischar=getchar()) != EOF)
    {   
        test = ((thischar = getchar()) != EOF);  //Q1.
        printf("The value of condition after putchar(): %d \n", test);
        flag = 1;
        //if ((thischar = getchar()) != EOF);   //test step
        while ((thischar = getchar()) != EOF && flag == 1)
        {
            putchar(thischar);
            //printf("\n");
        }
        flag = 0;

    }

输入“12345678”,输入就是“345678”。
缺少“12”。
我打开调试之后,发现thischar的值是这样变化的:

breakpoint1
breakpoint2

我查了ASCII码,对应的49,50就是1和2.
也就是说因为我多检测了两次

 (thischar = getchar()) != EOF

这个。就导致我输出少了两个字符。我之后又试了试,以此类推,条件数量增多少,输出的字符就会少多少。
网上说getchar()函数的代码是这样的:

    int  
    getchar ()  
    {  
      int result;  
      _IO_acquire_lock (_IO_stdin);  
      result = _IO_getc_unlocked (_IO_stdin);  
      _IO_release_lock (_IO_stdin);  
      return result;  
    }  

我也查了寄存器的说明,但是还是不明白,为什么会造成这样的情况。和getchar()这个函数的定义有关系吗?如果没有,那是哪里出的问题呢?

感激不尽!

追加:
谁能大概解释一下getchar()函数定义,用自然语言描述大概是什么样的过程?
以及:

 while ((thischar=getchar()) != EOF)
01064C89  mov         esi,esp  
01064C8B  call        dword ptr [__imp__getchar (0106916Ch)]  
01064C91  cmp         esi,esp  
01064C93  call        __RTC_CheckEsp (01061113h)  
01064C98  mov         dword ptr [thischar],eax  
01064C9B  cmp         dword ptr [thischar],0FFFFFFFFh  
01064C9F  je          main+0D3h (01064D33h)  
    {   
        test = ((thischar = getchar()) != EOF);  //Q1.
01064CA5  mov         esi,esp  
01064CA7  call        dword ptr [__imp__getchar (0106916Ch)]  
01064CAD  cmp         esi,esp  
01064CAF  call        __RTC_CheckEsp (01061113h)  
01064CB4  mov         dword ptr [thischar],eax  
01064CB7  cmp         dword ptr [thischar],0FFFFFFFFh  
01064CBB  je          main+69h (01064CC9h)  
01064CBD  mov         dword ptr [ebp-0E8h],1  
01064CC7  jmp         main+73h (01064CD3h)  
01064CC9  mov         dword ptr [ebp-0E8h],0  
01064CD3  mov         eax,dword ptr [ebp-0E8h]  
01064CD9  mov         dword ptr [test],eax

上面的EAX寄存器应该是存了getchar()的返回值,那后面这个值是怎么样被后续操作抹掉的?我不太懂。

3个回答

u014327136
u014327136   2016.09.19 22:41
已采纳

while ((thischar=getchar()) != EOF)
{

test = ((thischar = getchar()) != EOF); //Q1.
这两行代码在你输入1和2时分别被赋值1和2;
while ((thischar = getchar()) != EOF && flag == 1)
{
putchar(thischar);
这几行代码运行是才是输出后面的赋值3,4 ,5,6,7,8;
如果需要更改,可改成:

main()
{
    int thischar,test=0;
    char flag = 0;

    while ((thischar=getchar()) != EOF)
    {   
            putchar(thischar);
        test = ((thischar = getchar()) != EOF);  //Q1.
                putchar(thischar);
       // printf("The value of condition after putchar(): %d \n", test);
        flag = 1;
        //if ((thischar = getchar()) != EOF);   //test step
        while ((thischar = getchar()) != EOF && flag == 1)
        {
            putchar(thischar);
            //printf("\n");
        }
        flag = 0;

    }
}

这样应该可以看明白吧。

HughKirk
HughKirk 回复yukangliu: 这篇我以前读过,还是谢谢您~这个主要是讲为什么不能用char来接收,需要用int,主要是EOF的值的问题。
接近 2 年之前 回复
u014327136
u014327136 http://blog.csdn.net/leichelle/article/details/6927861了这个你应该可以懂了。
接近 2 年之前 回复
HughKirk
HughKirk 恩恩,没事。谢谢您~我再看看。
接近 2 年之前 回复
u014327136
u014327136 回复匠川: 额,这个是汇编语言,我就不太懂了
接近 2 年之前 回复
HughKirk
HughKirk 回复yukangliu: 我键入的“12345678”不是一列值吗?它是读一个丢一个吗?只要读了一个字符,就会读下一个?我不太懂寄存器里是怎么变的。
接近 2 年之前 回复
HughKirk
HughKirk 回复yukangliu: 我更新了问题,您能看一下追加的嘛?我不是太明白寄存器里的值是怎么被覆盖的。
接近 2 年之前 回复
u014327136
u014327136 回复匠川: getchar()相当于定义了一个只能接收一个字符的 变量,当你键入其他字符后原先的值便被覆盖,因此只能打印当前键入字符。
接近 2 年之前 回复
HughKirk
HughKirk 恩恩,可以看懂。但必须这样写是因为getchar用一个字符就直接丢掉了嘛?缓冲区不保存是吗?也就是说getchar()是只要在键入输入值后,每调用一次就会消耗一个字符?如果想打印,就必须在调用下面直接加上putchar,是这样吗?
接近 2 年之前 回复
waterhexuan
waterhexuan   2016.09.19 22:43

getchar 本来就是执行一次 少一个啊 没看懂你这程序有什么异常啊

HughKirk
HughKirk 谢谢~
接近 2 年之前 回复
weixin_36183906
weixin_36183906   2016.09.19 23:31

每执行一次getchar,就会取出一个值,1和2你取出来后没有打印!也就是说,你在那个循环打印之前,已经执行了2次getchar

HughKirk
HughKirk 恩恩,谢谢您。我知道了。
接近 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
关于C语言中getchar()的详细使用
(此贴对自己受用,来源网络,在此分享)在C语言中有个重要的库函数getchar(),可从终端获得一个字符的ASCII码值。在终端输入字符时并非输入一个字符就会返回,而是在遇到回车换行前,所有输入的在C语言中有个重要的库函数getchar(),可从终端获得一个字符的ASCII码值。在终端输入字符时并非输入一个字符就会返回,而是在遇到回车换行前,所有输入的字符都会缓冲在键盘缓冲器中,直到回车换行一次性
C语言中的getchar和putchar详解
一、首先给出《The_C_Programming_Language》这本书中的例子:include include “stdio.h”main() { char c,d,e,f; printf(“please input two characters:\n”); c=getchar(); putchar(c); putchar(‘\n’);
C语言中,getchar()函数的使用事项
最近在用c语言写代码,经常使用getchar()函数,但感觉输出的结果和自己的预期不一样,最后发现是getchar()在使用的时候,忽略了一个重要的细节。现在把它写出来,供大家参考,也方便以后自己编写程序。 getchar()是从键盘中读取字符,它一次接受一个字符;如果一次敲的字符多于一个,包括回车字符,它会将剩下的字符存入缓存中,下次继续执行。 例如下面的代码所示: #include #i
C语言中getchar()和putchar()的实现细节
单个字符的输入输出函数 本文引用了以下博客 http://www.cnblogs.com/jiangjun/archive/2012/05/16/2503676.html http://www.cnblogs.com/hdchild/archive/2009/11/19/1606457.html 下面用一个例子来讲解如何获取字符和输出字符: #include "stdio.h
C语言中getch()与getchar()
getch getch函数在C语言中使用时需包含的头文件为 conio.h ,应写为#include 函数原型为:int getch(void); getch的功能:从标准输入设备(键盘)读入一个字符,不回显在显示器上.  getch函数的使用例程  # include  # include  # include  int main() {     char
C语言中printf,scanf,getchar , puts,gets 的使用及区别
1 printf和scanf    printf 的函数原型是  printf("", )    scanf的函数原型是 scanf("", );    格式化字符串:    整数 : %d,   单精度浮点数 : %f   双精度福电视: %lf   字符串: %s,   单个字符 : %c   参数表: 使用的是输入参数和输出参数的地址。 关于scanf接
C语言中getchar()、gets()和scanf()的特点以及scanf产生的多余回车符问题
第三个问题是关于get()和getchar()这两个函数的。大家都知道,gets()函数作用是输入字符串,而getchar()是输入单个字符。但在一个小程序中,我发现了它们两个一些别的用法。    因为源文件的代码很长,所以只打上源文件中涉及到这个问题的一个函数:    void input(num,name)    int num[];    char name[10][8]; {in
由一个switch语句理解c语言中getchar函数
调用getchar函数时
C语言中 scanf gets getchar 的区别
scanf: 原型:scanf("格式化字符串",地址表); 格式化字符说明 %d 十进制 整数 %o 八进制 %x 十六进制 %f 浮点型 %c 字符 %s 字符串 地址表可以是指针或者是一个地址 特点:遇到回车 空格 tab键 会结束输入,结束后自动加'\0' gets: 原型:gets(指针或者地址) 特点:获取一个字符串,能够接收空格和tab建,但遇到
关于C语言里getchar和scanf的思考
今天在做《C primer plus》的课后习题的时候,有这样一道题: 编写一个程序读入一行输入,然后反向打印该行。 您可以把输入存储在一个char数组中;假定该行不超过255个字符。 回忆一下,您可以使用具有%c说明符的scanf()从输入中一次读入一个字符, 而且当您按下回车键时会产生换行字符(\n)。 按照题目要求 我编写了这样一段代码: /*编写一个程序读入一行输入,然后反向打