字符I/O

字符I/O

字符输入是由getchar家族执行的,原型如下: 

int fgetc(FILE* stream);
int getc(FILE* stream);
int getchar(void); 

fgetc函数从指定的文件中读一个字节, getchar从标准输入读一个字节,调用getchar()相当于调用fgetc(stdin)

需要操作的流作为参数传给getc和fgetc,但getchar始终从标准输入读取。每个函数从流读取一个字符,并作为返回值。如果流中没有字符,就返回EOF。

要用fgetc函数读一个文件,该文件的打开方式必须是可读的。

系统对于每个打开的文件都记录着当前读写位置在文件中的地址(或者说距离文件开头的字节数),也叫偏移量(Offset) 。当文件打开时,读写位置是0,每调用一次fgetc,读写位置向后移动一个字节,因此可以连续多次调用fgetc函数依次读取多个字节 。 

把单个字符写入到流中,使用putchar家族,原型如下: 

int fputc(int character, FILE* stream);
int putc(int character, FILE* stream);
int putchar(int character);

fputc函数向指定的文件写一个字节, putchar向标准输出写一个字节,调用putchar(c)相当于调用fputc(c, stdout)

要用fputc函数写一个文件,该文件的打开方式必须是可写的(包括追加)。
每调用一次fputc,读写位置向后移动一个字节,因此可以连续多次调用fputc函数依次写入多个字节。但如果文件是以追加方式打开的,每次调用fputc时总是将读写位置移到文件末尾然后把要写入的字节追加到后面。

如果由于任何原因(如写入到一个已被关闭的流)导致函数失败,它们就返回EOF。

示例: 

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
int ch;
if ( (fp = fopen("file2", "w+")) == NULL) {
perror("Open file file2\n");
exit(1);
}
while ( (ch = getchar()) != EOF)
fputc(ch, fp);
rewind(fp);
while ( (ch = fgetc(fp)) != EOF)
putchar(ch);
fclose(fp);
return 0;
}

从终端设备读有点特殊。当调用getchar()fgetc(stdin)时,如果用户没有输入字符, getchar函数就阻塞等待,所谓阻塞是指这个函数调用不返回,也就不能执行后面的代码,这个进程阻塞了,操作系统可以调度别的进程执行。

从终端设备读还有一个特点,用户输入一般字符并不会使getchar函数返回,仍然阻塞着,只有当用户输入回车或者到达文件末尾时getchar才返回。
从终端设备输入时有两种方法表示文件结束,一种方法是在一行的开头输入Ctrl-D(如果不在一行的开头则需要连续输入两次Ctrl-D),另一种方法是利用ShellHeredoc语法: 

./a.out <<END
hello
hey
END

<<END表示从下一行开始是标准输入,直到某一行开头出现END时结束。 <<后面的结束符可以任意指定,不一定得是END,只要和输入的内容能区分开就行。 

字符I/O宏

fgetc和fputc都是真正的函数,但getc、putc、getchar和putchar都是通过#define定义的宏。

撤销字符I/O

int ungetc(int character, FILE* stream);

ungetc把一个先前读入的字符退回到流中,这样它还可以重新被读入。

注意:把字符退回到流中和写入到流中并不相同。与一个流相关联的外部储存并不受ungetc的影响。“退回”字符和流的当前位置有关,所以如果用fseek、fsetpos或rewind函数改变了流的位置,所有退回的字符都将被丢弃。

posted @ 2018-04-05 17:16  刘-皇叔  阅读(227)  评论(0编辑  收藏  举报