欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > C语言基础十六:枚举、c语言中文件的读写操作

C语言基础十六:枚举、c语言中文件的读写操作

2025/9/26 21:19:27 来源:https://blog.csdn.net/m0_64837308/article/details/144684115  浏览:    关键词:C语言基础十六:枚举、c语言中文件的读写操作

构造类型-枚举

建议:如果定义不相干的常量,使用宏定义:如果需要定义一组相关的常量,使用枚举。以后正式开发switch的case后访问的就是枚举。

  • 定义

    我们一般情况下,定义常量使用宏定义(#define 红名称值),宏定义非常适合没有关联关系的常量;但是有时候我们可能需要对一组拥有关联关系的量进行定义,比如 ==周一周日、1月12月、方向(上下左右中)等,那么使用宏定义,就不是很清晰,这时就需要用到枚举。

    枚举的存在就是将多个拥有关系的常量组合到一起,提高代码的可读性。

说明:

  • 枚举类型定义了一组常量,我们在开发中直接使用这些常量。(常用)
  • 当然枚举类型也可以类似于结构体一样定义变量等操作。(不常用)
  • 枚举常量有默认值,从0开始依次+1;我们可以在定义时指定它的默认值,如果个别没有赋值,可以根据赋值依次+1推导。

特点:

定义了一组常量,类似于定义了多个自定义常量(宏定义)。

提供了代码的可读性。

定义语法:

定义枚举类型名以后就可以定义该枚举类型的变量

enum 枚举类型名 变星列表;

在定义枚举类型的同时定义该枚举类型的变量。

enum 枚举类型名{枚举元素列表}变星列表;

直接定义枚举变量

enum{枚举元素列表}变星列表;

案例

#include <stdio.h>
int main()
{// 定义一个枚举类型//枚举类型名一般首字母大写,主要是根枚举变量区分enum Week{//定义枚举元素,元素命名要符合标识符命名规则,同时采用大写字母+下划线方式命名SUN=10,MON,TUE,WED,THU,FRI,SAT};//直接访问枚举printf("%d,%d,%d\n",SUN,WED,SAT);// 定义枚举类型的变量(先定义变量,后赋值)enum Week week;week =	TUE;printf("%d\n",week);//一定是这个枚举类型中定义的元素// 定义枚举类型变量的同时赋值(定义变量和赋值同时进行)enum Week week1 = THU;printf("%d\n",week);enum H{A,B,C//多个元素使用逗号分隔}x,y;x=B;y=C;printf("x=%d,y=%d\n",x,y);//1,2return 0;
}

typedef

说明:

​ 给类型重命名,不会影响到类型本身
​ 作用:给已有的类型起别名

格式:

typedef 已有类型名 新别名;

使用:

//方式一
//定义一个结构体类型
struct student
{int id;char *name;char sex;int age;
};
// 类型重命名
typedef struct Student Stu;
//定义结构体变量
struct Stu stu={1,"张”,'w',21};
//方式2
typedef struct PersonInfo
{int a;double b;
}Per;//结构体类型的别名,本质上还是数据类型
//定义变量
struct Per per = {2,5};
  • 应用场景:

    • 数据类型复杂(结构体、共用体、枚举、结构体指针、无符号的长整型)时使用

    • 为了跨平台兼容性,例如:

      1.size_t;类型重命名后的数据类型:typedef unsigned long size_t;

      2.unit 16:类型重命名后数据类型

  • 案例

    #include<stdio.h>
    struct student
    {int age;char* name;double score;
    }
    int arr[3];
    typedef struct student Stu_t;
    typedef Stu_t* pstu_t;
    void test1()
    {Stu_ts1={23,"zhangsan",23.33,{11,22,33}};printf("%d,%s,%f,%d\n",s1.age,s1.name, s1.score, s1.arr[0]);//Stu t *p = &s1;Stu t* p;p = &s1;pStu_t p2;p2 = P;printf("%d,%s,%f,%d\n",p2->age,p2->name,p2->score, p2->arr[0]);
    }
    

文件操作

概述

  • 什么是文件?

    文件是保存在外存储器(一般代指磁盘,U盘,移动硬盘等)的数据的集合。

  • 文件操作体现在哪几个方面

    1.文件内容的读取

    2.文件内容的写入

    数据的读取和写入可被视为针对文件进行输入(input)和输出(output)操作,此时数据像水流一样从外存储器流向内存,或者从内存流向外存储器,所以系统形象的成文件操作为文件流

    C语言程序对文件的操作采用“文件缓冲机制"。就是说在程序对文件的数据读写并不是直接操作文件中的数据,而是系统会为文件在内存中创建“文件缓冲区",程序对文件的操作,其实是在缓冲区进行的。

    在这里插入图片描述

    • 文件的分类

      根据数据的存储方式划分:

      文本文件(ASCII文件)

      二进制文件

    • 文件的标识

      ①文件系统中:路径+文件名,举例d:/aaa/bbb.txt

      ②C语言程序中:文件指针(文件类型指针),语法:FILE*指针变量名;

    • 文件操作的步骤:

      打开文件

      文件处理(读写文件)

      关闭文件

文件的操作

文件的打开与关闭

打开文件

打开文件,让系统为文件创建文件缓冲区

  • 函数名:fopen()
  • 头文件:#include <stdio.h>
  • 函数原型:FILE* fopen(const char *path,const char *mode)`
  • 函数功能:打开文件,并为文件创建缓冲区
  • 函数参数:
    • "path:目标文件的路径
    • mode:文件打开的方式(读-,写-w,读写-r+,二进制-读rb,二进制写-rw,附加-a)
  • 返回值:
    • 成功:返回文件指针FILE*(缓冲区首地址)
    • 失败:返回NULL;
关闭文件

文件关闭,文件使用完毕,一定要释放内存

  • 函数名:fclose

  • 头文件: #include<stdio.h>

  • 函数原型: int fclose(FILE *fP)

  • 函数功能:

    • fp:已经打开的文件指针
  • 返回值:

    • 成功:返回0
    • 失败:返回EOE(-1)
    #include <stdio.h>
    int main()
    {//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc<2){printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);return -1;}// 根据提供的文件路径,打开文件FILE* fp = fopen(argv[l],"1");//校验文件是否读取成功if(!fp){perror("文件打开失败\n");return -1;}puts("文件打开成功!\n");//关闭文件int ret = fclose(fp);if(ret==-1){perror("文件关闭失败");return -1}puts("关闭成功");
    }
    
文件的顺序读写
单字符读取

函数名:fgetc

头文件:#include <stdio.h>

函数原型::`int fgetc(FILE *fp);

函数功能:从fp代表的文件中获取一个字符

  • 函数参数:
    • fp我们需要操作的文件的指针
  • 返回值:
    • 成功:返回读取到的字符
    • 失败:或者文件末尾,返回EOF(-1)
#include <stdio.h>
int main()
{//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc<2){printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);return -1;}// 根据提供的文件路径,打开文件FILE* fp = fopen(argv[l],"1");//校验文件是否读取成功if(!fp){perror("文件打开失败\n");return -1;}puts("文件打开成功!\n");int re =0;//char ch;while((re=fgetc(fp))!=-1)//while(ch=fgetc(fp)!=EOF)printf("%c\n",re);//   printf("%c\n",re);//关闭文件int ret = fclose(fp);if(ret==-1){perror("文件关闭失败");return -1}puts("关闭成功");
}

多字符读取

  • 函数名:fgets0

  • 头文件:#include <stdio.h>

  • 函数原型:char*fgets(char *buf,int size,FILE* fp);

  • 函数功能:从如代表的文件中获取size个字符(size大小以字节为单位),放置在buf代表的内存中

  • 函数参数:

    • buf:内存空间首地址用于存放读取的字节
    • size:待读取的字符,实际读取size
    • fp:已经打开文件的指针
  • 返回值:

    • 成功:返回buf
    • 失败:或者文件末尾,返回NULL
  • 案例

    #include <stdio.h>
    #include <string.h>
    int main()
    {//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc<2){printf("输入有误,请按照<%s 文件路径>格式输入\n",argv[0]);return -1;}// 根据提供的文件路径,打开文件FILE* fp = fopen(argv[l],"1");//校验文件是否读取成功if(!fp){perror("文件打开失败\n");return -1;}puts("文件打开成功!\n");char buf[64]={0};while((re=fgets(buf,64,fp))!=NULL){printf("%s\n",buf);memset(buf,0,sizeof(buf));}//关闭文件int ret = fclose(fp);if(ret==-1){perror("文件关闭失败");return -1}puts("关闭成功");
    }
    

    单字符写入

    • 函数名:fput
    • 头文件: #include<stdio.h>
    • 函数原型: int fputc(int c,FILE*fp);
    • 函数功能:向fp代表的文件中写入一个字符c
    • 函数参数:
      c:待写入的字符
      fp:已打开的文件指针
    • 返回值:
      • 成功:返回字符c
      • 失败:返回EOF(-1)
    #include <stdio.h>
    #include <string.h>
    int main()
    {//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc<2){printf("输入有误,请按照<%s 文件路径 文本数据>格式输入\n",argv[0]);return -1;}// 根据提供的文件路径,打开文件FILE* fp = fopen(argv[l],"w");//校验文件是否读取成功if(!fp){perror("文件打开失败\n");return -1;}puts("文件打开成功!\n");//借助循环,一个字符一个字符写入while(*argv[2]!='\0'){fputc(*argv[2],fp);argv[2]++;}//关闭文件int ret = fclose(fp);if(ret==-1){perror("文件关闭失败");return -1}puts("关闭成功");
    }
    

多字符写入

  • 函数名:fputs

  • 头文件: #include<stdio.h>

  • 函数原型: int fputs(int c,FILE*fp);

  • 函数功能:向fp代表的文件中写入一个字符数组buf[]

  • 函数参数:
    buf:待写入的字符数组
    fp:已打开的文件指针

  • 返回值:

    • 成功:返回非负整数(>0)
    • 失败:返回EOF(-1)
  • 案例:

    #include <stdio.h>
    #include <string.h>
    int main()
    {//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc<2){printf("输入有误,请按照<%s 文件路径 文本数据>格式输入\n",argv[0]);return -1;}// 根据提供的文件路径,打开文件FILE* fp = fopen(argv[l],"w");//校验文件是否读取成功if(!fp){perror("文件打开失败\n");return -1;}puts("文件打开成功!\n");//借助循环,一个字符一个字符写入fputs(fargv[2],fp);//关闭文件int ret = fclose(fp);if(ret==-1){perror("文件关闭失败");return -1}puts("关闭成功");
    }
    
综合案例

实现从a文件读取内容,写入到b文件

#include <stdio.h>
#include <string.h>
int main()
{//在命令行执行./a.out的时候,传递一个需要打开的目录文件的地址if(argc<3){printf("输入有误,请按照<%s 读文件路径 写文件路径>格式输入\n",argv[0]);return -1;}// 根据提供的文件路径,打开文件FILE* fp1 = fopen(argv[l],"1");FILE* fp2 = fopen(argv[2],"2");//校验文件是否读取成功if(!fp1||!fp2){perror("文件打开失败\n");return -1;}puts("文件打开成功!\n");char buf[64]={0};while((re=fgets(buf,64,fp1))!=NULL){//printf("%s\n",buf);fputs(buf,fp2);memset(buf,0,sizeof(buf));}//关闭文件int ret1 = fclose(fp1);int ret2 = fclose(fp2);if(ret1==-1||ret2==-1){perror("文件关闭失败");return -1}puts("关闭成功");
}
判别文件结束
  • 函数名:feof(fp)
  • 头文件: #include<stdio.h>
  • 函数原型: int feof(fp);
  • 函数功能:在读如指向的文件时判断是否遇到文件结束。
  • 函数参数:
    • fp:已打开文件的指针
  • 返回值:
    • 文件未读取完毕:返回0
    • 文件已读取完毕:返回非0
数据块的读写
数据块的读取
  • 函数名:fread
  • 函数原型: size_t fread(void* ptr,size_t size,size_t count,FILE* fp);int arr[4]
  • 函数功能:从fp代表的文件中以字节为单位(一个数据块)读取count个数据块存放在内存中。
  • 函数参数:
    • ptr:内存空间首地址,用于存放读到的数据(任意类型缓冲数据)
    • size:数据块大小,以字节为单位
    • count:带读取的数据块的个数
    • fp:已打开的文件指针
  • 返回值:
    • 成功:返回实际读取的字节数大小
    • 失败:返回<0
数据块的写入
  • 函数名: fwrite

  • 函数原型:size_t fwirte(const void* ptr,size_t size, FILE*fp)

  • 函数功能:向fp代表的文件中以size为一个数据块写入count个数据块存放在内存中。

  • 函数参数:

    • ptr:内存空间首地址,用于存放写入的数据(任意类型缓冲数据)
    • size:数据块大小,以字节为单位
    • count:待写入的数据块的个数
    • fp:已打开的文件指针
  • 返回值:

    • 成功:返回实际写入的字节数大小

    • 失败:返回<0

      • 写入文件
      #include <stdio.h>
      #define SIZE 4//学生数量
      //创建学生结构体
      struct Student
      {char name[20];int num;int age;char addr[50]
      }stus[SIZE];
      void save()
      {FILE *fp;int i;//打开文件if((fp=fopen("stu-list","wb"))==NULL)//wb二进制写入{perror("文件打开失败");return -1;}//写入数据for(i=0;i<SIZE;i++){fwrite(&stud[i],sizeof(struct Student),1,fp);}//关闭文件fclose(fp);return 0;
      }
      int main(int argc,char *argv[])
      {int i;printf("请输入学生的信息:姓名,学号,年龄,住宅\n");for(i=0;i<SIZE;i++){scanf("%s%d%d%s",stus[i].name,&stus[i].num,&stus[i].age,stus[i].addr);save();}
      }
      
    • 数据块的读

      #include <stdio.h>
      #define SIZE 4//学生数量
      //创建学生结构体
      struct Student
      {char name[20];int num;int age;char addr[50]
      }stus[SIZE];
      int main(int argc,char *argv[])
      {int i;FILE*fp;if((fp = fopen("stu-list"."rb"))== NULL)//rb 以二进制读取{perror("文件打开失败!");return -1;}printf("请输入学生的信息:姓名,学号,年龄,住宅\n");for(i=0;i<SIZE;i++){fread(&stuslil,sizeof(struct student),1,fp);// 将读取的数据输出到控制台printf("%-10s%4d%4d%-20s\n",stus[i].name,stus[i].num,stus[i].age,stus[i].addr);fclose(fp);}
      }
      
文件的随机读写
  • 说明:C语言允程序员在读写文件内容的时候,可以在指定位置上读写数据

  • 文件随机读写的核心操作:文件位置指针的定位

  • 文件位置指针移动方法:

    • rewind

      • 头文件: #include <stdio.h>

      • 函数原型: void rewind(FILE* fp)

      • 函数功能:将文件位置指针定位到文件开头

      • 函数参数:

        • fp:已经打开文件的指针
        • 返回值:空类型
      • fseek

        • 头文件: #include <stdio.h>
        • 函数原型: int fseek(FILE* fp,long offset,int whence);
        • 函数功能:将文件位置指针定位到指定位置
        • 函数参数:
          • fp:已经打开的文件的指针
          • ofset:相对于参考位置的偏移量
          • whence:参考位置
            • SEEK_SET 或0:表示文件头
            • SEEK_CUR 获1:表示当前读写的位置
            • SEEK_END 或2:表示文件尾
          • 返回值
            • 成功:0
            • 失败:-1
      • ftell

        • 头文件: #include<stdio.h>
        • 函数原型: long ftell(FILE* fp)
        • 函数功能: 获取文件位置指针当前位置
      • 函数参数:

        • fp:已经打开的文件的指针
      • 返回值

        • 成功:0

        • 失败:-1

    案例:

    #include <stdio.h>
    /*
    *一个磁盘文件,第一次将它的内容通过控制台输出,第二次把它复制到另一个文件上。
    */
    int main()
    {if(argc<2){perror("请使用<%s 被读取文件 被写入文件>的方式!\n"}return -1;}//创建两个指针,用来接收打开的文件FILE *fp1,*fp2;fp1=fopen(argv[1],"r");fp2=fopen(argv[2],"w");// 第一次,读取文件内容通过控制台打印           while(!feof(fp1))putchar(getc(fp1));//输出到控制台//将指针指问文件的头,否则下次读取文件,会读取不到内容 rewind(fp1);// 第二次,读取文件内容将其拷贝至fp2对应的文件中while(!feof(fp1))putc(getc(fp1),fp2);//输出到文件//关闭文件fclose(fp1);fclose(fp2);
    }
    
    案例二:
    #include <stdio.h>
    #include <stdlib.h>
    //需求:在磁盘文件上存储10个学生的数据,要求第1,3,5,7,9个学生数据输入计算机,并在屏幕上显示出来。
    typedef struct Student
    {char name[20];int num;int age;char sex;
    }Stu;
    //创建一个学生数组
    Stu stu[10]={0};
    int main()
    {int i;FILE *fp;//打开文件if((fp = fopen("stu-dat","rb"))==NULL){perror("文件打开失败!\n");return -1;}//循环录入for(i=0;i<10;i+=2){// 跳过对应位置,改变文件指针的指向7fseek(fp,i*sizeof(Stu),0);fread(&stu[i],sizeof(Stu),1,fp);//输出到控制台printf("%s,%d,%d,%c\n",stu[i].name,stu[i].num,stu
    [i].age,stu[i].sex);}
    }
    

    案例:

    #include <stdio.h>
    //下列c程序的功能是,用“追加"的形式打开文件gg.txt,查看文件读写指针的位置,
    //然后向文件写入“data",再查看文件读写指针的位置。
    int main()
    {long p;FILE*fp;if((fp = fopen(argv[1],"a"))==NULL)//此时的mode:a代表追加(a是append){perror("文件打开失败!");return -1;}p=ftell(fp);printf("%ld",p);// 向文件添加数据fputs("data",fp);p = ftell(fp);printf("p=%ld\n",p);fclose(fp);return 0;
    }
    

/循环录入
for(i=0;i<10;i+=2)
{
// 跳过对应位置,改变文件指针的指向7
fseek(fp,i*sizeof(Stu),0);
fread(&stu[i],sizeof(Stu),1,fp);
//输出到控制台
printf(“%s,%d,%d,%c\n”,stu[i].name,stu[i].num,stu
[i].age,stu[i].sex);
}
}


案例:```c
#include <stdio.h>
//下列c程序的功能是,用“追加"的形式打开文件gg.txt,查看文件读写指针的位置,
//然后向文件写入“data",再查看文件读写指针的位置。
int main()
{long p;FILE*fp;if((fp = fopen(argv[1],"a"))==NULL)//此时的mode:a代表追加(a是append){perror("文件打开失败!");return -1;}p=ftell(fp);printf("%ld",p);// 向文件添加数据fputs("data",fp);p = ftell(fp);printf("p=%ld\n",p);fclose(fp);return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词