免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2036 | 回复: 7

[C] 问题:使用read从控制终端读部分数据引发的问题 [复制链接]

论坛徽章:
0
发表于 2013-02-26 14:00 |显示全部楼层
本帖最后由 BillStone 于 2013-02-26 14:06 编辑

main从标准输入获取3个字节,继而退出:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>

  5. extern int errno;

  6. int main(void)
  7. {
  8.         char data[3];
  9.         int n;

  10. again:
  11.         while ( (n = read(STDIN_FILENO, data, 3)) < 0)
  12.         {
  13.                 if (EINTR == errno)
  14.                 {
  15.                         puts("get a signal.");
  16.                         goto again;
  17.                 }
  18.                 break;
  19.         }

  20.         puts("");
  21.         exit(0);
  22. }
复制代码
我的运行环境:Ubuntu 10.04LTS + gcc 4.4.3,运行效果如下:
  1. rockstone@rockstone-desktop:~/trash$ ./a.out
  2. 123abc
  3. rockstone@rockstone-desktop:~/trash$ abc
复制代码
可以看到,当输入123abc、键入Ctrl+D后,123被read读取,而剩余的abc则在main执行完毕后打印到终端,这是为什么?从什么资料可以找到答案?

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
发表于 2013-02-26 14:33 |显示全部楼层
目测程序没读走的东西, shell当做下一条命令了.

论坛徽章:
0
发表于 2013-02-26 15:00 |显示全部楼层
奥,大概明白了。
main返回后,由shell进程接手,它从标准输入等待命令的输入,而此时abc保留在标准输入缓冲区中,所以此时键入enter时,会把abc当做命令来解析。

to linux_c_py_php:
但还有个问题,为什么shell接手后还要将abc打印出来?

论坛徽章:
6
申猴
日期:2013-10-08 17:32:32金牛座
日期:2013-10-18 19:45:53天秤座
日期:2013-10-18 20:17:34处女座
日期:2014-02-11 10:10:29丑牛
日期:2014-02-15 10:44:15巳蛇
日期:2014-02-18 22:05:54
发表于 2013-02-26 15:38 |显示全部楼层
将puts("");改为getchar();用于接受回车字符,可以得到你想要的结果

论坛徽章:
0
发表于 2013-02-26 16:20 |显示全部楼层
to helpstudy:
  效果上有了,但有些不好理解:假如我键入了123abc^D后,调用getchar可以得到a,由shell接管后,标准输入缓冲区中应该还留着bc,显示中却没有,哪里去了?效果上貌似被清除了,什么时候被清除的? 什么资料上有提及?
  3x

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
发表于 2013-02-26 17:02 |显示全部楼层
回复 5# BillStone


    当你后来调用getchar()的时候,程序也应该会调用底层的read()函数。
    为了“效率”,我想read函数不会一次只读一个字符,而是一次读“若干”个字符,至于多少我也不清楚。
    因为在调用 getchar()后,后面的"abc"其实已经被读走了,所以后来就不会显示了。
    ====个人猜想====,未证实。

论坛徽章:
0
发表于 2013-02-26 20:18 |显示全部楼层
本帖最后由 BillStone 于 2013-02-26 21:03 编辑

回复 6# idi0t

假定在调用 getchar()后,后面的"abc"其实已经被读走了,那么当连续调用两次getchar时会发生什么呢?
从getchar的语义来看,它应该只读取一个字节,如果在getchar中使用read读取了多个字节(或者说剩下的字节),这有违getchar的语义。

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
发表于 2013-02-26 21:18 |显示全部楼层
回复 7# BillStone


    猜想在你的环境下,当调用getchar()的时候,猜想调用 read()的,比如说一次读1024个字符放入"buffer" ,而实际只剩下“abc",于是就只读了“abc"。
    读完后返回第一个字符的整型也是可以的,这并没有违背getchar()。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP