[问题]关于 getchar EOF ^D

软件和网站开发以及相关技术探讨
回复
头像
dickfisch
帖子: 110
注册时间: 2007-10-22 17:40

[问题]关于 getchar EOF ^D

#1

帖子 dickfisch » 2008-07-28 23:06

这样一段程序

代码: 全选

while((c = getchar()) != EOF)
{
    putchar(c);
}
运行输入

代码: 全选

abc + ^D
这个时候屏幕上马上显示

代码: 全选

abcabc
就是说按了^D后,程序把前面输入的内容送入缓冲,putchar函数立刻把输入的字符打在屏幕上了。

这比较清楚,但是如果是这样

代码: 全选

while((c = getchar()) != EOF)
{
    fputc (c, fp);  /* fp 是一个文件指针 */
}
那么输入

代码: 全选

abc + ^D
马上去查看文件,发现文件并没有被写入。一定要等输入流完全断了,文件才被写入。

请问这是为什么呢?为什么fput函数没有马上起作用?
头像
kofshower
帖子: 1343
注册时间: 2007-03-13 11:23
联系:

#2

帖子 kofshower » 2008-07-28 23:53

任何操作流的函数基本上都会被缓存的。自己看
/* Write a character to STREAM.

These functions are possible cancellation points and therefore not
marked with __THROW.

These functions is a possible cancellation point and therefore not
marked with __THROW. */
extern int fputc (int __c, FILE *__stream);
extern int putc (int __c, FILE *__stream);
而所谓的流本身有是些什么东西:
struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */

struct _IO_marker *_markers;

struct _IO_FILE *_chain;

int _fileno;
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */

#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];

/* char* _save_gptr; char* _save_egptr; */

_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
}
编程遇到不懂之处,自己跳转到库里面看看就很清楚了。
甚至不需要翻书
"We are all in the mud, but some of us are looking at the stars." (Oscar Wilde)
We are not born for ourselves.
人生天地间,并非为自己
Homepage:http://sites.google.com/site/polarisnotme/
头像
dickfisch
帖子: 110
注册时间: 2007-10-22 17:40

#3

帖子 dickfisch » 2008-07-29 1:25

kofshower真是个热心人 :lol:
不过实在不好意思, 这些库文件我看得不是太懂,可能答案就在里面,请见谅。

wiki上说: It (指putc) is allowed to be a macro with the same effects as fputc, except that it may evaluate the stream more than once.

这里所说的宏(macro)是不是指代这样?
#define putc(c,fp) fputc(c,fp)

还有 putchar(c) has the same effects as putc(c,stdout)

那么,我的疑问是 putc(c,fp) /*这里fp指向一个文件*/ 和 putc(c,stdout) 为什么效果不一样呢?
后者在^D以后,马上putc函数起作用(屏幕上可以看到),而前者要等到最后输入流中断了,文件才被写入?
头像
kofshower
帖子: 1343
注册时间: 2007-03-13 11:23
联系:

#4

帖子 kofshower » 2008-07-29 2:53

第一个问题
是的
第二个问题:
和FILE这个对象有关。
对stream操作的API多是为了缓存的:
The stream stderr is unbuffered. The stream stdout is line-buffered
when it points to a terminal. Partial lines will not appear until
fflush(3) or exit(3) is called, or a newline is printed. This can pro-
duce unexpected results, especially with debugging output. The buffer-
ing mode of the standard streams (or any other stream) can be changed
using the setbuf(3) or setvbuf(3) call. Note that in case stdin is
associated with a terminal, there may also be input buffering in the
terminal driver, entirely unrelated to stdio buffering. (Indeed, nor-
mally terminal input is line buffered in the kernel.) This kernel
input handling can be modified using calls like tcsetattr(3); see also
stty(1), and termios(3).
上面说的很清楚了stdout是行缓冲的。
与普通文件描述符不一样。
我贴上一页的代码只是为了说明这个stream也就是File,他的大致接口是那个样,可是文件,stdout,
stdio不是一个东西。
这是取决于实现的。
此外还有low-level api 比如read write。这些都是不缓存的
"We are all in the mud, but some of us are looking at the stars." (Oscar Wilde)
We are not born for ourselves.
人生天地间,并非为自己
Homepage:http://sites.google.com/site/polarisnotme/
头像
dickfisch
帖子: 110
注册时间: 2007-10-22 17:40

#5

帖子 dickfisch » 2008-07-29 5:42

谢谢,大概明白什么意思了。因为我看的材料上说stdin, stdout和stderr都是当作文件来看,所以会有这么个疑问。

我也是刚刚开始学C,很多不懂的。明天去图书馆找本好教材来看。
头像
kofshower
帖子: 1343
注册时间: 2007-03-13 11:23
联系:

#6

帖子 kofshower » 2008-07-29 15:27

换一个方法
使用nspr这样跨平台的c库。
实际上glibc的跨平台不如想象的好。
具体参照:
nspr,这个是历史最久的,网景的。Mozilla全部项目的基础。
pjsip,一个sip协议栈。里面有很好的c的包装。
上面两个项目基本上都是我接触的比较好的。文档也很齐全
----------------------------------------------------------------
你问的那些问题其实只要一本书就清楚了,这本书好像图书馆不好找。
http://www.amazon.com/Reference-Manual- ... 013089592X
Amazon四星半的书,作为参考~也是我之前辅助教材
"We are all in the mud, but some of us are looking at the stars." (Oscar Wilde)
We are not born for ourselves.
人生天地间,并非为自己
Homepage:http://sites.google.com/site/polarisnotme/
头像
dickfisch
帖子: 110
注册时间: 2007-10-22 17:40

#7

帖子 dickfisch » 2008-07-31 22:53

谢谢,我看了一下,我们图书馆第五版的已经借完了,有第四版的。我想我需要一本进阶的教程。
头像
dickfisch
帖子: 110
注册时间: 2007-10-22 17:40

#8

帖子 dickfisch » 2008-07-31 23:13

kofshower 想跟你资讯一下:

我现在还在读书,想靠写C程序勤工俭学。当然我现在只是初学者,希望在一年后有能力干一些简单的活。就是想问问你,我该怎么积累经验,能让老板能雇佣我?比如自己先做点小project什么的。希望你能给我点建议。谢谢!
头像
kofshower
帖子: 1343
注册时间: 2007-03-13 11:23
联系:

#9

帖子 kofshower » 2008-08-01 2:21

对于面试这类经验有限。我到今天一共真正面试过两次。
第一次的话,是因为笔试成绩好。简历上有项目开发经验。是一些数据库的项目,和大学里面图书馆的后台
第二次的话,是简历上写明了算法方面的,加上精通C++范型编程,所以收了。
奇怪的是我面试都没有人问我技术上的问题。最多按着简历问我是不是做过。大三的时候去华为试验的时候倒是问了点技术的,第5面要求画双向链表,写几个算法题,第3面的时候写ADO的代码(因为我简历上写的)
我看来他们多是看中项目和基础(编码的可靠,算法方面)
经验的话就是自己找老师了。班上要出国的一般找个老师共同完成个项目。然后就是大四的时候申请校外做毕业设计了。我的毕业设计是跑到Mozilla实验室下面做MYSQL的XPCOM组件的包装的。
其实在大公司里面有还没有见过没有自己的框架的。所以我觉得基础第一。然后的话,熟悉一个常用的框架,如果关心开源的话,比如搞C++的话精通STL,然后是ACE之类的框架,ICE之类的组件模型。搞c的话也是同样的,比如阅读pjsip。那儿的代码可读性很高。你会学到如下的东西,为什么开发不采用glibc,怎么用c实现面向对象,一种以后用的着c的内存池解决方案,计算机网络方面的sip的协议,RFC的ICE算法(我不得不看,在公司会被人逼着看一些自己不想学的东西,现下实现最完整的ICE实现,也就是说它的内网传透能力最强)
培养读代码的能力,很多时候你要先看懂别人的代码,我记得我读完的就有mfc,mozilla的nspr和基础框架,pjsip,libjingle,所以我现在看到问代码的第一反应是叫人去读源码。
------------------------------------------------------------------------------------------------------------------------------
大学阶段我觉得我做到了精通两们语言,有过项目经验,熟悉算法和范型(从同学的经历来看算法的力量确实是最大的。)。操作系统方面只是熟悉win 核心编程
其他的我都没有做到。
我觉得精通框架的话对在校的时候的我很有难度,在校的时候不知道原来会有这么个包罗万象的库,不懂软件架构设计,不知道软件版本控制CVS,SVN。不懂怎么解决问题,我记得我到了实习地方的课题是怎样设计一个可用的框架,实现手机和电脑的数据同步。我的同学的要求是实现一个firefox里面的文字朗读,听起来像是TTs,然后给了两周时间,先画出Rose图,讲解架构设计。不妥的话,别人会指正你。然后开始写,这些东西都没有学过,自己去cvs上取文档来读。所以大学的要求上好大学的每一们课就好了。我的数字图像处理就老是学不好。在后来学着写游戏的时候就收到报应了。基础最重要,因为基本上工作的事情和学院派有很大的区别。
(出来招聘的不是老板,他们都是技术人员,起码招开发人员最后拍板的是你的leader。去年腾讯的湖南中大招聘会就是我同学。我也招过人,leader忙着开会 讨论问题的时候)
ps:我现在也是学生了。攒了money,准备考研
"We are all in the mud, but some of us are looking at the stars." (Oscar Wilde)
We are not born for ourselves.
人生天地间,并非为自己
Homepage:http://sites.google.com/site/polarisnotme/
头像
dickfisch
帖子: 110
注册时间: 2007-10-22 17:40

#10

帖子 dickfisch » 2008-08-01 7:33

kofshower你太厉害了!

非常感谢你写了那么多。我只是个业余编程爱好者,说是爱好者,其实也就是最近才爱上的。:lol:

学编程是因为专业上以后会用到(我选的方向是数值计算)。 至于工作我是想能不能掌握了这个技能后,给自己赚点生活费,就是student job之类的。毕竟是学生,没有收入,而且我觉得编程算是比较体面的工作。

你的建议对目前的我来说太远大了。不过你有句话说得对,基础很重要。我想还是多看别人写的代码,培养读代码的能力是最基本的,是吧? 非常感谢这个建议!

祝你考研顺利。
回复