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("姓名    年龄    分数  \n\n");//表头 
	for (i = 0; i <= 2; i++)
	{
		printf("%-4s   %4d     %4d\n", (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级考试 ,所以之前一直都是只完成了框架,大部分的内容是在这两天写出来的。
  • 个人感觉,相对于上一次,这一次写大作业的感觉要好得多,对于函数的运用也熟练了起来。但是对于新学习的知识,比如文件的运用,结构体的运用等还是不够熟练。(果然还是能力限制了我的发挥...)
  • 个人在运用指针的时候还是很生疏,以后还是要多练习指针内容。
  • 这一次对于一些新内容,比如清屏函数的运用多了起来。
posted on 2019-12-15 20:37  蔡浩伟  阅读(307)  评论(2编辑  收藏  举报