前言:C语言提供了一些库函数,而IO函数就是其中的一部分。
首先我们介绍一个错误报告函数:perror
void perror(const char * str)
perror以一种简单、统一的方式报告错误。C函数库的许多函数调用操作系统来完成任务。当操作系统按照要求执行某些任务的时候,就可能会失败。例如:打开一个根本就不存在的文件,读取内容。操作系统的做法就是发生错误的时候,能够提示发生的错误。
标准库函数提供了一个全局变量errno(在errno.h中定义),来记录错误的错误码,交给用户程序,用于提示错误的准确原因。
例子:
#include
int main(){
FILE* pFile;
pFile = fopen("1.txt","rb");
if(pFile == NULL)
perror("The following error occurred");
else
fclose(pFile);
return 0;
}
输出结果:
如果perror函数的参数str不是NULL,并非指向一个非空字符串,perror函数先打印这个字符串,然后跟着输出一个分号和空格,接着输出错误信息提示。
终止执行(exit)
原型如下:void exit(int status);
参数status返回给了操作系统,用于提示程序是否正常完成。
C语言定义了预定义符号:EXIT_SUCCESS和EXIT_FAILURE 来表示成功或者失败返回。
例子:
#include
#include
int main(){
FILE* pFile;
pFile = fopen("1.txt","rb");
if(pFile == NULL){
printf("Error opening file");
exit(EXIT_FAILURE);
}
else
fclose(pFile);
return 0;
}
注意:main函数的返回值就是函数的退出码。
I/O概念
当前的计算机有大量不同的设备,很多都与I/O相关,每一种外设都有不同的特性和操作协议。操作系统负责这些设备的通信细节,并向程序员提供一个更简单的,更统一的I/O接口。
而ANSI C进一步的对I/O概念进行了抽象,就C程序而言,所有的I/O操作都是简单的程序移进、移出字节的事情,因此这种字节被称为流。这样程序员就只需要关注创建正确的输出字节数据,就已经正确解释从输入读取的字节。
绝大多数的流都是完全缓冲的,这就意味着“读取”和“写入”都是在一块被称为:缓冲区的内存区来回复制数据。从内存中来回复制数据是特别快的。用于输出流的缓冲区只有被写满时才会被刷新到设备或文件中。一次性把放满的缓冲区数据写入比逐片写入效率更高。
流被分为两种:文本流和二进制流
①文本流在不同的系统中实现不太相同。
②二进制流的字节完全是安装程序编写他们形式写入到文件和设备中。而且完全根据他们从文件或设备读取的形式读入到程序。
文件
在stdio.h中定义了一个FILE结构。
请不要把他和磁盘上的文件混淆。FILE是一个数据结构,用于访问一个流,如果你激活了几个流,每个流都会对应一个FILE结构。
对于每一个ANSI C程序而言,至少打开三个流:标准输入(stdin)、标准输出(stdout)、标准错误(stderr),他们都是指向FILE结构的指针。
通常:
标准输入为:键盘设备
标准输出为:终端或者屏幕
I/O常量
在stdio.h中定义了很多I/O常量
EOF 文件结束标致,表示文件到了结尾
FOPEN_MAX 一个程序最多打开的文件数
FILENAME_MAX 文件名的最大长度
I/O函数总览
1、程序必须为 同时处于活动状态的每一个文件 声明一个指针,其类型为:FILE*,
这个指针指向一个结构,当他处于活动状态的时由流使用。
2、流通过fopen函数打开,打开流的时候,必须指定需要访问的文件或者设备已经访问的方式。fopen函数和操作系统去验证文件或设备确实存在,验证访问方式,然后初始化FILE结构。
3、根据需要对文件进行读取和写入。
4、最后,fclose函数可以关闭流。关闭一个流可以防止与他相关的文件再次被访问,保证任何储存于缓冲区的数据都被正确的写入文件中。
输入、输出函数列表
打开流:
FILE* fopen(const char* filename,const char * mode);
代码演示:
#include
#include
int main(){
FILE* pFile;
pFile = fopen("1.txt","w");
if(pFile != NULL){
//fputs函数:在pFile文件中写入“fopen example”字符
fputs("fopen example",pFile);
fclose(pFile);
}
return 0;
}
代码运行结束后,我们会发现,在工程里面,出现一个1.txt文件,里面有字符:fopen example
关闭流:
代码演示:
#include
#include
int main(){
FILE* pFile;
pFile = fopen("1.txt","wt");
fprintf(pFile,"fclose example~!");
fclose(pFile);
return 0;
}
代码运行结束后,在1.txt文件中会出现“fclose example~!”的字样
getchar 和putchar函数:
int getchar(void)
int putchar(int character)
代码演示:
#include
#include
int main(){
int c;
//puts函数可以用于输出一行文本到标准输出流
puts("Enter text. Include a dot('.') in a sentence to exit:");
do{
//getchar吃从标准输入获取一个字符
c = getchar();
//putchar是向标准输出流输出一个字符
putchar(c);
}while(c!= '.');
return 0;
}
运行结果:
在屏幕打印出:Enter text.Include a dot('.') in a sentence exit:
此时在屏幕输入什么,就打印什么,直到碰到‘.’的时候结束退出
gets 和 putc 函数
int getc(FILE * stream)
int putc(int character,FILE * stream)
代码演示:
#include
#include
int main(){
FILE* pFile;
int c;
int n = 0;
pFile = fopen("1.txt","r");
if(pFile == NULL)perror("Error opening file");
else {
do{
c = getc(pFile);
if(c == '$')n++;
}while(c!= EOF);
fclose(pFile);
printf("File contains %d$.\n",n);
}
return 0;
}
代码功能:计算“1.txt”文件中‘$’的个数
代码演示:
#include
#include
int main(){
FILE* pFile;
char c;
pFile = fopen("alphabet.txt","wt");
for(c = 'A';c<'Z';c++){
putc(c,pFile);
}
fclose(pFile);
return 0;
}
代码功能:打开文件中的alphabet.txt文件,如果没有,就创建一个,“wt”中:t是按照文本方式打开,w是从头开始读写,若没有就创建一个。然后给c赋值为‘A’,c依次在字母表中递增,然后每一次都把字母写进
alphabet.txt文件中,程序结束时,alphabet.txt文件中就是字母表。
fgetc 和 fputc
int fgetc (FILE * stream)
int fputc(int character ,int FILE* stream)
getc 和 fgetc 功能一样
putc 和 fputc 功能一样
未格式化的行I/O
gets 和 puts函数
char* gets (char* str)
int puts(const char* str)
代码演示:
#include
#include
int main(){
char string1[]= "Hello World";
char string[256];
printf("Insert your full address");
gets(string);
printf("Your address is:%s\n",string);
puts(string1);
return 0;
}
fgets 和 fputs
char* fgets(char* str,int num,FILE* stream)
int fputs(const char* str,FILE* stream)
代码演示:
fgets:
#include
#include
int main(){
FILE* pFile;
char mystring[100];
pFile = fopen("1.txt","r");
if(pFile == NULL)perror("Error opening file");
else {
if(fgets(mystring,100,pFile)!= NULL)
puts(mystring);
fclose(pFile);
}
return 0;
}
代码演示:
代码功能:将屏幕输入的字符放到sentence中,再把sentence中的内容放到pFile所指向的文件中去。
#include
#include
int main(){
FILE* pFile;
char sentence[256];
printf("Enter sentence to append:");
pFile = fopen("1.txt","a");
fgets(sentence,256,stdin);
fputs(sentence,pFile);
fclose(pFile);
return 0;
}
格式化的I/o
fscanf 和 fprintf
int fscanf(FILE* stream,const char *format,...)
int fprintf(FILE* stream, const char* format,...)
代码演示:
fscanf:
代码功能,先把3.1416 和“PI”按照浮点数和字符的形式输入到pFile所指向的文件中去,在中文件中读取浮点数和字符类型的数,分别给f和str赋值。
#include
#include
int main(){
char str[80];
float f;
FILE* pFile;
pFile = fopen("1.txt","w+");
fprintf(pFile,"%f %s",3.1415,"PI");
rewind(pFile);//将写入的位置回到文件的起始位置。
fscanf(pFile,"%f",&f);
fscanf(pFile,"%s",str);
fclose(pFile);
printf("I have read : %f and %s \n",f,str);
}
fprintf:
代码演示:
#include
#include
int main(){
FILE* pFile;
int n;
char name[1000];
pFile = fopen("1.txt","w");
for(n = 0;n<3;n++)
{
puts("Please,enter a name:");
gets(name);
fprintf(pFile,"Name %d [%-10.10s]\n",n+1,name);
}
fclose(pFile);
return 0;
}
代码功能:
把输入的名字按照一定的格式在pFile所指向的文件中打印出来,也就是储存在文件中。
二进制I/O
size_t fread(void* ptr,size_t size,size_t count,FILE* stream)
size_t fwrite(const void * ptr,size_t size,size_t count,FILE* stream)
代码演示:
#include
#include
int main(){
FILE* pFile;
long lSize;
char* buffer;
size_t result;
pFile = fopen("1.txt", "rb");
if(pFile =NULL){
fputs("File error ",stderr);
exit(1);
}
//fseek:移动写入字尖到任意位置
fseek(pFile,0,SEEK_END);//最后一个参数传进去文件的结尾,则把写入字尖挪动到文件的文件结尾。
lSize = ftell(pFile);//返回光标的当前位置
rewind(pFile);//回到文件最开始的位置
buffer = (char*)malloc(sizeof(char)*lSize);
if(buffer == NULL ){
fputs("Memory error ",stderr);
exit(2);
}
result = fread(buffer,1,lSize,pFile);
if(result != lSize){
fputs("Reading error",stderr);
exit(3);
}
fclose(pFile);
free(buffer);
return 0;
}
fwrite:
#include
#include
int main(){
FILE* pFile;
char buffer[] = {'x','y','z'};
pFile =fopen("1.txt","wb");
fwrite(buffer,sizeof(char),sizeof(buffer),pFile);
fclose(pFile);
return 0;
}