然后,我把c=getchar()改成了scanf("%d",&i);
运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
97 10 10 10 0 0 0 0 0 0
over
这下我就更糊涂了,为什么要输入两次才有反应?那个15跑哪去了?缓冲区中为什么会有三个换行符?
我又试着这样运行:输入15 25再回车,马上就有结果了:
49 53 32 50 53 10 10 0 0 0
over
分别对应着每一个输入字符的ASC码!
原帖由 "stdlib.h" 发表:
然后,我把c=getchar()改成了scanf("%d",&i);
运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
97 10 10 10 0 0 0 0 0 0
over
然后,我把c=getchar()改成了scanf("%d",&i);
运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
97 10 10 10 0 0 0 0 0 0
over
这下我就更糊涂了,为什么要输入两次才有反应?那个15跑哪去了?缓冲区中为什么会有三个换行符?
我的理解是:一旦执行到getchar()这个语句,getchar()首先去查看缓冲区看有没有数据,如果没有,就让用户用标准输入键盘输入数据,一旦检测到有敲“回车”这个动作,就认为输入结束,然后把这一串输入(包括一个'a' 97 和一个回车符CR 10)当作字节流送到缓冲区中去,然后程序从缓冲区中读取数据,由于getchar()只读取一个字符,所以CR就被留在了缓冲区中,这样会引发一些问题,所以kenelxu在精华区的那个帖子中详细的讨论了如何解决这个问题,比如在后面加一个getchar()吃掉这个回车符,这也是最不保险的办法。
但是,我的理解却是错的!
通过打印buf的值,发现是:
97 10 10 0 0 0 0 0 0 0
over
按我的理解,应该是:
10 0 0 0 0 0 0 0 0 0
over
然后,我把c=getchar()改成了scanf("%d",&i);
运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
97 10 10 10 0 0 0 0 0 0
over
这下我就更糊涂了,为什么要输入两次才有反应?那个15跑哪去了?缓冲区中为什么会有三个换行符?
我又试着这样运行:输入15 25再回车,马上就有结果了:
2:还有一个问题就是使用setbuf(stdin,NULL);关掉标准输入的行缓冲功能后,到底输入的过程是怎样的,为什么它就能解决c=getchar()后残留的那个回车符问题?
的效果是不是应该是一样的?
下面改动后的程序就不能治疗getchar()读到换行符的问题
you generally need to enter a newline after the initial 'y' because although the input might not be "buffered" by the time it gets to your program, it might be buffered at the shell -- setting
stdin to be unbuffered is *not* the same as undertaking system-
specific methods to turn on "raw" mode.
若我们使用setbuf(stdin, buf)来修改系统提供的缓冲区为我们指定的缓冲区,我猜想这时候可以使用fflush(stdin),我已试验了几例都可以,哪位仁兄可以帮忙在linux下试试,我的系统坏了。
原帖由 "fsilence" 发表:
结果是:又是运行一次就退出了;我的i,j输入的是1和2,printf那个buffer的结果是
50 10 0 0 0 0 0 0 0 0
说明fflush(stdin)还是不好用
原帖由 "albcamus"]kernelxu兄弟是不是comp.lang.c上的kernelxu?呵呵我不小心认出来了[/quote 发表:
呵呵,这也被老大人出来了。不知老大在上面是什么马甲,能不能站内短信告知一下,以后说不定就“撞车”了。![]()
自己有些东西也搞不清,就在comp.lang.c上发了一个贴。
大家也可以看一看别人的解答:
http://groups-beta.google.com/gr ... en#6b7dfa8b01784910
我将解答总结在下面,希望对大家理解setbuf()和setvbuf()有所帮助。
1、C标准(ISO/IEC 9899:1999 standard)规定fflush(stdin)操作是未定义的<参看《ISO/IEC 9899:1999 standard》p270>;。也就是说不一定能实现刷新功能,但有的编译器可能不遵循标准,对fflush(stdin)操作不予警告,并且有时可能产生正确的结果,但最好不要这样使用。
[quote]若我们使用setbuf(stdin, buf)来修改系统提供的缓冲区为我们指定的缓冲区,我猜想这时候可以使用fflush(stdin),我已试验了几例都可以,哪位仁兄可以帮忙在linux下试试,我的系统坏了。
The fflush() function shall fail if:
[EAGAIN]
The O_NONBLOCK flag is set for the file descriptor underlying stream and the thread would be delayed in the write operation.
[EBADF]
The file descriptor underlying stream is not valid.
[EFBIG]
An attempt was made to write a file that exceeds the maximum file size.
[EFBIG]
An attempt was made to write a file that exceeds the process' file size limit.
[EFBIG]
The file is a regular file and an attempt was made to write at or beyond the offset maximum associated with the corresponding stream.
[EINTR]
The fflush() function was interrupted by a signal.
[EIO]
The process is a member of a background process group attempting to write to its controlling terminal, TOSTOP is set, the process is neither ignoring nor blocking SIGTTOU, and the process group of the process is orphaned. This error may also be returned under implementation-defined conditions.
[ENOSPC]
There was no free space remaining on the device containing the file.
[EPIPE]
An attempt is made to write to a pipe or FIFO that is not open for reading by any process. A SIGPIPE signal shall also be sent to the thread.
The fflush() function may fail if:
[ENXIO]
A request was made of a nonexistent device, or the request was outside the capabilities of the device.
You've asked stdin to use a buffer that will cease to exist as soon as main() returns, but when main() returns stdin is still "alive" and hasn't been closed. If any shutting-down operations try to make use of the now- vanished buffer, there's no telling what could happen. (True, this is usually more troublesome for output streams than for input, but you're begging for trouble.)
Question 12.26
How can I flush pending input so that a user's typeahead isn't read at the next prompt? Will fflush(stdin) work?
--------------------------------------------------------------------------------
fflush is defined only for output streams. Since its definition of ``flush'' is to complete the writing of buffered characters (not to discard them), discarding unread input would not be an analogous meaning for fflush on input streams.
There is no standard way to discard unread characters from a stdio input stream, nor would such a way be sufficient unread characters can also accumulate in other, OS-level input buffers.
fflush函数仅仅对于输出流是确定的,由于它对“刷新”的定义是完成缓冲字符的写入(而非丢弃这些字符),在输入流上应用fflush函数也不是意味着抛弃未读取的输入信息。
没有一种标准的方法可以去除来自标准输入流的未读取字符,也可能没有哪种方法能将未读取字符积攒在操作系统级的输入缓冲区中。
``C takes the point of view that the programmer is always right. ''
-- Michael DeCorte
原帖由 "fsilence" 发表:
是不是可以理解为:既然setbuf(stdin,NULL)没能实现重置标准输入为空缓存的功能,所以对于没有证实为对的东西,还是不要使用;免得以后出现莫名其妙的错误;还是老老实实的getchar()吧;
建议对setbuf(stdin,NULL)?.........
这样理解是不对的。
setbuf(stdin, NULL)和fflush(stdin)是不一样的。
可是如果setbuf(stdin,NULL)就是设置stdin为空缓存模式,那么为什么只设一次时没有成功,只有每次setbuf(stdin,NULL)才好用,难道还能说setbuf(stdin,NULL)是好用的吗?
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |