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

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

HughKirk
HughKirk 谢谢~
大约一年之前 回复
weixin_36183906
weixin_36183906   2016.09.19 23:31

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

HughKirk
HughKirk 恩恩,谢谢您。我知道了。
大约一年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!