标题:[求助]关于putchar()和getchar()..
只看楼主
xiaoyunhu
Rank: 1
等 级:新手上路
帖 子:39
专家分:0
注 册:2006-9-24
 问题点数:0 回复次数:6 
[求助]关于putchar()和getchar()..

请大家看下面的一个程序:
#include <stdio.h>
void main()
{
char c;
while((c=getchar())!=EOF)
putchar(c);
}
我的本意是从键盘上敲一个字符就在屏幕上显示一个字符,比如说我敲入:
a
回车后屏幕上有两个a,这个我可以理解,因为一个是我输入的,一个是程序输出的;
可是我敲入aaaaaaa时,回车后屏幕上显示了两行aaaaaaa
我想问的是:程序中的c不是单字符变量么?为什么可以存放这么多的字符?

搜索更多相关主题的帖子: getchar putchar 
2006-10-05 21:20
mp3aaa
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:2013
专家分:8
注 册:2006-2-15
得分:0 
你着不就是循环吗?

羊肉串 葡萄干 哈密瓜!!
2006-10-05 21:40
mp3aaa
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:2013
专家分:8
注 册:2006-2-15
得分:0 
#include <stdio.h>
void main()
{
char c;
c=getchar() ;
putchar(c);
}
这样就可以了

羊肉串 葡萄干 哈密瓜!!
2006-10-05 21:40
nuciewth
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:我爱龙龙
等 级:贵宾
威 望:104
帖 子:9786
专家分:208
注 册:2006-5-23
得分:0 
你输入一个字符,然后换行不就有字符显示了.

倚天照海花无数,流水高山心自知。
2006-10-05 23:10
hzwk0814
Rank: 1
等 级:新手上路
帖 子:18
专家分:0
注 册:2006-9-27
得分:0 
和我碰到的问一样
不过现在改了
呵呵 纳闷呢~~怎么多出了2行呢
2006-10-06 01:16
ChenMo
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:3
帖 子:481
专家分:10
注 册:2004-4-8
得分:0 
一、getchar 函数

从书本上获得关于 getchar 函数的知识是如此说明的:getchar() 函数将从标准设备中读入一个字符,这里所谓的标准设备指的是键盘。当然也有其他一些关于介绍 getchar() 函数的不同于前的说法,然而不过是笔墨不同,意思是一样的。

getchar() 函数是从缓冲字节流(Stream)中读入字符,C语言以文件流(字节流)来维护设备的数据,在调用 getchar() 函数时,你可以输入一个以上的字符,它们将缓冲到标准输入流(stdin)中,然而 getchar() 函数每次被调用时只会从输入流中读取(函数返回)一个字符,剩余的字符将在下一次被调用时读取,直到读至文件流的尾部(文件流尾部的标志是 EOF),事实上,程序执行中会先判断缓冲区是否为空(检查 FILE 结构的 level 属性),若不为空则取出一个字符,否则调用 _fgetc() 函数向设备读取字符。

getchar() 函数事实上不是一个函数,它是一个宏,被定义在 stdio.h 头文件中,如下:
#define getchar() getc(stdin)

getc(stdin) 在预处理时将替换 getchar(),这在编译前便已经被处理了。
再深入一些,getc() 也不是函数,它与 getchar() 一样,是一个宏,getc() 的宏定义如下:
#define getc(f) \
((--((f)->level) >= 0) ? (unsigned char)(++(f)->curp)[-1] : \
_fgetc (f))

_fgetc() 函数在 stdio.h 头文件如下被声明:
int _Cdecl _fgetc (FILE *stream);

可以猜测得到 _fgetc() 函数遇到回车即刻返回。

stdin 是标准输入流,除了标准输入流外,还有标准输出流(stdout),标准错误输出流(stderr),标准打印流(stdptr),标准辅助设备流(stdaux)。
这五个标准流在 stdio.h 头文件如下被定义(它们也是宏):
#define stdin (&_streams[0])
#define stdout (&_streams[1])
#define stderr (&_streams[2])
#define stdaux (&_streams[3])
#define stdprn (&_streams[4])

_streams 是由外部(系统)定义的 FILE(文件)结构类型的一个数组,它在 stdio.h 中定义如下:
extern FILE _Cdecl _streams[];

getchar() 获得字符是通过读取标准输入文件流,标准输入文件流将缓冲所输入的字符(回车结束输入),下一次调用 getchar() 函数时将从流中读取,除非缓冲区已为空,若缓冲区已为空则调用 _fgetc() 函数读入,_fgetc() 函数将客户所输入的字符缓冲到标准输入文件流,_fgetc() 函数直到遇到回车才结束。


二、while 循环的条件:(c=getchar())!=EOF

首先需要知道一点就是,EOF 是一个宏,在 stdio.h 头文件中被定义为 -1,宏定义如下:
#define EOF (-1)

这个程序与《C陷阱与缺陷》一书中第五章 5.1 节 中的程序几乎是一样的,我将在下面引用该书的相关内容,在引用之前,我补充说明一下,我们是无法直接从键盘上输入 -1 这个值,因为键盘上并没有“-1”这个键,若无法输入,则该循环将会是个死循环,按 Ctrl+Z(屏幕上将显示^Z) 可以向缓冲区插入 EOF 标志。若输入 abcd^Zefgh,即在输入 abcd后按Ctrl+Z,然后再输入 efgh,那么缓冲区中虽然存放了以上字符,然而文件读到d 之后,将认为文件已经读到尾部,所以若要输出的话,将只输出 abcd。

以下摘录该书原中文版的说明,你便可以知道这个条件的可能存在的问题(或许这个问题并不是你所关心的):

5.1 返回整数的 getchar 函数

我们首先考虑下面的例子:
#include <stdio.h>
main()
{
char c;
while((c=getchar()) != EOF)
putchar(c);
}

getchar 函数在一般情况下返回的是标准标准输入文件(流)中的下一个字符,当没有输入时返回 EOF(一个在头文件 stdio.h 中被定义的值,不同于任何一个字符)。这个程序乍一看似乎是把标准输入复制到标准输出,实则不然。
原因在于程序中的变量 c 被声明为 char 类型,而不是 int 类型。这意味着 c 无法容下所有可能的字符,特别是,可能无法容下 EOF。
因此,最终结果存在两种可能。一种可能是,某些合法的输入字符在被“截断”后使得 c 的取值与 EOF 相同;另一种可能是,c 根本不可能取到 EOF 这个值。对于前一种情况,程序将在文件复制的中途终止;对于后一种情况,程序将陷入一个死循环。
实际上,还有可能存在第三种情况:程序表面上似在能够正常工作,但完全是因为巧合。尽管函数 getchar() 的返回结果在赋给 char 类的变量 c 时会发生 “截断”操作,尽管 while 语句中比较运算的操作数不是函数 getchar 的返回值,而是被“截断”的值 c,然而令人惊讶的是许多编译器对上述表达式的实现并不正确。这些编译器确实对函数 getchar 的返回值作了“截断”处理,并把低端字节部分赋给了变量 c。但是,它们在比较表达式中并不是比较 c 与 EOF,而是比较 getchar 函数的返回值与 EOF!编译器如果采取的是这种做法,上面的例子程序看上去就能够“正常”运行了。

[此贴子已经被作者于2006-10-6 4:19:06编辑过]


欢迎加入 MVC 技术讨论群(新群:90093426)
2006-10-06 03:38
xiaoyunhu
Rank: 1
等 级:新手上路
帖 子:39
专家分:0
注 册:2006-9-24
得分:0 

多谢楼上的朋友,我大概明白了...
同时也感谢所有朋友的解答!


小晕乎
2006-10-06 12:13



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-94393-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.388380 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved