c博客06-2019-结构体&文件
1.本章学习总结
1.1 学习内容总结
1.1.1 结构体如何定义、成员如何赋值
//结构体声明:
struct student
{
int stuNum;//学号
char name[10];//学生姓名
int score;//分数
};//注意分号不能少,这也相当于一条语句
1.首先使用关键字struct,它表示接下来是一个结构体
2.后面是一个可选的标志(student),它是用来引用该结构体的快速标记
因此我们以后就可以这样创建数据对象
struct student something;
把something设为一个可以使用student结构体的结构体变量,则something这个变量就包含了其student结构体中的所有元素
3.接下来就是一个花括号,括起了结构体成员列表,及每个成员变量,使用的都是其自己的声明方式来描述,用分号来结束描述
例如:char name[10];字符数组就是这样声明的,用分号结束
4.在结束花括号后的分号表示结构体设计定义的结束
struct student的作用:
在结构体声明中,struct student所起到的作用就像int、double等基础数据类型名作用一样
struct student s1,s2,*ss;
定义两个struct student结构体类型的结构体变量,还定义了一个指向该结构体的指针,其ss指针可以指向s1,s2,或者任何其他的student结构体变量
1.1.2 结构体数组排序做法
void sortStr(struct student* stu, int n)
{
int i, j;
struct student temp;
for(i=0;i<n-1;i++)
{
for (j = 0; j < n - i - 1; j++)
{
if (stu[j].score < stu[j + 1].score)
{
temp = stu[j];
stu[j] = stu[j + 1];
stu[j + 1] = temp;
}
}
}
}
1.1.3 结构体指针怎么用
# include <stdio.h>
struct student
{
int stuNum;
char name[10];
int score;
};
int main(void)
{
struct student stu[5] = {{22,"小红", 75}, { 21,"小明", 63}, {23,"小七", 82}};
struct student *p = stu;
return 0;
}
-
此时指针变量 p 就指向了结构体数组的第一个元素,即指向 stu[0]。我们知道,当一个指针指向一个数组后,指针就可以通过移动的方式指向数组的其他元素。
-
这个原则对结构体数组和结构体指针同样适用,所以 p+1 就指向 stu[1] 的首地址;p+2 就指向 stu[2] 的首地址……所以只要利用 for 循环,指针就能一个个地指向结构体数组元素。
-
同样需要注意的是,要将一个结构体数组名赋给一个结构体指针变量,那么它们的结构体类型必须相同。
1.1.4 共用体、枚举类型做法
共用体变量的定义、初始化和引用
- 定义
union 共用体名
{
数据类型 成员1;
数据类型 成员2;
数据类型 成员3;
...
}共用体 变量名列表;
union 共用体名 共用体变量名列表;
1.当一个共用体变量被定义后,编译程序会自动给变量分配存储空间,其长度为共用体数据成员中所占内存空间最大的成员的长度。
2.共用体变量的初始化,和结构体变量的初始化截然不同。由于共用体的成员共占用一个首地址,所以在任何时刻只能存放其中一个成员的值。所以,在对共用体变量进行定义并初始化时,只能对其中的第一个成员赋初值,即给其赋予一个和第一个成员类型相同的常量,初值需要用大括号括起来。
3.也就是说,共用体变量初始化的时候只能给第一个成员赋初值,但是其他时候可以通过对共用体变量成员的引用来进行赋值。同时,不能直接引用共用体变量,只能引用变量中的成员,除非将一个共用体变量赋值给另一个同类型的共用体变量。
枚举
在实际问题中,有些变量的取值被限定在一个有限的范围内。为此,C语言提供了一种称为“枚举”的类型,在枚举类型的定义中列举出所有的可能的取值,被说明为该枚举类型的变量取值不能超过定义的范围。
- 枚举定义
enum 枚举名
{
枚举值[=整型常量],
枚举值[=整型常量],
...
枚举值[=整型常量],
}变量列表;
-
如果枚举枚举值没有初始化,也就是声明中[=整型常量]没有定义,则从第一个枚举值开始,顺序赋给标识符0,1,2,3,4……但是当枚举中的某个成员赋值后,其后面的成员按顺序依次加1
-
枚举成员之间用逗号分隔,不是分号
-
枚举成员初始化时可以赋予负数,但是依次加1的规律不变
-
枚举值是常量,不是变量,不能在程序中用赋值语句再对它进行赋值
-
只能把枚举值赋予给枚举变量,不能把元素的数值直接赋予枚举变量
1.1.5 文件读写,文件中数据如何读进结构体数组
- 文本文件(ASCII)
使用方式 | 含义 |
---|---|
r | 打开只读文件,该文件必须存在 |
r+ | 打开可读写的文件,该文件必须存在 |
w | 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件 |
w+ | 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件 |
a | 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留 |
a+ | 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留 |
- 二进制文件
使用方式 | 含义 |
---|---|
rb | 打开只读文件,该文件必须存在 |
rb+ | 打开可读写的文件,该文件必须存在 |
wb | 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件 |
wb+ | 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件 |
ab | 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留 |
ab+ | 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留 |
1.2 本章学习体会
1.2.1 学习感受
- 结构体定义的话一开始预习上课什么的还是懵懵的,后来通过写大作业吧,有熟练了一点,以及多文件编程,一开始听就觉得很高大上感觉是我不会写出来的东西,也是大作业让我变得熟练了,果然还是要实践才能真正熟练代码操作
- 再然后是链表,早早意识到链表的威力之后,我就先看了翁恺的课,还是似懂非懂,经过老师上的几次课,我懂了怎么插入和删除结点,但是吧,前面链表具体怎么操作的还是不清楚,在这次链表实验作业里要好好摸索一下
1.2.2 代码量
- 代码量:484
2.综合作业--“我爱成语”
2.1 文件介绍
2.1.1 头文件“idiom.h”
结构体or函数声明 | 功能 |
---|
include<stdio.h>|必用啦
include<stdlib.h>|随机函数使用
include<string.h>|字符串处理使用
include<windows.h>|计时函数使用
typedef struct {}IDIOM|定义结构体用来存储成语及释义
void ListMenu()|菜单函数
void GetChoice()|选择函数
void Login()|登录系统函数
int GetIdiom(IDIOM* i, FILE* fp|获取成语函数
int Checkuser(char user, char psw)|判断用户输入是否正确函数
void TimeCount()|计时函数
void PlayGame(IDIOM idiom)|成语游戏函数
void SearchIdiom(IDIOM i)|查找成语函数
void ReadIdiom(IDIOMi,FILEfp)|输出成语及释义函数
- 代码截图
2.2 函数实现文件介绍
文件1:main.c
- 功能:用于输出登录界面菜单以及调用选择函数,然后选择退出后输出退出界面
- 设计思路:一开始是打算用login函数调用Listmenu函数,再用Listmenu函数调用GetChoice函数的,这样main函数就能更短了,不过这样子在后续会遇到我不好解决的问题,于是把GetChoice函数放到了main函数里,这样方面后续函数调用
文件2:login.c
-
功能:用来调用各种登录页面菜单选项函数什么的文件
-
设计思路:先调用Login函数,并设计了登录时超过三次输入错误就在5min后重试的倒计时,然后输入对了就进入菜单页面进行选择,通过选择函数再进入相应的函数调用
-
Login函数
- Listmenu函数&GetChoice函数
文件3:Checkuser.c
-
功能:用于判断输入用户以及密码是否正确,以及一个倒计时函数
-
设计思路:结合了课堂派的互动写的判断函数,想要有个倒计时功能于是就搜索了倒计时函数
-
Checkuser函数
-
TimeCount函数
文件4:GetIdiom.c
- 功能:获取,查找,输出成语的函数集合
- 设计思路:一开始是获取函数和输出是整合成一个函数的,但是这样子其他函数想要调用获取成语函数的话就会很麻烦,所以还是分装了,查找的话就是字符串对比如果对的话就输出释义
- GetIdiom函数
- ReadIdiom函数
- SearchIdiom函数
文件5:PlayGame.c
- 功能:成语挖空填写
- 设计思路:运用随机函数随机产生挖空的几种不同方式,然后输入成语,对比我输入的成语和系统中的是否一致,答对则是绿色,答错则是红色
2.2 运行结果
1.登录界面
- 登录成功:
- 登录失败:
2.游戏界面
-
回答正确:
-
回答错误:
2.3大作业总结
1.碰到问题及解决办法
- 首先是清屏函数,运用清屏函数的话我在清屏函数之前想要输出的东西会一闪而过根本看不清是啥就没了,然后我发现可以用
system("pause")
来让它停一下再清屏 - 然后是要调用只有成语的部分,成语游戏和查找成语释义都要用到,可是我一开始都是不行,调试出来全都是error,然后我用逐语句看了看,那些原本应该是成语 的字符全都是烫 😦
后来就像上文所说的我把获取函数分装了出来,再在每个函数里调用,这样就可以有正常的成语辽 - 还有是菜单界面的问题,虽然现在也还是有不够好的地方,但是调整之前吧,界面看着很花里胡哨,然后我就各种函数调用和清屏函数,修改了好几次才勉强能过过眼 害
- 输出成语以及释义的函数,其实我一开始是想调用获取成语函数然后再输出的,但是这样我要不然就是只能输出第一个峥嵘岁月的释义要不然就是输出不出来,我也想不出来要咋整,我就把获取函数复制了一遍然后在里面添加了一句输出语句 ·_·
2.小结
- 这次大作业说真的一开始毫无头绪,甚至都不知道文件要怎么打开,然后就是慢慢摸索吧,也找到了那么一点感觉
- 对于清屏函数和pause函数的调用熟练了很多!
- 比起上次大作业来说更多利用了函数嵌套调用吧,感觉有比之前写大作业的时候思路好一点耶
- 我觉得变色函数和倒计时函数也挺好玩滴
- 其实对于指针的运用还是不太熟练,还是要多练习