免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: kernelxu
打印 上一主题 下一主题

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2005-08-12 20:50 |只看该作者

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结

我喜欢这种精神

论坛徽章:
0
12 [报告]
发表于 2005-08-15 14:56 |只看该作者

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结

补充一点

希望对大家理解setbuf()和setvbuf()有所帮助。
1、C标准(ISO/IEC 9899:1999 standard)规定fflush(stdin)操作是未定义的<参看《ISO/IEC 9899:1999 standard》p270>;。也就是说不一定能实现刷新功能,但有的编译器可能不遵循标准,对fflush(stdin)操作不予警告,并且有时可能产生正确的结果,但最好不要这样使用。
引用:
若我们使用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.)  



更详细讨论见:
http://bbs.chinaunix.net/forum/v ... ff415a9b9814c9f8b07

论坛徽章:
0
13 [报告]
发表于 2005-08-22 18:01 |只看该作者

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结

自己试了一下,还有些不大明白。
环境:SunOS
代码:
#include <iostream>;
#include <stdio.h>;
using namespace std;
int main(int argc, char* argv[])
{
char c='\0';
puts("input your name:";
c=getchar();
cout<<c<<endl;
if(c=='c')
    {   cout<<"yes"<<endl;
    }
}

运行结果:
sr-bu-/export/home/daladmin/ct>; ./a.out
input your name:
c
c
yes

我输入c之后,敲回车,然后getchar 得到结果是‘c’并不是换行符。
键盘的回车,是被解析为什么?难道不是“\n”么?

初学c, 还请大虾指教

论坛徽章:
0
14 [报告]
发表于 2005-08-23 14:41 |只看该作者

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结

这不正好是对的吗
你输入的是c

论坛徽章:
0
15 [报告]
发表于 2005-10-28 13:18 |只看该作者

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结

多谢楼主,写得真是详细,顶!!!!

论坛徽章:
0
16 [报告]
发表于 2005-10-28 13:35 |只看该作者

关于流和缓冲区的理解以及一般标准输入问题的解决方法小结

多谢楼主,写得真是详细,顶!!!!

论坛徽章:
0
17 [报告]
发表于 2005-11-08 21:27 |只看该作者
#include <stdio.h>;

int main&#40;void&#41;
{
   int i,j;
   char c;
   printf&#40;"n do you want to cal&#58;y/n n"&#41;;

   while &#40;c=getchar&#40;&#41;=='y'&#41;
   {
       printf&#40;"input number&#58;"&#41;;
       scanf&#40;"%d%d",&i,&j&#41;;
       printf&#40;"i*j=%d",i*j&#41;;
       setbuf&#40;stdin, NULL&#41;;
       printf&#40;"n do you want to cal&#58;y/n n"&#41;;
   }
  /*system&#40;"pause"&#41;;*/
   return 0;
}

论坛徽章:
0
18 [报告]
发表于 2005-11-12 09:56 |只看该作者
厉害啊,
最近正好被这些问题搞的头荤.
先顶一下再细看

论坛徽章:
0
19 [报告]
发表于 2005-11-12 12:09 |只看该作者
向LZ学习

论坛徽章:
0
20 [报告]
发表于 2007-04-29 11:12 |只看该作者
最近遇到scanf无法获得正确输入的问题,这贴药治标治本,不可沉下去!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP