c博客06-2019-结构体&文件
1.本章学习总结(2分)#
1.1 学习内容总结##
- 结构体的定义与赋值
- 单独定义
struct 结构名
{
类型名 结构成员名1;
类型名 结构成员名2;
...
类型名 结构成员名n;
};
struct 结构名 变量名;
- 混合定义
struct 结构名
{
类型名 结构成员名1;
类型名 结构成员名2;
...
类型名 结构成员名n;
}结构变量名表;
- 无类型名定义
struct
{
类型名 结构成员名1;
类型名 结构成员名2;
...
类型名 结构成员名n;
}结构变量名表;
- 用typedef语句定义
typedef struct
{
类型名 结构成员名1;
类型名 结构成员名2;
...
类型名 结构成员名n;
}结构变量名;
- 结构成员的赋值:可以直接赋值,如struct student s1={101,“zhang”,78,87,85};也可以用“.”来赋值,如s1.num=101;还可以结构变量的整体赋值,前提是两个结构变量具有相同的类型,如s2=s1。
- 结构体数组排序做法
- 选择排序法
for(i=0;i<n-1;i++)
{
index=i;//记录下标
for(j=i+1;j<n;j++)
当下标为j大于下标为index时
index=j;
end for
交换下标为index和下标为i的元素
}
end for
- 冒泡排序法
for(i=1;i<n;i++)
{
for(j=0;j<n-i;j++)
{
如果下标为j的元素比下一个元素大
则交换这两个元素
}
end for
}
end for
- 结构体指针的用法
- 结构指针的定义一般为struct 结构名* 变量名;结构指针的值实际上是结构变量的首地址,即第一个成员的地址。如果变量名为p,则可以用p来访问结构成员,如(p).num=101;也可以用->指向运算符来访问指针指向的结构成员,如p->num=101。结构指针作为函数参数,如int update(struct student*p);pos=update(students);形参介绍结构指针,对应的实参是结构数组名students。结构指针作为函数参数只要传递一个地址值,因此能够极大地提高参数传递的效率。
- 共用体、枚举类型做法
- 联合的一般声明为
union 联合名
{
成员声明;
成员声明;
...
}变量列表;
联合中的成员共享同一块内存空间,C语言编译程序保证分配给联合的内存能够容纳其最大的成员变量,以最后一次赋值为值。
- 枚举变量定义和初始化
enum 枚举名{枚举值1,枚举值2,...} 变量列表;每个枚举值都是一个合法的标识符,或者是一个标识符后面跟一个等号,再加上一个常量表达式。编译程序从0开始逐个给枚举值赋值,如果当其中一个枚举值以及确定有值了,则从该枚举值的值往后依次加1。某个枚举变量的值只能是定义时列出的枚举值之一。 - 文件读写,文件数据读取
- 打开文件用函数fopen(),调用形式为fopen(“文件名”,“文件打开方式”);文件的打开方式有“r”:打开文本文件进行只读,“w”:建立新文本文件进行只写,“a”:打开文本文件进行追加,“r+”:打开文本文件进行读写,“w+”:建立新文本文件进行读写,“a+”:打开文本文件进行追加读写,这是文本文件的打开方式,而二进制文件的打开方式在后面加一个b即可。关闭文件用函数fclose(),一般格式为fclose(文件指针);
- 文件读写分为字符方式文件读写函数:fgetc()和fputc();字符串方式文件读写函数:fputs()和fgets();格式化方式文件读写函数:fscanf()和fprintf();数据块方式文件读写函数:fread()和fwrite()。
- 还有其他相关函数,如重定位文件首函数rewind();指针移动控制函数fseek();获取指针当前位置函数ftell();文件末尾检测函数feof();读写错误检查函数ferror();出错标记清除函数clearerr()。
1.2 本章学习体会##
- 通过对文件和结构的学习,发现指针终于派上用场了,指针以及数组起到了很大的作用,同时难度也大大提高了,不是很好懂,多文件写程序的时候,脑子有点混乱,基本上把前面所学的知识全都用上了,综合量比较大,必须知识点要掌握的够,掌握的多,并且还要掌握的牢固。我发现现在随着对C语言的逐渐深入的学习,写程序出错时,特别不好调试,因为函数传参量太多,也不知道错在了哪,基本上断点调试找错基本不可能了,总之学过这两章后,感觉知识量巨大,不是很好消化,甚至消化不了,那只能慢慢的看,慢慢的理解,慢慢的消化了。
- 这两周的代码量大概为664行。
2.综合作业--“我爱成语”(8分)#
2.1.文件介绍##
1.头文件介绍###
idiom.h####
typedef struct
{
char username[20];
char password[20];
}USER;
typedef struct
{
char idiomAndMean[200];
}IDIOM;
- 这两个结构体一个是用户登录的账号和密码,另一个是成语及成语意思。
int LoginMenu();
int checkUserValid(USER* psu);
void UserLogin();
void IdiomConnect();
int GetIdiomData(IDIOM* idiomNum, FILE* fp);
void Choice();
- 依次是用户用于登陆,检查用户登陆的合法性,用户登陆后的选择,成语接龙游戏的实现,查找成语的实现,打开成语文件。
2.函数实现文件介绍###
文件1.idiomMain.cpp####
- 主要就是调用一个用户登录函数。
文件2.Login.cpp####
- 首先LoginMenu()函数是显示出登录页面;在里面再套用一个checkUserValid(USER* psu)函数检查用户名密码合法性,如果正确返回1,错误返回0,然后在根据checkUserValid(USER* psu)的返回值,确定LoginMenu()返回什么到UserLogin(),UserLogin()函数显示出游戏的选择,在里面再分别调用IdiomConnect()函数和Choice()函数用于游戏的实现。
文件3.idiomData.cpp####
- IdiomConnect()函数用于做成语接龙的游戏,在里面定义一个字符二维数组和一个一维字符数组,分别来放"13355个成语无释义.txt"文本文件中的成语和自己输入的成语,然后遍历所有字符二维数组中的元素的首个汉字与自己输入的成语的最后一个汉字做比较,看是否相等。Choice()函数主要来打开"idiom清洗版.txt"文本文件,并且来调用有返回值的GetIdiomData(IDIOM* idiomNum, FILE* fp)函数,直到返回值为0,GetIdiomData()函数中定义两个字符数组,一个用于自己输入的要查找的成语,一个用于文本文件的成语,然后让这两个数组比较,找出成语,输出成语及成语意思,如果要继续查找,则返回到文件首,并返回1到Choice()函数中,继续循环。
2.2.运行结果##
1.登录界面###
2.游戏界面###
2.3大作业总结##
1.碰到问题及解决办法###
Q1:不知道怎么设计对成语填空和用户排名。
A1:想了好长时间,看了看那些有关的库函数,还是不会做,然后就着重于做成语接龙和成语字典了。
Q2:用户登陆时,写好代码后输入文本中的数据,代码不能运行。
A2:发现文本中的用户密码格式不对,然后把文本改了一下,变成统一格式。
Q3:在写IdiomConnect()这个函数时,运行之后退出不了。
A3:数组太大了,超过了某个范围,就在最后加了一个exit(0),使它完成程序的结束。
Q4:在写Choice()和GetIdiomData()这两个函数时,没有找到他们俩的关系,导致只能查找一次成语,并且不能在中途退出。
A4:把GetIdiomData()函数改成了带有返回值的参数,并返回Choice()中做循环的条件,循环里面放GetIdiomData()函数。
Q5:在做GetIdiomData()函数时,运行后无法输入成语。
A5:在操作前面加了一个getchar(),因为上一次输入多输入了一个回车,所以用getchar()来吸收回车。
2.小结###
- 通过这次的大作业和上次的大作业相比,我发现这里面的漏洞少了很多,但还是没能实现成语填空和用户排名以及记录时间的功能,还是有待学习。上次大作业花了半天来写的,效果很差,功能也不好,而这次大作业花了一天来写的,虽然功能做的很少,但没有出现程序会崩溃,起码可以正常运行,上次大作业需要输入特定的东西才能运行。我知道我花的时间还是太少了,相比李悦、林智凯、王炜等人实在是太少了,估计他们都是做了好几天,才做出如此优秀的代码,肯定投入了大量的时间去学习那些课堂上没讲的新知识,我应该向他们学习。第一眼看到这个大作业时,和第一次一样,很懵,但我整理了一下思路,想想第一步要做什么,第二步要做什么,想好了每一步之后,开始慢慢的编写代码。这次的大作业真的是把以前学过的知识以及没学过的知识都运用了一遍,这真的是编程语言的神奇之处,可以用代码来实现各种各样的功能。