Chinaunix

标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问! [打印本页]

作者: stdlib.h    时间: 2005-08-12 12:42
提示: 作者被禁止或删除 内容自动屏蔽
作者: fsilence    时间: 2005-08-12 14:39
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
关于这个精华帖,我也说一下我的疑问

  1. #include <stdio.h>;

  2. int main(void)
  3. {
  4.   int i,j;
  5.   char c;
  6.   printf("\n do you want to cal:y/n \n");

  7.   while (c=getchar()=='y')
  8.   {
  9.       printf("input number:");
  10.       scanf("%d%d",&i,&j);
  11.       printf("i*j=%d",i*j);
  12.       setbuf(stdin, NULL);
  13.       printf("\n do you want to cal:y/n \n");
  14.   }
  15. /*system("pause");*/
  16.   return 0;
  17. }
复制代码

和程序段

  1. #include <stdio.h>;

  2. int main(void)
  3. {
  4.   int i,j;
  5.   char c;
  6.   printf("\n do you want to cal:y/n \n");
  7.   setbuf(stdin,NULL);

  8.   while (c=getchar()=='y')
  9.   {
  10.       printf("input number:");
  11.       scanf("%d%d",&i,&j);
  12.       printf("i*j=%d",i*j);
  13.       //setbuf(stdin, NULL);
  14.       printf("\n do you want to cal:y/n \n");
  15.   }
  16. /*system("pause");*/
  17.   return 0;
  18. }
复制代码

的效果是不是应该是一样的?
下面改动后的程序就不能治疗getchar()读到换行符的问题
作者: renstone921    时间: 2005-08-12 15:19
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
To stdlib.h: 我做测试的结果。gcc4, fedora4
97 10  0  0  0  0  0  0  0  0

To fsilence:
放到循环外,只清空了一次输入缓冲区。
循环内,每次重新输入前都清空。效果当然不一样。

while (c=getchar()=='y')这里,估计这不是你想要的
可能应当改成while ((c = getchar()) == 'y')
注意优先级。
作者: fsilence    时间: 2005-08-12 16:16
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
我贴的是转自精华帖的源码,没有注意优先级的问题,虽然那样写不好不规范,但是应该也没有错。
还有setbuf(stdin,NULL),含义是

1。每次调用时清空stdin缓存
还是
2。调用之后就能设置输入流没有缓存,为空缓存机制
作者: fsilence    时间: 2005-08-12 16:27
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
如果每次都要setbuf(stdin,NULL)才好用的话,那与getchar()一下那个换行符,也没什么本质区别
作者: stdlib.h    时间: 2005-08-12 16:33
提示: 作者被禁止或删除 内容自动屏蔽
作者: renstone921    时间: 2005-08-12 17:01
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
有三种类型的缓冲策略,它们是无缓冲,块缓冲和行缓冲。当输出流无缓冲时,信息在写的同时出现于目标文件或终端
       上;当是块缓冲时,字符被暂存,然后一起写入;当是行缓冲时,字符被暂存,直到要输出一个新行符,或者从任何与
       终 端 设 备 连 接 的 流 中 (典型的是 stdin) 读取输入时才输出。函数 fflush(3) 可以用来强制提前输出。(参见
       fclose(3)) 通常所有文件都是块缓冲的。当文件 I/O 操作在文件上发生时,将调用 malloc(3) ,获得一个缓冲。 如
       果流指向一个终端 (通常 stdout 都是这样),那么它是行缓冲的。标准错误流 stderr 默认总是无缓冲的。

       函数 setvbuf 可以用在任何打开的流上,改变它的缓冲。参数 mode 必须是下列三个宏之一:

              _IONBF 无缓冲

              _IOLBF 行缓冲

              _IOFBF 完全缓冲

       除 非是无缓冲的文件,否则参数 buf 应当指向一个长度至少为 size 字节的缓冲;这个缓冲将取代当前的缓冲。如果
       参数 buf 是 NULL ,只有这个模式会受到影响;下次 read 或 write 操作还将分配一个新的缓冲。函数 setvbuf  只
       能在打开一个流,还未对它进行任何其他操作之前使用。

       其他三个函数调用是函数 setvbuf 的别名,函数 setbuf 与使用下列语句完全等价:

              setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);

       函 数 setbuffer 与此相同,但是缓冲的长度由用户决定,而不是由默认值 BUFSIZ 决定。函数 setlinebuf 与使用下
       列语句完全等价:

              setvbuf(stream, (char *)NULL, _IOLBF, 0);

个人认为,应当调用的是fflush(stdin)而不是setbuf;
作者: fsilence    时间: 2005-08-12 17:13
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
首先,不能用fflush,fflush只能对用户缓冲区而且是写缓冲进行刷新,
man fflush的结果:
The  function  fflush forces a write of all user-space buffered data for the given  output or update stream via the stream's underlying write function.
关于我的那个疑问,希望大家能仔细看看;希望大家对精华帖的对换行符的"治本"处理的那部分仔细考证一下,记住一个错误的知识点就不好了

To:楼主
   我在RH7.3,gcc 2.96上试,输出是一个10,不是两个10,跟renstone921的结果一样,怀疑是windows系统跟linux系统的机制哪里不一样。
作者: fsilence    时间: 2005-08-12 17:17
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
然后,我把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码!

关于输出的是每个输入字符的ASCII码,这个倒很正常,因为我们从键盘上敲入的本来就是ASCII码,只是scanf这个函数对这些ASCII数字做了处理,能做特定的类型转换;你如果把这个输入流输出的话,肯定还是ASCII码的
作者: fsilence    时间: 2005-08-12 17:30
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
我现在的看法是:
从man的输出看,setbuf(stdin,NULL)是设置标准输入无缓存;
但从程序结果来看,setbuf貌似只是清空缓存流;
所以让我很疑惑。
作者: renstone921    时间: 2005-08-12 17:34
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
麻烦在对一下info fflush.
作者: fsilence    时间: 2005-08-12 18:21
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
我的没什么不一样
作者: kukucm    时间: 2005-08-12 19:34
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
个人认为,应当调用的是fflush(stdin)而不是setbuf;


// fflush有个动作是对缓冲区中的所有数据写入流
写入输入流是没有意义的,是无定义的,但是很多系统通常是忽略,这个造成很多人fflush(stdin)

我到如今还没有发现怎么晴空,我一般都是直接fseek到流的末尾,我自认为这样是合理的,////希望高手指点.
作者: stdlib.h    时间: 2005-08-12 22:05
提示: 作者被禁止或删除 内容自动屏蔽
作者: stdlib.h    时间: 2005-08-12 22:19
提示: 作者被禁止或删除 内容自动屏蔽
作者: zlrll    时间: 2005-08-13 07:52
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
原帖由 "stdlib.h" 发表:

然后,我把c=getchar()改成了scanf("%d",&i);
运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
97 10 10 10 0 0 0 0 0 0
over

改成了scanf("%d",&i)后,在我的机子上输15回车马上就输出了
49 53 10 10 0 0 0 0 0 0
xp+vc6
作者: fsilence    时间: 2005-08-13 09:36
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
To kukucm:
    我在我的RH7.3上试过了你说的用fseek的方法,结果是fseek(stdin,0,2)返回-1;我觉得应该是不能对标准输入流进行fseek操作。不知道你以前试过没有。
To stdlib.h:
>;>;如果每次都要setbuf(stdin,NULL)才好用的话,那与getchar()一下那个换行符,也没什么本质区别   
我这句话只是针对精华帖帖出来的那个程序而言,因为那个程序只有再getchar一个换行符就行了。你说的循环getchar直到读到换行符以后终止当然可以了。
作者: fsilence    时间: 2005-08-13 09:47
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
然后,我把c=getchar()改成了scanf("%d",&i);
运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
97 10 10 10 0 0 0 0 0 0
over
这下我就更糊涂了,为什么要输入两次才有反应?那个15跑哪去了?缓冲区中为什么会有三个换行符?

怀疑是这次实验你的操作有误,我在vc6上的实验结果与zlrll 完全一致。
至于为什么会有两个10,怀疑是setbuf的实现上windows下的与linux的不一致
作者: stdlib.h    时间: 2005-08-13 12:39
提示: 作者被禁止或删除 内容自动屏蔽
作者: stdlib.h    时间: 2005-08-13 13:03
提示: 作者被禁止或删除 内容自动屏蔽
作者: fsilence    时间: 2005-08-13 18:55
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
再顶一下,为什么没有人解答呢?高手们都去哪儿了,都放假了吗?
作者: kernelxu    时间: 2005-08-14 11:10
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
几天没来,发现这么多关于stream和buffer的问题,首先谢谢大家提出这么多好问题。
我在这方面也不是高手,但我会尽我所能争取能和大家一道解决好这个问题。
对于楼主stdlib.h的疑问:

1、
我的理解是:一旦执行到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

你的理解是错误的,getchar()不是取走了'a',而只是读取了它。在缓冲区刷新之前,所有输入的字符都存在于缓冲区之中。标准输入缓冲区的刷新大体可分为系统刷新和人为刷新,系统刷新需遵循一定的规则(我正在思索中),而标准C语言对于人为刷新标准输入缓冲区(fflush(stdin))是未定义的。所以精华贴的实例中不可用fflush(stdin)。但是,若我们使用setbuf(stdin, buf)来修改系统提供的缓冲区为我们指定的缓冲区,我猜想这时候可以使用fflush(stdin),我已试验了几例都可以,哪位仁兄可以帮忙在linux下试试,我的系统坏了。
       下次读取缓冲区哪一个单元是由stdin的文件结构体中的位置指针来指示的。所以缓冲区中的数据是依次读取的。
       再者,为什么这里有两个‘10’,一个是敲入的回车转换来的,这个大家都知道。另一个我认为是与系统有关系,是由的系统内部自己加上的,为什么呢?我猜想(正在查找原因)是因为在自定义的缓冲区中(buf[10]),那些未用的单元要么存储着初值要么存储着未初始化造成的垃圾数据,系统加入‘10’就是为了避免这些垃圾数据被“悄悄地读取”。

2、
然后,我把c=getchar()改成了scanf("%d",&i);
   运行后输入一个数,如15,回车!嗯?没反应,光标往下移了一行!我再输入一个数或者字符如'a',再回车,程序才接着往下走,打印出如下结果:
  97 10 10 10 0 0 0 0 0 0
  over
  这下我就更糊涂了,为什么要输入两次才有反应?那个15跑哪去了?缓冲区中为什么会有三个换行符?
我又试着这样运行:输入15 25再回车,马上就有结果了:

我怀疑是你的程序问题:我没有这种问题。你是不是scanf()上面还有个getchar()啊?

3、
2:还有一个问题就是使用setbuf(stdin,NULL);关掉标准输入的行缓冲功能后,到底输入的过程是怎样的,为什么它就能解决c=getchar()后残留的那个回车符问题?

setbuf(stdin,NULL);是设定stdin流缓冲区的大小为0,也就是使其变成无缓冲的。
作者: kernelxu    时间: 2005-08-14 11:57
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
对于fsilence的疑问:
的效果是不是应该是一样的?
下面改动后的程序就不能治疗getchar()读到换行符的问题


1、
setbuf()的设置在整个main()函数中都有效。也就是说当程序执行完毕后,操作系统收回对标准输入缓冲区的控制权,恢复系统默认的缓冲区设置。但一定要在流已被打开后调用(这是十分明显的,因为每个函数都要求一个有效的文件指针作为它们的第一个参数),而且也应在对该流执行任何一个其他操作之前调用。
2、
所以,在main()函数中使用一次即可。
3、
为什么

  1. #include <stdio.h>;

  2. int main(void)
  3. {
  4. int i,j;
  5. char c;
  6. printf("\n do you want to cal:y/n \n");
  7. setbuf(stdin,NULL);

  8. while (c=getchar()=='y')
  9. {
  10.      printf("input number:");
  11.      scanf("%d%d",&i,&j);
  12.      printf("i*j=%d",i*j);
  13.      //setbuf(stdin, NULL);
  14.      printf("\n do you want to cal:y/n \n");
  15. }
  16. /*system("pause");*/
  17. return 0;
  18. }
复制代码

这个有问题,是因为这里面可能还涉及到一个问题:
程序设定输入不缓冲并不表示操作系统shell也不缓冲,而且还可能涉及到硬件缓冲的问题。引用一外国朋友Walter Roberson的话:
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.

还得仔细研究一下。
哪位高人也指点一下吧。
作者: fsilence    时间: 2005-08-14 13:52
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
首先,赞一下kernelxu的解释,很详细,个人觉得也很有道理,虽然想不通的问题依然存在
若我们使用setbuf(stdin, buf)来修改系统提供的缓冲区为我们指定的缓冲区,我猜想这时候可以使用fflush(stdin),我已试验了几例都可以,哪位仁兄可以帮忙在linux下试试,我的系统坏了。

我在精华贴的源码基础上稍作修改

  1. int main(void)
  2. {
  3.   int i,j;
  4.   char c;
  5.   char buffer[1024];

  6.   printf("\n do you want to cal:y/n \n");
  7.   setbuf(stdin,buffer);

  8. while ((c=getchar())=='y')
  9.   {
  10.       printf("input number:");
  11.       scanf("%d%d",&i,&j);
  12.       printf("i*j=%d",i*j);
  13.       fflush(stdin);
  14.       printf("\n do you want to cal:y/n \n");
  15.       for(i=0;i<10;i++)
  16.         printf("%d ",buffer[i]);
  17.       printf("\n");
  18.   }

  19. }
复制代码

结果是:又是运行一次就退出了;我的i,j输入的是1和2,printf那个buffer的结果是
50 10 0 0 0 0 0 0 0 0
说明fflush(stdin)还是不好用
作者: mq110    时间: 2005-08-14 14:05
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
楼上的兄弟 运行程序的平台是什么?

可能是未实现 对stdin 做fflush. 不同的平台实现不同吧.
作者: kernelxu    时间: 2005-08-14 14:23
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
原帖由 "fsilence" 发表:
结果是:又是运行一次就退出了;我的i,j输入的是1和2,printf那个buffer的结果是
50 10 0 0 0 0 0 0 0 0
说明fflush(stdin)还是不好用

我在DEV-C++下执行没有问题很好用的。不知你是在什么环境下。
不过,这也是我的一个猜想而已,既然能找到不能实现的例子,那么也就说明我的猜想有问题,至于说是什么原因,大家不妨继续探讨。
作者: fsilence    时间: 2005-08-14 16:05
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
很不好意思的说,我的平台很老,RH7.3,gcc 2.96
作者: stdlib.h    时间: 2005-08-15 09:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: albcamus    时间: 2005-08-15 10:23
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
kernelxu兄弟是不是comp.lang.c上的kernelxu?呵呵我不小心认出来了
作者: kernelxu    时间: 2005-08-15 12:44
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
原帖由 "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下试试,我的系统坏了。

所以这种猜测是错误的,不可仿效。至于说MSDN说可以fflush(stdin),估计是
MS的VC的特性吧,但这样编出的程序也就只能属于VC了。
2、为什么C标准规定fflush(stdin)是未定义的呢?其实,fflush()对其他流的刷新也有可能会失败。以下给出几类fflush()可能失败的情况:

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.


3、
关于函数setbuf(stream, buf)和setvbuf(stream, buf, mode, BUFSIZ)
1)   setbuf(stream, buf)中,当buf不是空指针时,它应该(shall be)等同于setvbuf(stream, buf, _IOFBF, BUFSIZ);setbuf(stream, buf)中,当buf是空指针时,它应该(shall be)等同于setvbuf(stream, buf, _IONBF, BUFSIZ).
2)   setbuf(stream, buf)中buf的大小至少应为BUFSIZ(DEV-C++为512bytes),所以前面讨论的设置buf[10]对于普通PC机是错误的,自己定义缓冲区大小应比标准规定的大(C89规定为256bytes)。
3)   还有一点需要注意:调用setbuf()分配的BUFSIZ个字节的空间不一定表示这些空间都来用作缓冲区(With setbuf(), allocating a buffer of BUFSIZ bytes does not necessarily imply that all of BUFSIZ bytes are used for the buffer area.《http://www.opengroup.org/onlinep ... nctions/setbuf.html》)


4)   像楼主的程序中在main()函数内部调用setbuf(stream, buf),buf声明为一个局部变量是有问题的,因为是操作系统来完成流操作的大部分后台(关闭、打开等)工作。main()函数完成后,buf被释放,操作系统就找不到了流的缓冲区,这样一来就引发了错误。所以自定义缓冲区一定得是全局变量或静态变量。
引用Eric Sosman的话:
      
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.)

作者: kernelxu    时间: 2005-08-15 13:48
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
又看了看C-FAQ:
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    时间: 2005-08-15 18:23
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
是不是可以理解为:既然setbuf(stdin,NULL)没能实现重置标准输入为空缓存的功能,所以对于没有证实为对的东西,还是不要使用;免得以后出现莫名其妙的错误;还是老老实实的getchar()吧;
建议对setbuf(stdin,NULL)的问题在精华区做一下说明,不要为后来者产生误导;知识还是要证实是对的之后才可用
作者: stdlib.h    时间: 2005-08-15 21:15
提示: 作者被禁止或删除 内容自动屏蔽
作者: kernelxu    时间: 2005-08-16 10:02
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
原帖由 "fsilence" 发表:
是不是可以理解为:既然setbuf(stdin,NULL)没能实现重置标准输入为空缓存的功能,所以对于没有证实为对的东西,还是不要使用;免得以后出现莫名其妙的错误;还是老老实实的getchar()吧;
建议对setbuf(stdin,NULL)?.........


这样理解是不对的。
setbuf(stdin, NULL)和fflush(stdin)是不一样的。
1、fflush()是完成写入,而fflush(stdin)未定义是因为它没有完成写入的对象(fflush(stdout)可以将未读取的内容直接写到终端屏幕,可是fflush(stdin)往哪里写呢?)。
2、而setbuf(stdin, NULL)等效于setvbuf(stream, buf, _IONBF, BUFSIZ)它是设置stdin为无缓冲类型,也就是不接受多余的内容。也就不存在要刷新缓冲区或丢弃未读字符等问题了。

所以,setbuf(stdin, NULL)是可以用的,只不过效率较低。
作者: fsilence    时间: 2005-08-16 14:30
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
可是如果setbuf(stdin,NULL)就是设置stdin为空缓存模式,那么为什么只设一次时没有成功,只有每次setbuf(stdin,NULL)才好用,难道还能说setbuf(stdin,NULL)是好用的吗?
这样理解是不对的。
setbuf(stdin, NULL)和fflush(stdin)是不一样的。

我从来没说过setbuf(stdin, NULL)和fflush(stdin)是一样的
作者: kukucm    时间: 2005-08-16 19:10
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
1、fflush()是完成写入,而fflush(stdin)未定义是因为它没有完成写入的对象(fflush(stdout)可以将未读取的内容直接写到终端屏幕,可是fflush(stdin)往哪里写呢?)。



这个是我想到的 不知道对不?
fseek应该行的啊。到末尾,可是我没有实验,刚才那位朋友说不行
作者: fsilence    时间: 2005-08-16 20:07
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
楼上的朋友,那为什么不试试呢,大家对照一下结果。我试的结果是fseek返回-1
我记得以前看哪本书上也写的是fseek对标准输入流无效。
作者: kernelxu    时间: 2005-08-17 15:04
标题: 看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
可是如果setbuf(stdin,NULL)就是设置stdin为空缓存模式,那么为什么只设一次时没有成功,只有每次setbuf(stdin,NULL)才好用,难道还能说setbuf(stdin,NULL)是好用的吗?



谢谢fsilence兄的建议。问题之大,已无法修补。
sebuf(stdin,NULL)确实存在问题,我从comp.lang.c上得到了答案。
大家可以去看一看
http://groups-beta.google.com/gr ... 1051c26299b4c?hl=en
中Walter Roberson的精彩发言。
由于都是英文,我正在消化中。等一阵子我把它翻译出来在分享给各位朋友。

为不误人子弟,恳请版主删掉精华贴中的《关于流和缓冲区的理解以及一般标准输入问题的解决方法小结 》一篇,里面存在很大的问题,待我修缮后再发上来。
作者: differtel    时间: 2011-11-28 16:05
就是都没有清除缓存的方法?只是能够设置为无缓存方式?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2