C语言学习(九)文件输入/输出

参考书:《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. 编程练习

  1. 提示用户输入文件名并读取输入,然后打印文件。
#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);
}
  1. 编写一个文件拷贝程序。
#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;
}
  1. 编写一个程序,用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;
}
  1. 编写一个程序打开两个文件,并打印这两个文件。
#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;
}
  1. 编写一个程序,统计一些文件中某个字符出现的次数。
#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"
  1. 编写一个程序打开一个文件,提示用户输入要给数字然后该程序打印该位置到换行符之前的内容。
#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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值