文章目录
- 1 IO 函数
- 1.1 错误函数
- 1.1.1 检测流上的错误函数ferror
- 1.1.2 复位错误标志函数clearerr
- 1.2 结束函数
- 1.2.1 检测文件结束符函数feof
- 1.2.2 清除文件缓冲区函数fflush
- 1.3 处理文件函数
- 1.3.1 文件的打开与关闭函数fopen,fclose
- 1.3.2 替换文件中数据流函数freopen
- 1.3.3 文件指针定位函数fseek
- 1.3.4 定位流上的文件指针函数fsetpos
- 1.3.5 返回当前文件指针位置函数ftell
- 1.3.6 删除文件函数remove
- 1.3.7 重命名文件函数rename
- 1.3.8 重置文件指针函数rewind
- 1.3.9 指定文件流的缓冲区函数setbuf,setvbuf
- 1.3.10 创建临时文件函数tmpfile
- 1.3.11 创建临时文件名函数tmpnam
- 1.4 读取函数
- 1.4.1 从流中读取字符函数fgetc
- 1.4.2 取得当前文件的句柄函数fgetpos
- 1.4.3 从流中读取字符串函数fgets
- 1.4.4 从流中读取字符串函数fread
- 1.4.5 向文件写入数据函数fwrite
- 1.4.6 从流中读取字符函数getc
- 1.4.7 从标准输入文件中读取字符函数getchar
- 1.4.8 从标准输入文件中读取字符串函数gets
- 1.4.9 格式化输入函数scanf
- 1.4.10 向字符串写入格式化数据函数sprintf
- 1.4.11 从缓冲区中读格式化字符串函数sscanf
- 1.4.12 把字符退回到输入流函数ungetc
- 1.5 输出函数
- 1.5.1 格式化输出函数fprintf
- 1.5.2 向流中输出字符函数fputc
- 1.5.3 向流中输出字符串函数fputs
- 1.5.4 格式化输入函数fscanf
- 1.5.5 打印系统错误信息函数perror
- 1.5.6 产生格式化输出的函数printf
- 1.5.7 向指定流中输出字符函数putc
- 1.5.8 向标准输出文件上输出字符putchar
- 1.5.9 将字符串输出到终端函数puts
1 IO 函数
1.1 错误函数
1.1.1 检测流上的错误函数ferror
函数原型:int ferror(FILE *fp);
函数功能:检测流上的错误。即:检查文件在使用各种输入输出函数进行读写时是否出错。当输入输出函数对文件进行读写时出错,文件就会产生错误标志。应用这个函数,就可以检查出fp
所指向的文件操作是否出错,也就是说是否有错误标志。
返回值:未出错返回值为0,否则返回非0,表示有错。
#include <stdio.h>
int main(void)
{FILE *fp;char ch;/* 以写的方式打开一个文件名为test.txt的文件 */fp = fopen("test.txt", "w");/* 错误地从fp所指定的文件中读取一个字符,并打印它*/ch = fgetc(fp);printf("%c\n",ch);if (ferror(fp)){/* 如果此操作错误,就发布错误信息*/printf("Error reading from test.txt !\n");/*复位错误标志*/clearerr(fp);}/*关闭文件*/
fclose(fp);return 0;
}
1.1.2 复位错误标志函数clearerr
函数原型:void clearerr(FILE *fp);
函数功能:复位错误标志,即:使fp所指向的文件中的错误标志和文件结束标志置0。当输入输出函数对文件进行读写出错时,文件就会自动产生错误标志,这样会影响程序对文件的后续操作。clearerr函数就是要复位这些错误标志,也就是使fp所指向的文件的错误标志和文件结束标志置0,从而使文件恢复正常。
#include <stdio.h>
int main(void)
{FILE *fp;char ch;/* 以写的方式打开一个文件名为test.txt的文件 */fp = fopen("test.txt", "w");/* 错误地从fp所指定的文件中读取一个字符,并打印它*/ch = fgetc(fp);if (ferror(fp)){/* 如果此操作错误,就发布错误信息*/printf("This is a error reading!\n");/*复位错误标志*/clearerr(fp);}/*关闭文件*/
fclose(fp);return 0;
}
注意:ferror
函数与clearerr
函数应该配合使用。也就是说,通过ferror函数检测出文件有错误标志后要用clearerr函数复位错误标志。
1.2 结束函数
1.2.1 检测文件结束符函数feof
函数原型:int feof(FILE *fp);
函数功能:检测流上的文件结束符,即:检测文件是否结束。应用该函数可以判断一个文件是否到了结尾。在读取一个未知长度文件时,这个函数很有用。
返回值:遇到文件结束符返回非0,否则返回0。
#include <stdio.h>
int main(void)
{FILE *stream;/* 以只读方式打开test.txt文件 */stream = fopen("test.txt", "r");/* 从文件中读取一个字符 */fgetc(stream);/*检测是否是EOF,即结束标志 */if (feof(stream))printf("Have reached the end of the file!\n");/* 关闭该文件 */fclose(stream);return 0;
}
注意
:在实际应用中,feof
函数很重要,利用它程序员就可以很方便地判断当前的文件是否结束,从而进行不同的处理。例如,在从一个未知长度的文件中读取信息时,就可以利用feof函数判断什么时候该文件读完。
1.2.2 清除文件缓冲区函数fflush
函数原型:int fflush(FILE *fp);
函数功能:清除一个流,即清除文件缓冲区,当文件以写方式打开时,将缓冲区内容写入文件。也就是说,对于ANSIC规定的是缓冲文件系统,函数fflush
用于将缓冲区的内容输出到文件中去。
返回值:如果成功刷新,fflush返回0。指定的流没有缓冲区或者只读打开时也返回0值。返回EOF指出一个错误。
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <io.h>
int main(void)
{FILE *stream1,*stream2;char test[20]="This is a test";char res[20];/*以写的方式打开文件test.txt*/stream1 = fopen("test.txt", "w");/*向文件写入字符串*/fwrite(test,15,1,stream1);/*以读的方式打开文件test.txt*/stream2 = fopen("test.txt", "r");/*将文件内容读入缓冲区*/if(fread(res,15,1,stream2))printf("%s",res);elseprintf("Read error!\n");fclose(stream1);fclose(stream2);getch();return 0;
}显示错误信息Read error!
第二种方式读写文件
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <io.h>
int main(void)
{FILE *stream1,*stream2;char test[20]="This is a test";char res[20];/*以写的方式打开文件test.txt*/stream1 = fopen("test.txt", "w");/*向文件写入字符串*/fwrite(test,15,1,stream1);/*将缓冲区的内容写入文件*/fflush(stream1);/*以读的方式打开文件test.txt*/stream2 = fopen("test.txt", "r");/*将文件内容读入缓冲区*/if(fread(res,15,1,stream2))printf("%s",res);elseprintf("Read error!\n");fclose(stream1);fclose(stream2);getch();return 0;
}
显示字符串"This is a test"
第一个例子将文件打开后,指针stream1
指向的是该文件的内存缓冲区,将字符串写入后也只是写到了文件的内存缓冲区中,而并没有写到磁盘上的文件中。而当以读的方式打开该文件时,该文件中的内容实际为空,也就是stream2指向的缓冲区中内容为空。因此读文件发生错误。
而第二个例子中,在写完文件后调用函数fflush
,将缓冲区的内容写到文件中,这样再以读的方式打开该文件时,文件中已经存有了字符串,因此可以正常读出。
注意:如果在写完文件后调用函数fclose
关闭该文件,同样可以达到将缓冲区的内容写到文件中的目的,但是那样系统开销较大。
1.3 处理文件函数
1.3.1 文件的打开与关闭函数fopen,fclose
函数原型:FILE fopen(char filename, char type);
int fclose(FILE fp);
函数功能:函数fopen
:打开一个流,即:打开一个文件。该函数有两个参数,filename
是需要打开文件的文件名,type
是打开文件的方式。函数fclose
:关闭一个流,即:关闭一个文件,并释放文件缓冲区。fclose
函数与fopen
函数是相对的两个函数。fclose
函数的参数是指向文件的指针,应用该函数用以在程序结束之前关闭文件,并释放文件缓冲区。这样可以保证文件的数据不流失。
返回值:fopen
:FILE
类型,如果打开的文件存在,返回指向该文件的指针;如果打开的文件不存在,则在指定的目录下建立该文件打开,并返回指向该文件的指针。fclose
:整型,有错返回非0,否则返回0。
文件使用方式 | 意 义 |
---|---|
r | 只读打开一个文本文件,只允许读数据 |
w | 只写打开或建立一个文本文件,只允许写数据 |
a | 追加打开一个文本文件,并在文件末尾写数据 |
rb | 只读打开一个二进制文件,只允许读数据 |
wb | 只写打开或建立一个二进制文件,只允许写数据 |
ab | 追加打开一个二进制文件,并在文件末尾写数据 |
r+ | 读写打开一个文本文件,允许读和写 |
w+ | 读写打开或建立一个文本文件,允许读写 |
a+ | 读写打开一个文本文件,允许读,或在文件末追加数据 |
rb+ | 读写打开一个二进制文件,允许读和写 |
wb+ | 读写打开或建立一个二进制文件,允许读和写 |
ab+ | 读写打开一个二进制文件,允许读,或在文件末追加数据 |
#include <string.h>
#include <stdio.h>
int main(void)
{FILE *fp;char buf[11] = "abcdefghij";/* 以写方式打开文件名为test.txt的文件 */fp = fopen("test.txt", "w");
/*把字符串写入文件中*/fwrite(&buf, strlen(buf), 1, fp);/* 关闭文件 */fclose(fp);return 0;
}
注意:用户在编写程序时应该养成及时关闭文件的习惯,如果不及时关闭文件,文件数据有可能会丢失。
1.3.2 替换文件中数据流函数freopen
函数原型:FILE freopen(char filename, char type, FILE fp);
函数功能:关闭fp所指向的文件,并将该文件中的数据流替换到filename所指向的文件中去。该函数共三个参数:第一个参数filename是文件流将要替换到的文件名路径;第二个参数type是文件打开的方式,它与fopen中的文件打开方式类似;第三个参数fp是要被替换的文件指针。
返回值:返回一个指向新文件的指针,即指向filename文件的指针。若出错,则返回NULL。
#include <stdio.h>
int main(void)
{FILE *Nfp;/* 替换标准输出文件上的数据流到新文件test.txt */if (Nfp=freopen("test.txt", "w", stdout)== NULL)fprintf(stderr, "error redirecting stdout\n");/* 标准输出文件上的数据流将会被替换到新文件中 */printf("This will go into a file.");/* 关闭标准输出文件 */fclose(stdout);/*关闭新生成的文件*/fclose(Nfp);return 0;
}
执行结果是在当前目录下生成一个文件test.txt,并将原终端的数据流"This will go into a file."重新写入test.txt文件中。
1.3.3 文件指针定位函数fseek
函数原型:int fseek(FILE *fp, long offset, int base);
函数功能:重定位流上的文件指针,即将fp指向的文件的位置指针移向以base为基准,以offset
为偏移量的位置。该函数有三个参数:fp为文件指针,offset为偏移量,即位移offset个字节,base为指针移动的基准,即起始点。其中,基准base用0、1或2表示。
返回值:成功返回0,否则返回非0
在ANSI C标准指定的名字如下表 ANSI C标准指定的起始点名字,偏移量用长整型数表示。ANSI C标准规定,在数的末尾加L就表示长整型数。该函数在随机读取较长的顺序文件时是很有用的。
起始点 | 名字 | 数字代码 |
---|---|---|
文件当前位置 | SEEK_CUR | 1 |
文件开始位置 | SEEK_SET | 0 |
文件末尾位置 | SEEK_END | 2 |
#include <stdio.h>
void main( void )
{FILE *fp;char line[81];int result;/*以读写的方式打开打开名为test.txt的文件*/fp = fopen( "test.txt", "w+" );if( fp == NULL )printf( "The file test.txt was not opened!\n" );else{/*按照规定格式将字符串写入文件*/fprintf( fp, "The fseek begins here:"This is the file 'test.txt'.\n" );/*将文件指针定位到离文件头23个字节处*/result = fseek( fp, 23L, SEEK_SET);if( result )perror( "Fseek failed" );else{printf( "File pointer is set to middle of first line.\n" );/*从fp指向的文件中读取字符串*/fgets( line, 80, fp );/*显示读取的字符串*/printf( "%s", line );}fclose(fp);}
}运行结果为在屏幕上显示出以下字符串:File pointer is set to middle of first line.
This is the file 'test.txt'.
1.3.4 定位流上的文件指针函数fsetpos
函数原型:int fsetpos(FILE fp, const fpos_t pos);
函数功能:将文件指针定位在pos指定的位置上。该函数的功能与fgetpos相反,是将文件指针fp按照pos指定的位置在文件中定位。pos值以内部格式存储,仅由fgetpos和fsetpos使用。
返回值:成功返回0,否则返回非0。
#include <stdio.h>
void main( void )
{FILE *fp;fpos_t pos;char buffer[50];/*以只读方式打开名为test.txt的文件*/if( (fp = fopen( "test.txt", "rb" )) == NULL )printf( "Trouble opening file\n" );else{/*设置pos值*/pos = 10;/*应用fsetpos函数将文件指针fp按照pos指定的位置在文件中定位*/if( fsetpos( fp, &pos ) != 0 )perror( "fsetpos error" );else{/*从新定位的文件指针开始读取16个字符到buffer缓冲区*/fread( buffer, sizeof( char ), 16, fp );/*显示结果*/printf( "16 bytes at byte %ld: %.16s\n", pos, buffer );}}fclose( fp );
}显示结果:16 bytes at byte 10: test for testing 。
1.3.5 返回当前文件指针位置函数ftell
函数原型:long ftell(FILE *fp);
函数功能:返回当前文件指针的位置。这个位置是指当前文件指针相对于文件开头的位移量。
返回值:返回文件指针的位置,若出错则返回–1L。
#include <stdio.h>
int main(void)
{FILE *fp;fp = fopen("test.txt", "w+");/*按照格式要求将字符串写入文件*/fprintf(fp, "This is a test");/*读出文件指针fp的位置*/printf("The file pointer is at byte %ld\n", ftell(fp));fclose(fp);return 0;
}
注意:ftell函数的返回值实际上就是该文件的长度。在实际的应用中,函数ftell常用来计算文件的长度。
1.3.6 删除文件函数remove
函数原型:int remove(char *filename);
函数功能:删除以filename为文件名的文件。该函数的参数为欲删除文件的文件名,如果是单纯的文件名,就表明删除当前文件夹下的文件,否则要写明文件的路径。
返回值:成功删除文件返回0,否则返回-1。
#include <stdio.h>
void main()
{if( remove( "test.txt" ) == -1 )perror( "Could not delete test.txt!!" );elseprintf( "Deleted test.txt \n" );
}
注意:perror
函数是按照一定格式要求向终端输出错误信息,因此,若删除文件成功,程序运行的结果为:Deleted test.txt
若删除失败,则程序运行的结果为:Could not delete test.txt!!: No such file or directory
这里,利用perror函数显示的完整的错误信息包括:用户自定义字符串,冒号,系统报错信息,换行符。
1.3.7 重命名文件函数rename
函数原型:int rename(char oldname, char newname);
函数功能:把由oldname所指的文件名改为由newname所指的文件名。该函数有两个参数,oldname为旧的文件名,newname为欲改成的新文件名。应当注意,oldname所指的文件一定要存在,newname所指的文件一定不存在。应用该函数可将一个文件的旧文件名oldname改为新文件名newname,但不能改变文件的路径。
返回值:成功返回0,出错返回-1。
include <stdio.h>
int main(void)
{if( rename("oldname.txt","newname.txt")==0)printf("Rename successful!!");elseprintf("Rename fail!!");
}
1.3.8 重置文件指针函数rewind
函数原型:void rewind(FILE *stream);
函数功能:将文件指针fp重新定位在文件开头,并清除文件的结束标志和错误标志。该函数与函数fseek
功能类似,但不同的是,该函数可以清除文件的结束标志和错误标志,而函数fseek不能;另外,该函数不能像函数fseek一样返回一个值表明操作是否成功,因为该函数无返回值。
返回值:无。
#include <stdio.h>
void main( void )
{FILE *fp;int data1, data2;data1 = 1;data2 = 2;if( (fp = fopen( "test.txt", "w+" )) != NULL ){fprintf( fp, "%d %d", data1, data2 );printf( "The values written are: %d and %d\n", data1, data2 );data1=0;data2=0;rewind( fp );fscanf( fp, "%d %d", &data1, &data2 );printf( "The values read are: %d and %d\n", data1, data2 );fclose( fp );}
}
运行结果为:
The values written are: 1 and 2
The values read are: 1 and 2
注意:在应用fprintf函数向该文件写入data1,data2两个整型数后,文件指针fp会自动指向文件尾。只有再应用函数rewind、fseek才能将文件指针重新定位到文件开头,以便读取文件。本例中,将data1和data2置0的目的是为了说明应用fscanf函数向data1,data2两个变量中读入文件中的数字的结果是正确的。
1.3.9 指定文件流的缓冲区函数setbuf,setvbuf
函数原型:void setbuf(FILE fp, char buf);
void setvbuf(FILE fp, char buf, int type, unsigned size);
函数功能: 这两个函数使得打开文件后,用户可以建立自己的文件缓冲区,而不必使用fopen函数打开文件时设定的默认缓冲区。 setbuf函数的定义中,参数buf指定的缓冲区大小由stdio.h
中定义的宏BUFSIZE的值决定,缺省值default为512字节。而当buf为NULL时,setbuf函数将使文件I/O不带缓冲区。而对setvbuf函数,则由malloc
函数来分配缓冲区。参数size指明了缓冲区的长度(必须大于0),而参数type则表明了缓冲的类型,其取值如下表: setvbuf函数中参数type的取值含义
type 值 | 含义 |
---|---|
_IOFBF | 文件全部缓冲,即缓冲区装满后,才能对文件读写 |
_IOLBF | 文件行缓冲,即缓冲区接收到一个换行符时,才能对文件读写 |
_IONBF | 文件不缓冲,此时忽略buf,size的值,直接读写文件,不再经过文件缓冲区缓冲 |
#include <stdio.h>
void main( void )
{char buf[BUFSIZ];FILE *fp1, *fp2;if( ((fp1 = fopen( "test1.txt", "a" )) != NULL) &&((fp2 = fopen( "test2.txt", "w" )) != NULL) ){/* 应用setbuf函数给文件流fp1指定缓冲区buf */setbuf( fp1, buf );/*显示缓冲区地址*/printf( "fp1 set to user-defined buffer at: %Fp\n", buf );/* 文件流fp2不指定缓冲区*/setbuf( fp2, NULL );/*信息提示不分配缓冲区*/printf( "fp2 buffering disabled\n" );fclose(fp1);fclose(fp2);}
}
注意
:使用setbuf
函数指定文件的缓冲区时,一定要在文件读写之前。一旦用户自己指定了文件的缓冲区,文件的读写就要在用户指定的缓冲区中进行,而不在系统默认指定的缓冲区中进行。函数setvbuf
的用法与setbuf类似,只是它的缓冲区大小可以动态分配,由函数的参数指定,而且缓冲区的类型也可以由参数指定。
1.3.10 创建临时文件函数tmpfile
函数原型:FILE *tmpfile(void);
函数功能:创建一个临时文件。该文件以w+b(二进制读写)方式打开,当该文件被关闭时,该文件会被自动删除。
返回值:返回指向临时文件的指针,如果文件打不开则返回EOF。
#include <stdio.h>
#include <process.h>
int main(void)
{FILE *tempfp;tempfp = tmpfile();if (tempfp)printf("Temporary file be created!!\n");else{printf("Unable to create the temporary file!!\n");exit(1);}sleep(20);return 0;
}
注意
:这里将程序挂起20秒的目的是为了让用户看到生成的临时文件。这是因为当程序执行完时,系统会自动删除临时文件,那样用户就感觉不到临时文件的创建了。当该程序运行时,会在当前文件夹下生成一个临时文件。 临时文件的作用是暂时存储程序运行过程中需要的数据,当程序运行完毕时,这些数据也就没有用了。
1.3.11 创建临时文件名函数tmpnam
函数原型:char tmpnam(char string);
函数功能:创建一个临时文件名,用以打开一个临时文件。
返回值:创建成功返回指向该文件名的指针,否则返回NULL。
#include <string.h>
#include <stdio.h>
main()
{char tmp[10];tmpnam(tmp);printf("The temporary name is %s\n",name);
}
注意
:应用函数tmpnam
生成的临时文件名是不同于任何已存在文件名的有效文件名。本函数用于给临时文件创建文件名。
1.4 读取函数
1.4.1 从流中读取字符函数fgetc
函数原型:int fgetc(FILE *fp);
函数功能:从流中读取字符,即从fp
所指定的文件中取得下一个字符。这里需要注意,在每取完一个字符时fp会自动向下移动一个字节。这样编程时,程序员就不用再对fp控制了。这种功能在许多读写函数中都有体现。
返回值:返回所得到的字符,若读入错误。返回EOF
。
#include <string.h>
#include <stdio.h>
#include <conio.h>
int main(void)
{FILE *fp;char string[] = "This is a test";char ch;/* 以读写方式打开一个名为test.txt的文件 */fp = fopen("test.txt", "w+");/* 向文件中写入字符串string */fwrite(string, strlen(string), 1, fp);/* 将fp指针指向文件首 */fseek(fp, 0, SEEK_SET);do{/* 从文件中读一个字符 */ch = fgetc(fp);/* 显示该字符 */putch(ch);} while (ch != EOF);fclose(fp);return 0;
}
1.4.2 取得当前文件的句柄函数fgetpos
函数原型:int fgetpos( FILE stream, fpos_t pos );
函数功能:取得当前文件的指针所指的位置,并把该指针所指的位置数存放到pos所指的对象中。pos值以内部格式存储,仅由fgetpos和fsetpos使用。其中fsetpos的功能与fgetpos相反,为了详细介绍,将在后节给与说明。
返回值:成功返回0,失败返回非0,并设置errno
include <string.h>
include <stdio.h>
int main(void)
{FILE *fp;char string[] = "This is a test";fpos_t pos;/* 以读写方式打开一个名为test.txt的文件 */fp = fopen("test.txt", "w+");/* 将字符串写入文件 */fwrite(string, strlen(string), 1, fp);/* 取得指针位置并存入&pos所指向的对象 */fgetpos(fp, &pos);printf("The file pointer is at byte %ld\n", pos);/*重设文件指针的位置*/fseek(fp,3,0);/* 再次取得指针位置并存入&pos所指向的对象 */fgetpos(fp, &pos);printf("The file pointer is at byte %ld\n", pos);fclose(fp);return 0;
}
1.4.3 从流中读取字符串函数fgets
函数原型:char fgets(char string, int n, FILE *fp);
函数功能:从fp所指的文件中读取一个长度为(n-1)的字符串,并将该字符串存入以string为起始地址的缓冲区中。fgets函数有三个参数,其中string为缓冲区首地址,n规定了要读取的最大长度,fp为文件指针。
返回值:返回地址string,若遇到文件结束符或出错,返回NULL。用feof 或ferror判断是否出错。
#include <string.h>
#include <stdio.h>
int main(void)
{FILE *fp;char string[] = "This is a test";char str[20];/* 以读写的方式打开一个名为test.txt的文件 */fp = fopen("test.txt", "w+");/* 将字符串写入文件 */fwrite(string, strlen(string), 1, fp);/* 文件指针定位在文件开头*/fseek(fp, 0, SEEK_SET);/* 从文件中读一个长为strlen(string)的字符串 */fgets(str, strlen(string)+1, fp);/* 显示该字符串 */printf("%s", str);fclose(fp);return 0;
}
从文件中读一个长为strlen(string)的字符串,这里应注意第二个参数若为n,则表示从fp所指的文件中读取一个长度为(n-1)的字符串。因此,这里的参数为strlen(string)+1,表示读取一个长度为strlen(string)的字符串。把字符串读到以str为首地址的数组中。
1.4.4 从流中读取字符串函数fread
函数原型:int fread(void buf, int size, int count, FILE fp);
函数功能:从fp指向的文件中读取长度为size 的count个数据项,并将它输入到以buf为首地址的缓冲区中。此时,文件指针fp会自动增加实际读入数据的字节数,即fp指向最后读入字符的下一个字符位置。
返回值:返回实际读入数据项的个数,即count值。若遇到错误或文件结束返回0。
#include <string.h>
#include <stdio.h>
int main(void)
{FILE *fp;char str[] = "this is a test";char buf[20];if ((fp = fopen("test.txt", "w+"))== NULL){fprintf(stderr,"Cannot open output file!!\n");return 1;}/* 向文件中写入字符串数组中的数据 */fwrite(str, strlen(str), 1, fp);/* 将文件指针定位到文件开头 */fseek(fp, SEEK_SET, 0);/* 把文件中的数据读出并显示 */fread(buf, strlen(str), 1, fp);printf("%s\n", buf);fclose(fp);return 0;
}
1.4.5 向文件写入数据函数fwrite
函数原型:int fwrite(void buf, int size, int count, FILE fp);
函数功能:将buf所指向的count*size
个字节的数据输出到文件指针fp所指向的文件中去。该函数与fread相对,输出数据后,文件指针fp自动指向输出的最后一个字符的下一个位置。该函数常用于分批将数据块输出到文件中。
返回值:返回实际写入文件数据项个数。
#include <stdio.h>
struct exp_struct
{int i;char ch;
};
int main(void)
{FILE *fp;struct exp_struct s;/*以写的方式打开名为test.txt的文件*/if ((fp = fopen("test.txt","wb")) == NULL){fprintf(stderr, "Cannot open the test.txt");return 1;}/*向结构体中的成员赋值*/s.i = 0;s.ch = 'A';/* 将一个结构体数据块写入文件 参数sizeof(s)是该结构体变量的大小,1指只写入文件1个数据块*/fwrite(&s, sizeof(s), 1, fp);fclose(fp);return 0;
}
1.4.6 从流中读取字符函数getc
函数原型:int getc(FILE *fp);
函数功能:从fp所指向的文件中读取一个字符。该函数与前面所讲到的fgetc作用类似。读取字符后,文件指针fp自动指向下一个字符。
返回值:返回所读的字符,若文件结束或出错返回EOF。
include <stdio.h>
int main(void)
{char ch;printf("Input a character:");/* 从标准输入文件(键盘)中读取一个字符,存入变量ch,并显示在屏幕上*/ch = getc(stdin);/*显示该字符*/printf("The character input was: '%c'\n", ch);return 0;
}
#include <stdio.h>
void main( void )
{FILE *fp;char ch;/*以写的方式打开名为test.txt的文件*/fp=fopen("test.txt","w");/*写入字符串*/fprintf(fp,"This is a test.");fclose(fp);/*再以读的方式打开名为test.txt的文件*/fp=fopen("test.txt","r");/*将文件指针指向文件开头*/fseek(fp,0L,SEEK_SET);/*应用getc函数从文件中循环读取字符并显示出来*/while(feof(fp)==0){ch=getc(fp);printf("%c",ch);}fclose(fp);return 0;
}
注意:与上例不同,上例是从标准输入文件(键盘)中读取一个字符,本例是从一般文件中读取字符,关键在于函数的参数不同。
1.4.7 从标准输入文件中读取字符函数getchar
函数原型:int getchar(void);
函数功能:从标准输入文件stdin(键盘)中读取一个字符。该函数与getc类似,但参数为空,它只能从标准输入文件中读取字符,而不能读取用户自定义的文件
。getchar函数在编程时多用于接收回车、换行符。
返回值:返回所读的字符,若文件结束或出错返回-1。
include <stdio.h>
int main(void)
{int c;/* 从键盘上接收字符并显示,直到键入换行符'\n'为止 */while ((c = getchar()) != '\n')printf("%c", c);return 0;
}
1.4.8 从标准输入文件中读取字符串函数gets
函数原型:·char gets(char buf);·
函数功能:从标准输入文件 stdin(键盘)
中读取一个字符串,并把该字符串存入以buf为首地址的缓冲区中。该函数与fgets类似,但它只能从标准输入文件stdin中读取字符串,而且没有长度限制。
返回值:返回其参数,即缓冲区指针buf,若出错则返回空NULL。
#include <stdio.h>
int main(void)
{char string[30];printf("Input a string:");/*从终端输入字符串,注意不要超过30个字符*/gets(string);/*显示该字符串*/printf("The string input was: %s\n",string);return 0;
}
1.4.9 格式化输入函数scanf
函数原型:int scanf(char *format[,argument,...]);
函数功能:从标准输入设备(键盘)
按照format指定的格式字符串所规定的格式,将数据输入到argument所指定的内存单元。scanf函数与printf函数相对,前者是从标准输入设备输入数值,后者是从标准输出设备输出数值。
返回值:成功返回输入的字符个数,否则遇到结束符返回EOF
,出错返回0。
#include <stdio.h>
void main( void )
{int i;char ch;float f;printf("Please input an integer:\n");scanf("%d",&i);getchar();printf("Please input a character:\n");scanf("%c",&ch);getchar();printf("Please input an float:\n");scanf("%f",&f);getchar();printf("These values are:%d,%c,%f",i,ch,f);
}
注意:scanf
函数与fscanf
函数类似,但只能从标准输入设备文件读取数值,而不能像fscanf
函数一样从一般用户自定义文件中读取数值。scanf函数常用作程序设计中数据的输入函数。
1.4.10 向字符串写入格式化数据函数sprintf
函数原型:int sprintf(char string, char farmat [,argument,...]);
函数功能:将格式化的数据存储到以string为首地址的缓冲区中。参数argument要被转化为farmat规定的格式,并按照这个规定的格式向字符串数组写入数据。这里应该注意,sprintf函数与printf函数和fprint函数不同,前者是向缓冲区(即数组)写入格式化数据,后者是向标准输出文件(stdout)和用户自定义文件输出格式化数据。
返回值:返回存储在string中数据的字节数。
#include <stdio.h>
#include <math.h>
int main(void)
{char str[80];sprintf(str, "An approximation of Pi is %f\n", M_PI);puts(str);return 0;
}
注意
:puts
函数的作用是把str
指定的字符串输出到标准输出设备,并且将字符串结束标志\0
转换为回车换行符。
1.4.11 从缓冲区中读格式化字符串函数sscanf
函数原型:int sscanf(char string, char format[,argument,...]);
函数功能:将string指定的数据读到argument所指定的位置。其中,参数argument是与format格式要求相符合的变量指针。也就是说,如果format指定的格式为%d
,则argument就必须是整型变量的指针。这里应该注意,sscanf函数与scanf函数和fscanf函数不同,前者是从指定的缓冲区读格式化数据到新的缓冲区中,而后者是从标准输入文件(stdin)和用户自定义文件中读取格式化数据到缓冲区中。
返回值:成功返回已分配空间的数量,返回0表示没用空间分配,返回EOF表示出错。
#include <stdio.h>
void main( void )
{char str[] = "1 2 3...";char s[81];char c;int i;float fp;/* 从缓冲区str中读取数据 */sscanf( str, "%s", s );sscanf( str, "%c", &c );sscanf( str, "%d", &i );sscanf( str, "%f", &fp );/* 输出已读取的数据 */printf( "String = %s\n", s );printf( "Character = %c\n", c );printf( "Integer: = %d\n", i );printf( "Real: = %f\n", fp );
}
1.4.12 把字符退回到输入流函数ungetc
函数原型:int ungetc(char c, FILE *fp);
函数功能:把字符c退回到fp所指向的文件流中,并清除文件的结束标志。fp所指向的文件既可以是用户自定义的文件,又可以是系统定义的标准文件。
返回值:成功返回字符c,否则返回EOF。
#include <stdio.h>
#include <ctype.h>
int main( void )
{int i=0;char ch;puts("Input an integer followed by a char:");/* 读取字符直到输入非数字或EOF */while((ch = getchar()) != EOF && isdigit(ch))i = 10 * i + ch - 48; /* 将ASCII码转换为整数值*//* 如果输入非数字,将其退回输入流 */if (ch != EOF)ungetc(ch, stdin);printf("i = %d, next char in buffer = %c\n", i, getchar());return 0;
}
注意
:所谓将结尾的非数字字符退回到标准输入文件,就是说将数字字符串后面的那个非数字字符退回到标准输入文件中去。例如:输入的字符串为"123abc",那么退回的字符就是a。这样,程序将前面的字符串"123"转换为整型数123,并存入变量i中。a作为数字字符串输入的结束标志(因为 a是继数字字符之后的第一个非数字字符),被退回到标准输入文件(stdin)。于是,再调用getchar函数读取的字符就应该是刚刚退回到标准输入文件中的字符a。因此,本段例程的执行结果为:
Input an integer followed by a char:
123abc
i = 123, next char in buffer = a
即:输入的字符串中123 为整型数,接下来的字符为a。
1.5 输出函数
1.5.1 格式化输出函数fprintf
函数原型:int fprintf(FILE fp, char format[, argument,...]);
函数功能:把argument的值以format所指定的格式输出到fp指向的文件中。这个函数理解起来和printf类似,在一般的使用中,第二个参数可以是一个字符串的头指针,也可以就是一个字符串。例如:fprintf(fp, “Cannot open this file!!”),意思就是把字符串Cannot open this file!!输出到文件fp中去。该函数一般用作终端的出错提示或是在磁盘中生成错误报告。
返回值:如果正确返回实际输出字符数,若错误则返回一个负数。
#include <stdio.h>
int main(void)
{FILE *fp;/*以只读方式打开名为test.txt的文件*/if ((fp = fopen("\\test.txt", "rt")) == NULL){fprintf(stderr, "Cannot open this file!!\n");return 1; /*若该文件不能打开,在屏幕上显示出错提示*/}/*若该文件能够打开,在屏幕上显示正确提示*/fprintf(stderr,"Have open this file!!\n");return 0;
}
注意
:该函数中第一个参数是stderr
,这是C语言中标准出错输出指针,它指向标准的出错输出文件,也就是显示器。因为,在操作系统中,I/O设备都是用文件进行管理的,因此设备都配有相应的控制文件。在C语言中,有三个文件与终端相联系,因此系统定义了三个文件指针。
设备文件 | 文件指针 |
---|---|
标准输入 | stdin |
标准输出 | stdout |
标准出错输出 | stderr |
用fprintf函数在磁盘中生成错误报告。
#include <stdio.h>
int main(void)
{FILE *fp1,*fp2;
/*以只读方式打开名为test.txt的文件*/if ((fp1 = fopen("text.txt", "rt")) == NULL){/*若文件打不开,则生成错误报告*/fp2=fopen("report.txt","w");fprintf(fp2, "Cannot open this file!!\n");return 1;}return 0;
}
注意
:这里函数fprintf
的第一个参数为文件指针,是用户自定义的,与上一例的系统定义的文件指针stderr不同。fprintf
函数与printf函数的使用类似,其实printf函数是fprintf函数的一个特例,printf函数只能向标准输出文件(显示器)输出数据,而fprintf函数也可以向一般用户定义的文件输出数据。
1.5.2 向流中输出字符函数fputc
函数原型:int fputc(char ch, FILE *fp);
函数功能:将字符ch输出到fp指向的文件中。该函数与前边提到的fgetc是相对的,第一个参数ch是字符型变量,函数将该变量中的字符输出到fp指向的文件中。
返回值:成功返回该字符,否则返回非0。
#include <stdio.h>
int main(void)
{/*初始化字符数组str */char str[] = "This is a test";int i = 0;/*将数组中的字符循环输出至屏幕*/while (str[i]){fputc(str[i], stdout);i++;}return 0;
}
注意两点:
- 该循环以
\0
作为结束标志,即循环碰到\0
时结束。 - 函数
fputc
的第二个参数是stdout
,它代表标准输出文件指针,这样就是在屏幕上显示该字串。
1.5.3 向流中输出字符串函数fputs
函数原型:int fputs(char string, FILE fp);
函数功能:将string所指的字符串输出到fp指向的文件中。该函数与fgets相对,第一个参数为字符串指针。与fgets函数不同的是,fputs函数没有字符串长度的限制,只是将string指向的字符串输出到文件中。
返回值:成功返回0,否则返回非0。
#include <stdio.h>
int main(void)
{FILE *fp;char str[]="This is a test!";/*以写的方式打开名为test.txt的文件*/fp=fopen("test.txt","w");/*将字符串写入文件*/fputs(str,fp);fclose(fp);return 0;
}
1.5.4 格式化输入函数fscanf
函数原型:int fscanf(FILE fp, char format[,argument...]);
函数功能:从fp所指向的文件中按format给定的格式读取数据到argument所指向的内存单元。其中argument是指针,指针类型要与输入的格式format相一致。例如:fscanf(stdin, "%d", &i);
&i
是整型的指针,输入的格式format也要为整型,即"%d"。
返回值:返回已输入的数据个数。若错误或文件结束返回EOF。
#include <stdlib.h>
#include <stdio.h>
int main(void)
{char ch;printf("Please input an character ");/* 从标准输入文件中读取一个字符,并送至ch */if (fscanf(stdin, "%c", &ch))printf("The character was: %c\n",ch);else{/*出错提示*/fprintf(stderr, "Error reading an character from stdin!!\n");exit(1);}return 0;
}
这里应该注意两点:
fscan
f函数的第一个参数不是用户定义的文件指针,而是系统定义的标准输入文件指针stdin
。但用法与用户定义的文件指针类似。&ch
是指向字符型数据的指针,因此,输入的格式format
也要为字符型"%c",它们必须保持一致。
该函数的使用与scanf类似。其实,scanf函数是fscanf函数的一个特例,它只能从标准输入文件(键盘终端)中输入数据。而fscanf函数则也可以从一般用户定义的文件中输入数据。
1.5.5 打印系统错误信息函数perror
函数原型:void perror(char *string);
函数功能:将错误信息输出到标准出错输出stderr。该函数的参数是字符串指针,指向错误信息字符串。也可以就是一个字符串,直接在参数中输入要显示的错误信息。但要注意,完整的错误信息不仅包括用户在参数中自己定义的字符串,还包括一个冒号,系统报错信息,和一个换行符。该函数主要用作向终端进行错误提示。
返回值:无。
#include <stdio.h>
int main(void)
{FILE *fp;/*企图以读的方式打开文件test.txt*/fp = fopen("test.txt", "r");if (fp==NULL)/*该文件不存在,在终端显示错误信息*/perror("Unable to open file for reading");return 0;
}运行结果格式如下:
Unable to open file for reading: No such file or directory
注意
:完整的错误信息包括:用户自定义字符串
,冒号
,系统报错信息,换行符。
1.5.6 产生格式化输出的函数printf
函数原型:int printf( const char *format [, argument]... );
函数功能:按format指向的格式字符串所规定的格式,将输出表列argument的值输出到标准输出设备。该函数与fprintf类似,但只能将argument的值输出到标准输出设备stdout,即显示器屏幕,而不能输出到用户自定义的文件中。
返回值:输出字符的个数,若出错则返回一个负数。
#include <stdio.h>
#include <string.h>
int main(void)
{int a=1;char ch='r';char str[]="This is a test!";printf("Output a string.\n");printf("%s",str);printf("The integer is %d\n",a);printf("The character is %c\n",ch);return 0;
}
1.5.7 向指定流中输出字符函数putc
函数原型:int putc(int ch, FILE *fp);
函数功能:向指定的文件输出一个字符。该函数有两个参数,ch是用户指定的字符,fp是文件指针。函数将字符ch输出到fp指定的文件中。
返回值:返回输出的字符ch,若出错则返回EOF。
#include <stdio.h>
int main(void)
{char str[] = "Hello world!";int i = 0;while (str[i]){putc(str[i], stdout);i++;}return 0;
}
include <stdio.h>
int main(void)
{FILE *fp;int i = 0;char str[]="This is a test!";fp=fopen("test.txt","w");while (str[i]){putc(str[i], fp);i++;}fclose(fp);return 0;
}
注意
:该函数既可以向标准输出文件输出字符,又可以向用户自定义文件输出字符。而且,每当向文件输出一个字符时,文件指针就会自动向后移一个字节。
1.5.8 向标准输出文件上输出字符putchar
函数原型:int putchar(char ch);
函数功能:将字符串ch输出到标准输出文件stdout上。也就是说将字符串ch输出到显示器屏幕上。
返回值:返回输出的字符ch,若出错,则返回EOF。
include <stdio.h>
int main()
{char str[]="This is a test!\n";int i=0;while(str[i]){putchar(str[i]);i++;}
}
注意
:该函数与putc函数不同,它只能向标准输出文件,也就是终端屏幕上输出字符。而putc函数既可以向标准输出文件上输出字符,又可以向一般用户自定义文件上输出字符。
1.5.9 将字符串输出到终端函数puts
函数原型:int puts(char *string);
函数功能:将string指向的字符串输出到标准输出设备(stdout),并将\0
转换为回车换行符\n
。在C语言中,字符串以’\0’结尾。该函数不仅可以将字符串输出到标准输出设备,而且要将字符串的结束标志转换为回车换行。
返回值:成功则返回换行符,若失败则返回EOF
。
#include <stdio.h>
int main(void)
{char string[] = "This is a test!\n";puts(string);return 0;
}
注意:该函数将字符串的结尾标志\0
转换为回车换行符\n