参考书:《C Primer Plus》第六版
文章目录
1. 与文件进行通信
文件通常是在磁盘或固态硬盘上的一段已命名的存储区。
C提供两种文件模式:文本模式和二进制模式。
所有文件的内容都是以二进制形式存储,但如果文件最初使用二进制编码的字符(如ASCII或Unicode)表示文本,该文件就是文本文件,其中包含文本内容。如果二进制值代表机器语言代码或者数值或图片或音乐编码,该文件就是二进制文件。
2. 标准I/O
先看一个示例
程序清单1
#include"stdio.h"
#include"stdlib.h"
int main(int argc,char **argv){
int ch;
FILE *fp;
unsigned long count =0;
if(argc!=2){
printf("Usage: %s filename\n",argv[0]);
exit(EXIT_FAILURE);
}
if((fp=fopen(argv[1],"r"))==NULL){
printf("Can't open %s\n",argv[1]);
exit(EXIT_FAILURE);
}
while((ch=getc(fp))!=EOF){
putc(ch,stdout);
count++;
}
fclose(fp);
printf("File %s has %lu Characters\n",argv[1],count);
}
其中用到的exit()
函数关闭所有打开的文件并结束程序。它的参数被传递给系统。通常,正常结束时传递0,异常结束传递非零值。所以exit(0)
和return 0
二者可以起到同样的效果。但二者有着微小的差别。
程序清单1中用fopen()
函数打开文件。这个函数定义在stdio.h
中。它的第一个参数时文件名,第二个参数是一个字符串指定要打开的文件的模式。
如下:
- r:只读
- w:写模式打开文件,会覆盖现有文件,若文件不存在则新建
- a:写模式,在文件末尾追加内容,若文件不存在则新建
- r+:以更新模式打开文件,可读写
- w+:更新模式,文件存在则将其长度截为0,不存在则新建
- a+:更新模式,在文件末尾添加内容
- rb、wb、ab、rb+、wb+、ab+、r+b、w+b、a+b:与上面的类似,但以二进制模式打开文件
- wx、wbx、w+x、wb+x、w+bx:与不加x的类似,但如果文件已存在或者以独占模式打开文件,则打开文件失败
getc()
和putc()
函数使用时要指定使用的文件。
fclose(fp)
函数关闭fp指定的文件,必要时刷新缓冲区。如果关闭成功返回0,否则返回EOF。
stdio.h
把3个文件指针和3个标准文件相关联:
- 标准输入:stdin,使用键盘
- 标准输出:stdout,显示器输出
- 标准错误:stderr,显示器输出
3. 一个简单的文件压缩程序
程序清单2:
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#define LEN 40
int main(int argc,char**argv){
FILE *in,*out;
int ch;
char name[LEN];
int count=0;
if(argc<2){
fprintf(stderr,"Usage: %s filename\n",argv[0]);
exit(EXIT_FAILURE);
}
if((in=fopen(argv[1],"r"))==NULL){
fprintf(stderr,"I couldn't open the file\"%s\"\n",argv[1]);
exit(EXIT_FAILURE);
}
strncpy(name,argv[1],LEN-5);
name[LEN-5]='\0';
strcat(name,".red");
if((out=fopen(name,"w"))==NULL){
fprintf(stderr,"Can't create output file.\n");
exit(EXIT_FAILURE);
}
while((ch=getc(in))!=EOF){
if(count++%3==0)
putc(ch,out);
}
if(fclose(in)!=0 ||fclose(out)!=0)
fprintf(stderr,"Error in closing files\n");
return 0;
}
fprintf()
和printf()
函数类似,但它的第一个参数是一个文件指针。
4. 文件I/O:fprintf()、fscanf()、fgets()和fputs()
rewind()
函数接收一个文件指针作为参数,将程序回到文件开始处。
fgets(buf,STLEN,fp)
fputs(buf,fp)
5. 随机访问: fseek()和ftell()
feek()
的第一个参数是文件指针,第二个参数是偏移量,第三个参数是模式,该参数确定起始点。如下:
- SEEK_SET:文件开始处
- SEEK_CUR:当前位置
- SEEK_END:文件末尾
如果一切正常则返回0,如果出错(如试图移动的距离超出文件的范围)返回-1。
ftell()
函数的返回类型是long,返回的是参数指向文件的当前位置距文件开始处的字节数。
6. 编程练习
- 提示用户输入文件名并读取输入,然后打印文件。
#include"stdio.h"
#include"stdlib.h"
int main(void){
puts("Enter the Filename: ");
char fname[50];
if(scanf("%s",fname)==0){
fprintf(stderr,"error input\n");
exit(EXIT_FAILURE);
};
FILE* fp;
if((fp=fopen(fname,"r"))==NULL){
fprintf(stderr,"open file %s failed.\n",fname);
exit(EXIT_FAILURE);
}
char ch;int count=0;
while((ch=getc(fp))!=EOF){
putc(ch,stdout);
count++;
}
printf("The number of characters: %d\n",count);
fclose(fp);
}
- 编写一个文件拷贝程序。
#include"stdlib.h"
#include"stdio.h"
int main(int argc,char **argv){
if(argc<3){
fprintf(stderr,"Usage :%s filename:\n",argv[0]);
}
FILE *in,*out;
if((in=fopen(argv[1],"r"))==NULL){
fprintf(stderr,"Can't open file: %s\n",argv[1]);
exit(EXIT_FAILURE);
}
if((out=fopen(argv[2],"w"))==NULL){
fprintf(stderr,"Can't create file: %s\n",argv[2]);
exit(EXIT_FAILURE);
}
char ch;
while((ch=getc(in))!=EOF)
putc(ch,out);
if(fclose(in)==EOF||fclose(out)==EOF)
puts("Can't clost file.");
return 0;
}
- 编写一个程序,用
toupper()
函数将文本的所有字母转换成大写。
#include"stdio.h"
#include "stdlib.h"
#include"ctype.h"
int main(void){
char fname[50];
puts("Enter the file name:");
scanf("%s",fname);
FILE *fp;
if((fp=fopen(fname,"r+"))==NULL){
fprintf(stderr,"Usage: %s filename\n",fname);
exit(EXIT_FAILURE);
}
fseek(fp,0L,SEEK_END);//定位到文件结尾
long len=ftell(fp);
char* pst=(char*)calloc(len,sizeof(char));
char ch;
fseek(fp,0L,SEEK_SET);//定位到文件开头
int i=0;
while((ch=getc(fp))!=EOF){
pst[i++]=toupper(ch);
}
int max=i;
fseek(fp,0L,SEEK_SET);//定位到文件开头
for(i=0;i<max;++i){
putc(pst[i],fp);
}
free(pst);
fclose(fp);
return 0;
}
- 编写一个程序打开两个文件,并打印这两个文件。
#include"stdio.h"
#include"stdlib.h"
int main(int argc,char **argv){
if(argc<3){
puts("Error");
exit(EXIT_FAILURE);
}
FILE *f1,*f2;
if((f1=fopen(argv[1],"r"))==NULL){
printf("Open %s failed.\n",argv[1]);
exit(EXIT_FAILURE);
}
if((f2=fopen(argv[2],"r"))==NULL){
printf("Open %s failed.\n",argv[2]);
exit(EXIT_FAILURE);
}
char ch1=getc(f1);
char ch2=getc(f2);
int i=1;
while(ch1!=EOF||ch2!=EOF){
if(i==1){
putc(ch1,stdout);
if(ch1=='\n')
i=2;
if(ch1!=EOF)
ch1=getc(f1);
else
i=2;
}
else{
putc(ch2,stdout);
if(ch2=='\n')
i=1;
if(ch2!=EOF)
ch2=getc(f2);
else
i=1;
}
}
printf("\n");
fclose(f1);
fclose(f2);
return 0;
}
- 编写一个程序,统计一些文件中某个字符出现的次数。
#include"stdio.h"
#include"stdlib.h"
int main(int argc,char **argv){
if(argc==1){
puts("error");
exit(EXIT_FAILURE);
}
if(argc==2){
char ch;
char chf=argv[1][0];
int count=0;
while((ch=getchar())!=EOF){
if(ch==chf)
count++;
}
printf("%c occurs %d times.\n",chf,count);
return 0;
}
int i;
for(i=2;i<argc;i++){
FILE* fp;
if((fp=fopen(argv[i],"r"))==NULL){
printf("%s can't open.\n",argv[i]);
continue;
}
char ch;
char chf=argv[1][0];
int count=0;
while((ch=getc(fp))!=EOF)
if(ch==chf)
count++;
printf("'%c' occurs %d times in file \"%s\"\n",chf,count,argv[i]);
fclose(fp);
}
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c13# make prac8
cc prac8.c -o prac8
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c13# ./prac8 t text text1
't' occurs 124 times in file "text"
't' occurs 97 times in file "text1"
- 编写一个程序打开一个文件,提示用户输入要给数字然后该程序打印该位置到换行符之前的内容。
#include"stdio.h"
#include"stdlib.h"
#include"ctype.h"
int main(int argc,char**argv){
if(argc!=2){
puts("Error");
exit(EXIT_FAILURE);
}
FILE *fp;
if((fp=fopen(argv[1],"r"))==NULL){
printf("Can't open %s",argv[1]);
exit(EXIT_FAILURE);
}
puts("Enter a value:");
int val,ind=0;
char ch;
while(scanf("%d",&val)==1){
if(val>=0){
while ((ch=getc(fp))!=EOF)
{
if(ind++>val){
if(ch=='\n') break;
putchar(ch);
}
}
printf("\n");
}
else
break;
puts("Enter another value:");
}
printf("\n");
fclose(fp);
return 0;
}
Enter a value:
23
如我) - Jamillions
Enter another value:
44
Sometimes you feel he don't love you
Enter another value:
55
Strummin your pain with his finger nails to make it hurt
Enter another value:
45
Somtimes you feel he don't want you
Enter another value:
1
No matter how you try he just don't seem to know your worth
Enter another value:
a