C语言程序设计
2002 年第九章 输入输出第九章 输入输出为永久性保存数据,需将数据以数据文件的形式存放,
以及从现有的某数据文件中读取数据,形成对数据文件的输入输出。
C程序的输入输出有两种方式:
( 1)标准 I/O或流式 I/O:依靠标准库函数实现输入输出。
如 printf(“sss”)
( 2)低级 I/O:利用操作系统提供的接口函数(称为底层接口或系统调用)实现输入输出。
9.1 流式 I/O
流式 I/O中,文件被看成是字符(字节)的序列(即
“流”),
C环境中,将所有 I/O设备当成文件进行管理,显示器为输出文件,用以输出数据,键盘为输入文件,用以输入数据。
流式 I/O通过 FILE指针( FILE结构类型在 <stdio.h>中定义)存取文件流式文件分为两种:
(1)文本文件,字符流序列;如32767需要5个字节存储;
(2)二进制文件:字节流序列;如32767需要2个字节存储;但显示时,需进行转换。
输入缓冲区输出缓冲区输入文件输出文件程序数据区文件I/O缓冲机制缓冲区空缓冲区满
9.2 标准输入输出函数
9.2.1 文件的打开与关闭文件的处理步骤为:
(1)首先打开文件,建立FILE指针和物理文件的联系,系统分配缓冲资源;
(2)利用标准输入输出函数读写文件,进行相关处理;
(3)关闭文件,将输出缓冲区中未写到文件中的数据输出到文件中(称为缓冲区清仓),系统释放缓冲资源。
C程序开始执行时,自动打开三个标准流式文件:
(1)标准输入文件( stdin),对应键盘;
(2)标准输出文件( stdout),对应显示器;
(3)标准错误输出文件( stderr),对应显示器。
用于打开与关闭文件的函数
(1) fopen 打开文件函数原型,FILE *fopen(char *filename,char *mode)
其中,filename:字符串形式的文件名
mode:文件存取方式,为 r,w,a,b,+的组合字符串
“r”,”r+”,”rb”,”r+b” 读
“w”,”w+”,”wb”,”w+b” 写
“a”,”a+”,”ab”,”a+b” 添加
r:表示读文件,此时该文件必须存在;
w:表示写;该文件必须存在时,清空文件数据,不存在时,创建指定文件名的文件。
a:表示在文件尾添加数据,不清空文件数据。
+:表示文件既可以读,也可以写;
b,表示打开的文件为二进制文件。缺省时表示文本文件。
r+则表示对一个存在的文本文件进行读写方式打开;
r+则表示对不一定存在的文本文件进行读写方式打开,并且清空文件数据;
例:
FILE *fp;
fp=fopen(“student.dat”,”r”);
if (fp==NULL) { printf(“不能打开文件”,
,student.dat”);
exit(-1);
}
fp=fopen(“C:\\LI\\student.dat”,”r”);
(2) fclose 关闭文件函数原型,int fclose(FILE *stream);
返回值,正确时返回0,错误时返回EOF。
stream,FILE指针。
例,fclose (fp);
注:如果对打开的文件未执行过 fclose,则程序终止时将自动调用 fclose关闭所有未关闭的文件。
9.2.2 文件的读写操作一、字符读写函数
(1) fgetc,从文件中读取一个字符 (unsigned char)并转换成 int值返回。
( 2) fputc,将参数 c转换为 unsigned char写到文件中。
( 3) getc和 putc:分别等同于 fgetc 和 fputc。
getchar与 putchar是建立在 getc和 putc上的宏:
#define getchar() getc(stdin)
#define putchar(x) putc((x),stdout)
( 4) ungetc:将 getchar,fgetc,getc读入的字符回送。
例,c=getchar(); /*输入 a*/
ungetc( c ); c1=getchar(); /*c1的值为‘ a’*/
( 5) ferror(fp):错误测试。
测试 I/O操作是否有错,返回 0表示正常,非 0表示 I/O操作出错。
( 5) feof(fp):文件结尾测试。
若读写指针指向文件尾,返回非 0,否则。返回 0。
一般用于测试输入文件的读过程。
!feof(fp) && !ferror(fp)feof(fp)==0 && ferror(fp)==0
表示指针未指向文件尾,且文件操作正常。
例:拷贝文本文件。命令格式为:
c> copyfile source target
其中 source为源文件名,target为目标文件名。
#include,stdio.h”
#include,stdlib.h”
void main(int argc,char *argv[])
{ FILE *fin,*fout; /*文件指针说明 */
if (argc!=3) /*检查参数的正确性 */
{ printf(“参数错误” ); exit(-1);}
if ((fin=fopen(argv[1],”r”))==NULL) /*打开源文件 */
{ printf(“不能打开文件 %s”,argv[1]);
exit(-1);}
if ((fin=fopen(argv[2],”r”))==NULL) /*打开目标文件 */
{ printf(“不能打开文件 %s”,argv[2]);
exit(-1);}
while(!feof(fin)) /*拷贝文件 */
putc(getc(fin),fout);
/*关闭文件 */
fclose(fin);
fclose(fout);
}
注:以上程序用文件名 copyfile.c存放。
二、字符串输入输出函数
( 1) char gets( char *s)
输入一行字符到数组 s,结尾的‘ \n’被换成’ \0’;
( 2) int puts( char *s)
输出字符串 s到 stdout,并将结尾的’ \0’ 被换成‘ \n’ ;
( 3) char gets( char *s,int n,FILE *stream)
从 stream文件输入一行字符到数组 s,行尾添加’ \0’。如果一行字符的数目多于 n个,则至多读入 n-1个字符。
( 4) int fputs( char *s,FILE *stream)
输出字符串 s到 tream文件,结尾不添加‘ \n’ ;
三、格式输入输出函数
( 1) int fscanf(FILE *stream,const char *format)
例,fscanf( fp1,”%3d”,&i);
/* fp1文件中为 123450,将 123读到变量 i中 */
( 2) int printf(FILE *stream,const char *format)
例,printf( fp1,”%6.2”,123.0);
/* 将 123.00写到 fp1文件中 */
四、成组输入输出函数
( 1)从 stream 文件中读取至多 nobj 个大小为 size的数据项到数组 ptr:
size_t fread(void *ptr,size_t size,size_t nobj FILE *stream)
例:
struct stud students[100];
FILE *f;
f=fopen(“student.dat”,’r’);
fread(students,sizeof(struct stud),10,f);
num=0; /*num:学生人数 */
while (!feof(f))
{fread(&students[num],sizeof(struct stud),1,f); num++}
( 2)将数组 ptr中 nobj 个大小为 size的数据项写到 stream 文件中:
size_t fwrite(void *ptr,size_t size,size_t nobj FILE *stream)
例:
struct stud students[100];
FILE *f;
………,/*num 个学生 */
f=fopen(“student.dat”,’w’);
fread(students,sizeof(struct stud),num,f);