C博客作业06--结构体&文件

第六次C博客作业


Q1.本章学习总结

1.1 学习内容总结

  • 结构体如何定义,成员如何赋值
    • 首先要定义一个结构体,常用的方法是
       struct 结构名
       {
            结构成员
       };    //注意这里有个分号
    • 然后需要在主函数中声明结构体变量,可在声明时对逐一结构成员进行赋初值,也可以采用 结构体变量名.结构成员名= 的方式进行赋值
    • 如果结构成员是char类型的,记得使用strcpy()函数进行赋值
       struct student
       {
            int num;
            int score;
       };   //这里分号前可以直接写上结构体变量名,用逗号分隔,这样在下面使用不用先声明
    
       int main()
       {
            struct student p = { 10,80 };   //声明时直接按成员顺序逐个赋值
            p.num = 10;     //中间用点连接,不能用->
            p.score = 80;
       }
    • 我们现在更支持使用typedef来定义结构体,和普通的定义基本一致,而且可以改变每次声明新的变量时都要写的struct xxx
       typedef struct student
       {
            int num;
            int score;
       }STU,*stu;
    
       int main()
       {
            STU a;  //等同于struct student a
            stu b;  //等同于struct student *b;
       }
  • 结构体数组排序做法
    • 个人觉得本质上和数组的排序基本一样,唯一要注意的点就是一个结构体赋值给另一个结构体时,所有的结构成员都会被替换
       typedef struct student
       {
        char name[10];
        int score;
       }STU;
    
       int main()
       {
        STU p[10], temp;
        int i, j;
    
        for (i = 0; i < 10; i++)
            scanf("%s %d", p[i].name, &p[i].score);   //给结构体数组赋值
    
        for (i = 0; i < 10; i++)
            for (j = i + 1; j < 10; j++)
                if (p[i].score < p[j].score)
                {
                    temp = p[i]; p[i] = p[j]; p[j] = temp;   //和数组的选择排序类似,只是交换的是一整个结构体里的内容而已
                }
       }
  • 结构体指针怎么用
    • 这个我认为也和普通的指针类似,只是类型从int/char这样子的变成了一整个结构体
    • 要注意取结构体指针的结构成员的写法,一般有下面的两种写法
       STU *p;
       (*p).score = 100;  //括号不能省略
       p->score = 100;   //更常见的写法
    
       p.score = 100;    //这是错的!!!!
    • 与普通指针类似,假设有STU *p=a(a是结构体数组),那么p即指向a[0] 的首地址,p+1指向a[1]的首地址
  • 共用体、枚举类型做法
    • 共用体和结构体长得很相似,但实际上它们大有不同:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。
    • 一般运用较少,在前几个结构成员相同,但因为几个结构成员不同导致后面要保存不同类型的内容时会用到。
    • 枚举类型个人认为与宏定义较类似,直接举例说明
       enum week{ Mon, Tues, Wed, Thurs, Fri, Sat, Sun };    //定义方式为enum 枚举类型名{每个值对应的名字};  分号!!
    
       /*这样子没有给初值定义完,默认Mon代表0,Tues代表1,以此类推*/
    
       enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };
    
       /*给了第一个名字初值,那么后面的Tues则为2,Wed为3,每个加1*/
    
       enum week day;    //枚举类型,输出星期的例子
       scanf("%d", &day);
       switch(day)
       {
          case Mon: puts("Monday"); break;
          case Tues: puts("Tuesday"); break;
          case Wed: puts("Wednesday"); break;
          case Thurs: puts("Thursday"); break;
          case Fri: puts("Friday"); break;
          case Sat: puts("Saturday"); break;
          case Sun: puts("Sunday"); break;
          default: puts("Error!");
       }
  • 文件读写,文件中数据如何读进结构体数组
    • 首先需要定义一个FILE类型的指针变量
    • 打开文件的方式为 文件指针名=fopen("文件名","文件操作方式")
      • 常用操作方式分为 r:只读;w:只写;a:追加在末尾;b:二进制文件;+:读和写
      • 其中,用"r"打开文件时,文件必须存在用"w"打开文件时,若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件
      • 文件可能会打开失败,这样fopen函数会返回NULL,在写程序时要注意对这部分有判断
      • 有打开就要有关闭,记得要用 fclose(文件指针名) 来关闭文件
    • 对文件数据进行读取、写入
      • fgets(用于储存的目标字符串,读取长度,文件指针名) 可以用于实现从目标文件中读取字符串,用法与注意事项以前使用fgets基本相同(会读入\n等),唯一不同的是最后一个从stdin(从键盘读入)改为了文件指针(从文件读入)
      • fputs(想要存入的字符串,文件指针名) 可以实现将字符串写入目标文件中
      • fputc、fgetc 用法与上面两个基本相同,从目标文件读入一个字符
      • fscanf、fprintf 与scanf、printf基本相同,按格式从文件中读取、写入数据
      • feof(文件指针名) 用于判断文件是否已经读到末尾
      /*文件中数据读入结构体数组简单样例*/
      typedef struct student
      {
       char name[10];
       int score;
      }STU;        
      
      int main()
      {
           FILE* fp;
           STU p[50];
           int i = 0;
      
       fp = fopen("stu.txt", "r+");
       if (fp == NULL)    //记得要对打不开的情况做判断
       {
           exit(1);
       }
      
       while (!feof(fp))
       {
           fscanf(fp, "%s %d", p[i].name, &p[i].score);
           i++;
       }
      
       fclose(fp);    //读完记得关闭文件!!
      }
    • 其他一些对文件进行操作的函数
      • fseek(FILE *stream, long offset, int fromwhere):函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere( 偏移起始位置:文件头为0(SEEK_SET),当前位置为1(SEEK_CUR),文件尾为2(SEEK_END) )为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
      • ftell(FILE *stream):用于得到文件位置指针当前位置相对于文件首的偏移字节数。
      • rewind(FILE *stream):将文件内部的位置指针重新指向开头。
      • remove(char *filename):用于删除指定文件。
      • rename(char oldname, char newname):将指定文件进行更名。

1.2 本章学习体会

  • 上半学期C语言的学期也进入了尾声,文件部分感觉通过一次大作业已经掌握了很多
  • 而对于链表,我也试着将它运用到大作业里面,虽然写程序的时候遇到很多磕碰,但还是成功用链表写了程序的一部分
  • 虽然是老生常谈了,但还是想说要多实践多运用,可能在课堂上听着感觉链表挺简单的,但一上手写起来又是生不如死了(脑子:我学会了 手:不,你不会)
  • 没有任何捷径,多敲代码才是真理
  • 代码量(本次大作业):887行

Q2.综合作业--“我爱成语”

2.1 文件介绍

2.1.1 头文件 idiom.h

  • 头文件中所有的结构体、函数声明以及函数的功能全部在截图上的注释中

C博客作业06--结构体&文件_第1张图片

2.1.2 文件1 main.cpp

  • 主界面函数功能
    • 先在这里读取文件,检查文件是否存在
    • 导入到登录界面、游戏的主菜单
    • 根据用户不同的选择进入不同的函数
    • 普通的主函数,没有啥设计思路。。
  • 代码截图
    C博客作业06--结构体&文件_第2张图片

2.1.3 文件2 main.cpp

你可能感兴趣的:(C博客作业06--结构体&文件)