免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
21 [报告]
发表于 2007-05-03 17:30 |只看该作者
原帖由 kernelxu 于 2005-8-3 21:39 发表
这个程序存在问题,这里使用setbuf()来“治疗”:

#include <stdio.h>;

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

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


粗粗的看了一下帖子,LZ似乎是在说使用 setbuf / setvbuf 清空输入流。不过上面举的这个例子也是不符合标准的。

From C99
Description
The setvbuf function may be used only after the stream pointed to by stream has
been associated with an open file and before any other operation (other than an
unsuccessful call to setvbuf) is performed on the stream
.

Description
Except that it returns no value, the setbuf function is equivalent to the setvbuf
function invoked with the values _IOFBF for mode and BUFSIZ for size,or(if buf
is a null pointer), with the value _IONBF for mode.


显然,上例在调用 setbuf(stdin, NULL); 之前,scanf("%d%d",&i,&j); 就已经对 stdin 进行了操作,与标准的定义不符合。

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
22 [报告]
发表于 2007-05-03 17:58 |只看该作者
原帖由 antigloss 于 2007-5-3 17:30 发表


粗粗的看了一下帖子,LZ似乎是在说使用 setbuf / setvbuf 清空输入流。不过上面举的这个例子也是不符合标准的。



显然,上例在调用 setbuf(stdin, NULL); 之前,scanf("%d%d",&i,&j) ...

在这里使用 setbuf/setvbuf 确实是不妥的。

关于如何清空标准输入,可以参看 comp.lang.c 的 FAQ:
Question 12.26b
Q: If fflush won't work, what can I use to flush input?

A: It depends on what you're trying to do. If you're trying to get rid of an unread newline or other unexpected input after calling scanf (see questions 12.18a-12.19), you really need to rewrite or replace the call to scanf (see question 12.20). Alternatively, you can consume the rest of a partially-read line with a simple code fragment like

        while((c = getchar()) != '\n' && c != EOF)
                /* discard */ ;

(You may also be able to use the curses flushinp function.)

There is no standard way to discard unread characters from a stdio input stream. Some vendors do implement fflush so that fflush(stdin) discards unread characters, although portable programs cannot depend on this. (Some versions of the stdio library implement fpurge or fabort calls which do the same thing, but these aren't standard, either.) Note, too, that flushing stdio input buffers is not necessarily sufficient: unread characters can also accumulate in other, OS-level input buffers. If you're trying to actively discard input (perhaps in anticipation of issuing an unexpected prompt to confirm a destructive action, for which an accidentally-typed ``y'' could be disastrous), you'll have to use a system-specific technique to detect the presence of typed-ahead input; see questions 19.1 and 19.2. Keep in mind that users can become frustrated if you discard input that happened to be typed too quickly.

References: ISO Sec. 7.9.5.2
H&S Sec. 15.2

论坛徽章:
0
23 [报告]
发表于 2007-12-17 13:58 |只看该作者

呵呵.....太好了, 真是值得收藏,

论坛徽章:
0
24 [报告]
发表于 2007-12-17 18:59 |只看该作者
今天正好看了一遍流..

我认为流就是引用打开文件的一种方式,就像文件描述符其实就是已打开文件的号码一样.
以这种方式打开文件后,就以进行以后的标准I/O读写了..

论坛徽章:
0
25 [报告]
发表于 2007-12-17 19:43 |只看该作者
以fopen方式打开文件,内核一样会分配这个文件一个文件描述符,通过引用这个文件描述符照样可以通过write来写这个文件

  1. #include    <stdio.h>
  2. #include    <fcntl.h>

  3. int
  4. main(void)
  5. {
  6.     int fd;
  7.     char buf[]="0123456789";

  8.     if ((fd = open("t1.c", O_RDONLY)) < 0) {
  9.         printf("open t1.c error\n");
  10.         exit(1);
  11.     }
  12.     else   
  13.         printf("fd1 = %d,", fd);
  14.     if (fopen("t2.c", "w") == NULL) {
  15.         printf("open t2.c error\n");
  16.         exit(2);
  17.     }
  18.     if ((fd = open("t3.c", O_RDONLY)) < 0) {
  19.         printf("open t3.c error\n");
  20.         exit(3);
  21.     }
  22.     else   
  23.         printf("fd2 = %d\n", fd);
  24.     if (write(4, buf, 10) != 10) {
  25.         printf("write error\n");   
  26.         exit(5);
  27.     }
  28.     exit(0);
  29. }
  30. [root@mylinux ap]# ./a.out
  31. fd1 = 3,fd2 = 5
复制代码

[ 本帖最后由 xi2008wang 于 2007-12-17 19:44 编辑 ]

论坛徽章:
0
26 [报告]
发表于 2009-01-01 15:27 |只看该作者
精华,绝对的精华。

论坛徽章:
0
27 [报告]
发表于 2012-04-08 21:50 |只看该作者
真是篇难得一见的好文章

论坛徽章:
0
28 [报告]
发表于 2012-05-06 23:14 |只看该作者
谢谢,确实不错,应该顶起
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP