zoukankan      html  css  js  c++  java
  • c博客06-2019-结构体&文件

    1.本章学习总结

    1.1 学习内容总结

    整理结构体和文件这两章主要知识点,必须包含内容有:

    1.结构体如何定义、成员如何赋值

    • 结构体一般形式
    struct  结构体名
        {
         数据类型   成员名1;
         数据类型   成员名2;
         :
         数据类型   成员名n;
         };
    
    • 结构体的定义及赋值
      • 先定义结构体类型再定义变量名,这是C语言中定义结构体类型变量最常见的方式。
          struct 结构体名
         {
                 成员列表;
         };
         struct 结构体名 变量名;
    
    - 在定义类型的同时定义变量。这种形式的定义的一般形式为:
    
    struct 结构体名
            {
                      成员列表;
            }变量名; 
    
    - 直接定义结构类型变量。其一般形式为:
    
    struct      //没有结构体名
             {
                       成员列表;
              }变量名;
    

    2.结构体数组排序做法

    • 结构体数组的排序方法与之前数组的排序方法差别并不大,这里列举一道学生信息按成绩排序的冒泡排序
    /*
    name:学生信息结构体  按总分排序 (降序)
    */
    
    
    #include<stdio.h>
    typedef struct {//结构体 定义时尽量放main()外面 
    	int grade;
    	int age;
    	char name[10];
    }Student;
    
    
    int main()
    {
    	int i, j;
    	Student temp;
    
    	Student student[3] = {/*分成多条初始化,更清晰*/ 
    	{600,18,"小明"},
    	{550,19,"小红"},
    	{700,20,"tom"},
    	};
    
    	  /*用结构体指针---提高效率*/
    	  /*冒泡排序*/
    
    	Student* p = student;
    	for (i = 1; i <= 2; i++)
    	{
    		for (j = 0; j <= 3 - i - 1; j++)//大-->小 
    		{
    			if ((p + j)->grade < (p + j + 1)->grade)
    			{
    				temp = *(p + j);
    				*(p + j) = *(p + j + 1);
    				*(p + j + 1) = temp;//注意 temp 的类型为Student 
    
    			}
    		}
    	}
    
    	/*以表的形式输出*/
    	printf("姓名    年龄    分数  
    
    ");//表头 
    	for (i = 0; i <= 2; i++)
    	{
    		printf("%-4s   %4d     %4d
    ", (p + i)->name, (p + i)->age, (p + i)->grade);
    	}
    
    	getchar();
    	return 0;
    }
    
    

    3.结构体指针怎么用
    在C语言使用中,随着知识的深入,我们结构体用到的机会很多。

    • 首先让我们定义结构体:
    struct stu
    {
    char name[20];
    long number;
    float score[4];
    };
    
    • 再定义指向结构体类型变量的指针变量:
    struct stu *p1, *p2 ;
    
    • 定义指针变量p 1、p 2,分别指向结构体类型变量。引用形式为:指针变量→成员;
    #include<stdio.h>
    #include <stdlib.h> //使用m a l l o c ( ) 需要
    struct data //定义结构体
    {
    	int day, month, year;
    };
    struct stu //定义结构体
    {
    	char name[20];
    	long num;
    	struct data birthday; //嵌套的结构体类型成员
    };
    int main() //定义m a i n ( ) 函数
    {
    	struct stu* student; //定义结构体类型指针
    	student = malloc(sizeof(struct stu)); //为指针变量分配安全的地址 
    	printf("Input name,number,year,month,day:/n");
    	scanf("%s", student->name); //输入学生姓名、学号、出生年月日
    	scanf("%ld", &student->num);
    	scanf("%d%d%d", &student->birthday.year, &student->birthday.month,
    		&student->birthday.day);
    	printf("/nOutputname,number,year,month,day/n");
    	/*打印输出各成员项的值*/
    	printf("%20s%10ld%10d//%d//%d/n", student->name, student->num,
    		student->birthday.year, student->birthday.month,
    		student->birthday.day);
    }
    

    4.共用体、枚举类型做法
    共用体

    • 共用体是一种多变量共享存储空间的构造类型,它允许几种不同的变量共用同一存储空间。
    • 共用体和结构体的区别:
      • 1.结构体每一位成员都用来表示一种具体事务的属性,共用体成员可以表示多种属性(同一存储空间可以存储不同类型的数据)。
      • 2.结构体总空间大小,等于各成员总长度,共用体空间等于最大成员占据的空间。
      • 3.共用体不能赋初值。

    枚举类型

    • 枚举类型是指变量的值可以全部列出,定义一个枚举变量后,变量的值确定在定义之中。
    • 它和结构体、共用体的区别在于,枚举元素是常量,只能在定义阶段赋值。

    5.文件读写,文件中数据如何读进结构体数组

    • 对文件的读和写是最常用的文件操作。在C语言中提供了多种文件读写的函数:
      • 字符读写函数 :fgetc和fputc
      • 字符串读写函数:fgets和fputs
      • 数据块读写函数:freed和fwrite
      • 格式化读写函数:fscanf和fprinf
    • 打开文件函数为fopen(),具体形式为
    fopen(“文件名”,“文件打开方式”);
    
    • 文件打开方式,具体有
    r	打开只读文件
    w	打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件
    a	以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留
    r+	打开可读写的文件
    w+	打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件
    a+	以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留
    

    1.2 本章学习体会

    学习感受
    学到现在,新的东西越来越多,平时觉得缺漏并不多,但是一到大作业时才发现自己的不足之处还有很多。这个学期很快就要结束了,我们的C语言课程也要迎来结束,在这个时候,查缺补漏才更为重要。在这两周学习的文件与结构体中,一开始确实感觉很难,但是运用时候,发现函数真的变得简洁了很多,尤其是多文件编程,好几百行代码在一个文件中的情况载用不会出现了。但是在结构体的运用中,尤其结构体数组和指针,老师讲的时候感觉指向的地址都很明了,但是自己在写的时候经常出错,果然还是练习的不够多...到期末了,各种各样的考试、总结和复习接踵而至,这两周对代码量也有所疏忽,希望能尽快赶上!

    2.综合作业--“我爱成语”(8分)

    本次作业要编写一个成语游戏。用户登录后,系统随机出若干个成语,如果答对则得分。用户得分写入成绩文件。系统能对用户成绩排名
    

    主要功能:

    • 登陆:需要输入正确用户名和 密码,才能登陆系统。错误提示错误的信息。
    • 成语游戏:从成语文件中随机抽一个成语,随机展示2个汉字,用户猜剩余汉字。如果答对,则得分。错误,给相应信息。
    • 排名:系统跟用户得分排名。
    • 退出。

    要求:

    • 本次作业必须建工程实现C的多文件。其中结构体定义、函数定义等都要封装在自定义头文件中。一个模块对应一个.h文件和.c文件。数据定义和数据实现分离。
    • 用户登录、排名信息的数据请封装结构体实现。
    • 涉及3个数据文件:user.txt、ranking.txt、idiom.txt
    • 尽量减少全局变量使用,数据传递通过地址、参数等传递。学会利用函数形参、返回值实现独立功能。
    • 菜单界面友好,任何一步都能随时推出,程序也 不会崩溃。程序界面要有清屏。
    • 尽量写一个函数调试一个函数,保证函数能读写文件数据再做下面内容。

    数据说明:

    • user.txt :用户名、密码
    • ranking.txt:用户名,答题总分数、最后答题时间。注意:答题分数是每次分数的积累,如答对一题5分,下一次同一个用户名再玩,这里数据能累加或更新。
    • idiom.txt:成语、成语解释。注意:给大家数据还包含数字,建议对数据预处理下,把数据改造成规范格式。成语:成语解释。出现其他如【】、数字等都过滤掉。数据统一格式才好读写。

    扩展功能

    • 本题可以做一个成语字典,用户输入成语,可以查询相应成语解释。这个查询可以是模糊查询,就是用户只输入一个汉字也可以查询所有相关的成语内容。
    • 游戏玩法可以多样,比如也可以做成语接龙,你写一个成语,根据最后一个汉字,系统能接龙下一个成语。如果是人机互玩,不是接龙规则,可提示。

    2.1.文件介绍

    头文件介绍


    • 头文件1:idiom.h
      功能介绍:定义了多个函数;IDIOM结构体:用于读取成语内容并储存;USER结构体:用于读取登录所需的账号与密码并储存。

    2.函数实现文件介绍。


    • 文件1:main.c。
      功能:令程序正常进行
      思路:在设计时,想主函数尽可能的简洁,因此大部分功能都使用了函数进行单独封装。

    • 文件2:users.c
      功能:读取并储存账号与密码,实现登录功能。
      思路:与林丽老师上课讲过的一样,同时借鉴了课堂派上的内容,定义了USER结构体来实现登录系统。

    • 文件3:Change.c
      功能:作为连接系统,打开并读取成语文件,是竟然两个主要功能的连接口,同时也可以有切换登录用户的功能。
      思路:因为老师说过一般打开文件都在主函数中打开,避免多次开关文件导致运行时间过长,因此一开始是把该函数的内容放在主函数中,但是后来为了实现切换登录用户的功能,写了这样一个函数。(个人能力有限)

    • 文件4:GetIdiomsData.c
      功能:最关键的将成语文件的成语内容与注释内容分开储存,并返回成语的个数number。
      思路:定义了IDIOM结构体数组来进行分别储存成语名与注释。

    • 文件5:Issue.c
      功能:出题系统,进行成语随机挖去两个空出题。同时在函数末尾进行一个继续或返回的选择。
      思路:在一开始进行写代码时,想通过遍历来随机出题,但是代码太长而且极易崩溃,让我挺头疼的。后来借鉴了同学的思路与代码,直接运用随机数来进行选择输出的成语和抹除的两个位置,同时运用复制函数,也避免了再重新定义一个数组。

    • 文件6:Search.c
      功能:查找系统,当用户输入文件中有的成语,输出该成语的意思。
      思路:因为成语名和注释已经分别储存了,且对应的成语和注释下标一样,所以只要利用循环遍历进行寻找即可。

    • 文件7:ListMenu.c
      功能:菜单函数
      思路:对用户进行提醒

    • 文件8:Choice.c
      功能:输入选择的功能并返回输入的选项choose
      思路:通过输入来进入不同的功能。

    • 文件9:End.c
      功能:结束函数,代表程序的结束
      思路:当用户选择退出时可以跳出,最后来到这个函数

    2.2.运行结果

    1.登录界面

    2.游戏界面



    3.查找界面


    2.3大作业总结

    1.碰到问题及解决办法

    • 首先是在出题函数,这个函数几乎花掉了一整个晚上的时间来写,删了许多次。一开始是定义了一共新的指针,令它直接等于随机出来的成语名,结果发现抹去字符后新定义的指针也一起被改变了,后来改用了复制函数才解决。其次是我之后删去了新指针,而是用了idiom[num + 2].IdiomName来储存。这样做其实是有弊端的,因为我事先知道我定义的数组内容远大于成语个数num,所以idiom[num + 2].IdiomName中其实是没有内容的,当时为了节约时间,也觉得这样可以避免重新定义指针占用更多的空间,就这么定义了。
    • 这次第一次使用清屏函数,刚刚开始老是用错地方,把有用的内容清掉。后来还是要一次一次调试慢慢改过来。
    • 这次大量使用了while(1)循环,没有写好条件容易造成死循环,每次写完都要经过多次调试才能确保没有问题。
    • 在读取文件内容时,因为不是操作不是很熟练,好多次没有加终止符号,再加上之前没有调好的while(1)循环,结果跳出来满屏的,吓了一跳,后来发现是在分离储存成语与注释的时候,在成语名赋值结束的末尾忘记加了。
    • 在写了很多次排名函数后都出现了运行错误或者引发异常的情况,不知道怎么处理,所以后面就先删去了排名函数,先完成其他功能。但是到现在还行没写出来,后续应该会慢慢地完善功能。

    2.小结

    • 一开始布置大作业时真的是不知从何下手。一共两周的时间,前一周基本都在构思作业思路,陆陆续续写了一些代码,这一周在林丽老师又复习过一次文件,已经机房课的指导后逐渐有了一些想法。但这周又碰到英语的4级考试 ,所以之前一直都是只完成了框架,大部分的内容是在这两天写出来的。
    • 个人感觉,相对于上一次,这一次写大作业的感觉要好得多,对于函数的运用也熟练了起来。但是对于新学习的知识,比如文件的运用,结构体的运用等还是不够熟练。(果然还是能力限制了我的发挥...)
    • 个人在运用指针的时候还是很生疏,以后还是要多练习指针内容。
    • 这一次对于一些新内容,比如清屏函数的运用多了起来。
  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/caihaoweideboke/p/12045575.html
Copyright © 2011-2022 走看看