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

构造类型-枚举

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

  • 定义

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

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

说明:

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

特点:

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

提供了代码的可读性。

定义语法:

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

c 复制代码
enum 枚举类型名 变星列表;

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

c 复制代码
enum 枚举类型名{枚举元素列表}变星列表;

直接定义枚举变量

c 复制代码
enum{枚举元素列表}变星列表;

案例

c 复制代码
#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,2
	return 0;
}

typedef

说明:

​ 给类型重命名,不会影响到类型本身

​ 作用:给已有的类型起别名

格式:

c 复制代码
typedef 已有类型名 新别名;

使用:

c 复制代码
//方式一
//定义一个结构体类型
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:类型重命名后数据类型

  • 案例

    c 复制代码
    #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)
    c 复制代码
    #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)
c 复制代码
#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
  • 案例

    c 复制代码
    #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)
    c 复制代码
    #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)
  • 案例:

    c 复制代码
    #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文件

c 复制代码
#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

      • 写入文件
      c 复制代码
      #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();
          }
      }
    • 数据块的读

      c 复制代码
      #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

    案例:

    C 复制代码
    #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);
    }
    案例二:
    c 复制代码
    #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)
        {
           // 跳过对应位置,改变文件指针的指向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;
    }

/循环录入

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;
}
相关推荐
是店小二呀1 分钟前
【Linux】Linux开发利器:make与Makefile自动化构建详解
linux·运维·自动化
qq_433554548 分钟前
C++ 面向对象编程:递增重载
开发语言·c++·算法
一只自律的鸡17 分钟前
C语言项目 天天酷跑(上篇)
c语言·开发语言
带多刺的玫瑰29 分钟前
Leecode刷题C语言之切蛋糕的最小总开销①
java·数据结构·算法
巫师不要去魔法部乱说40 分钟前
PyCharm专项训练5 最短路径算法
python·算法·pycharm
BUG 4041 小时前
LINUX--shell
linux·运维·服务器
菜鸟小白:长岛icetea1 小时前
Linux零基础速成篇一(理论+实操)
linux·运维·服务器
深海的鲸同学 luvi1 小时前
【HarmonyOS NEXT】hdc环境变量配置
linux·windows·harmonyos
qystca1 小时前
洛谷 P11242 碧树 C语言
数据结构·算法
冠位观测者1 小时前
【Leetcode 热题 100】124. 二叉树中的最大路径和
数据结构·算法·leetcode