c博客06-2019-结构体&文件

1.本章学习总结

1.1 学习内容总结

1、结构体
·结构的概念
结构是C语言中一种新的构造数据类型,它能够把有内在联系的不同类型的数据汇聚成一个整体,使之互相关联。它是一个变量的集合。
·结构的定义
一般形式为:

struct 结构体
{
类型名 结构成员名1
类型名 结构成员名2
···
类型名 结构成员名n
};

·关键字struct+后面的结构名-->数据类型名
·大括号内的内容是结构所包括的结构成员
注:结构定义结束要以分号结束
而为了方便,我们一般利用typedef给结构体重新命名,例如:

struct student
{
int x;
int y;
}STU;

·结构的嵌套定义
即在一个较大的实体中可能由多个成员构成,而这些成员中有些又有可能由一些更小的成员构成。而在这时候就需要结构的嵌套定义。
例如:

struct address
{
char city[10];
char street[20];
int code;
int zip;
};
struct substudent
{
int num;
char name[10];
struct address addr;
int computer,english,math;
double average;
};

结构类型struct substudent的成员变量addr被定义为结构类型struct address,而其中它又包含了4个成员。
·结构变量的定义
我们需要定义结构变量来操作和访问结构的数据,只有定义了相应的结构变量后才为其分配储存单元
定义结构变量有几种方式:
①单独定义
先定义一个结构变量,再定义这种结构类型的变量
形如:

struct student
{
int num;
char name[10];
};
struct student s1,max;
定义了结构变量s1,max

②混合定义
在定义结构类型的同时定义结构变量
一般形式:

struct 结构名
{
类型名 结构成员1;
类型名 结构成员2;
···
类型名 结构成员n;
}结构变量名表;

·结构变量的初始化
在定义时对其赋值,例如:

struct student s1={101,"zhang",78,87,85};

采用初始化表的方法,大括号内各数据项间用逗号隔开,将大括号内的数据项按顺序对应赋给结构变量的各个成员,且要求数据类型一致。
通常,一个结构类型变量所占的内存空间是其各个成员所占内存空间之和
利用sizeof(),运算对象可以是结构类型名,也可以是结构变量名,结构以字节为单位。
·结构变量的使用
①结构变量成员的引用
引用格式一般为:

结构变量名.结构成员名

例如:

struct student s1;
s1.addr.zip=300010

每个成员按从左到右,从外到内的方式引用。
注:结构成员运算符和一般运算符混合运算时,结构成员运算符优先
②结构变量的整体赋值

s1=s2
与
s2.num=s1.num;
strcpy(s2.name,s1.name);
s2.math=s1.math;
等效

注:只有相同结构类型的变量之间才可以直接赋值。
③结构变量作为函数参数
结构变量作为函数参数的特点是,可以传递多个数据且参数形式较简单。
·结构数组

结构数组是结构与数组的结合体
例如:

struct student students[50]
定义了结构数组student,具有50个数组元素
这样可以储存50个学生信息

②初始化
例如:

struct student students[50]=
{{101,"zhang",76,78,79},{102,"lin",77,79,80}};

结构数组的元素是连续存放的,编译程序为所有结构数组元素分配。
③结构变量引用
一般格式为:

结构数组名[下标].结构成员名

④赋值
假设为第i个学生,赋值可为:

students[i].num=101;
strcpy(students[i].name,"zhang");

数组元素之间可以直接赋值,如

students[i]=students[k];

·结构指针

结构指针就是指向结构类型变量的指针

struct student s1={101,"zhang",78,79,76},*p
这条语句定义了struct student类型的变量s1并初始化
还定义了一个结构指针变量p
p=&s1
是结构指针p指向结构变量s1

结构类型的数据往往由多个成员组成
结构指针的值实际上是结构变量的首地址,即第一个成员的地址。
②指向
可以通过结构变量直接访问结构成员
也可以通过指针变量p间接访问它所指向的结构变量的各个成员
其间接访问有两种方式:
1、*p访问成员

(*p).num=101

注:p)的括号是必不可少的 ,“.”的优先级高于“”,即p.num=(p.num)
2、指向运算符->访问指针指向的结构成员

s1.num=101
(*p).num=101;
p->num=101;
这三条语句的效果是一样的

③作为函数参数
结构指针只是作为函数参数只要传递一个地址值,能够极大的提高参数传递的效率。
2、文件
·文件的概念
文件系统功能是操作系统的重要功能和组成部分
文件类似于数组、结构,是一种数据组织方式,是C语言程序处理的对象。
·文本文件和二进制文件

文件 储存方式 储存内容
文本文件 ASCII码 字符
二进制文件 二进制 二进制数据

C语言源程序是文本文件,其内容完全由ASCII码构成。
·缓冲文件系统
由于系统对磁盘文件数据的存取速度与内存数据存取访问的速度不同,所以,磁盘数据先放入内存缓冲区
大致为
数据->文件:
数据->缓冲区->磁盘文件
文件中读数据:
文件->缓冲区->内存数据
使用缓冲文件系统可以大大提高文件操作的速度。
磁盘数据的组织方式按扇区进行,每个扇区512B,缓冲区大小也为512B
缓冲区的大小与磁盘的一个扇区大小相同,从而保证了磁盘操作的高效率
·文件结构与文件类型指针
①文件结构

FILE *fp
定义了一个FILE结构指针

FILE类型是用typedef命名的,在头文件stdio.h中定义,所以使用文件都需要用到<stdio.h>头文件。
②文件类型指针

FILE *fp
FILE是文件类型定义符
fp是文件类型的指针变量

文件指针是特殊指针,指向的是文件类型结构
注:fp++意味着指向下一个FILE结构。
·文件处理步骤
①定义文件指针
②打开文件
③文件处理
④关闭文件
·打开文件和关闭文件
①打开文件
由函数fopen()实现,调用形式为:

fopen("文件名","文件打开方式");

(1)该函数具有返回值
(2)包括两个参数 文件的绝对完整路径中定位子目录的“\”需要用“\”替代
“\”在C语言中表示为转义符。
(3)文件打开的实质是把磁盘文件与文件缓冲区对应起来
(4)一旦文件经fopen()函数被打开,对该文件的操作方式就被确定了,直至关闭。
(5)C语言中允许同事打开多个文件,但不允许同一个文件在关闭前被再次打开。
②关闭文件
有函数fclose()实现,调用形式为:

fclose(文件指针)
若返回0为正常关闭,否则无法正常关闭

·文件读写

方式 函数 函数
字符 fgetc(fp) fputc(ch,fp)
字符串 fputs(s,fp) fgets(s,n,fp)
格式化 fscanf(文件指针,格式字符串,输入表) fprintf(文件指针,格式字符串,输出表)
数据块 fread(buffer,size,count,fp) fwrite(buffer,size,count,fp)

其他相关函数:

函数 调用形式 作用
rewind() rewind(FILE *fp) 定位文件读写位置指针,使其指向读写文件的首地址
fseek() fseek(fp,offset,from) 将文件位置指针移动到离文件offset个字节
ftell() ftell(文件指针) 用来获取当前文件读写位置指针的位置
feof() feof(fp) 判断fp指针是否已经到文件末尾
ferror() ferror(文件指针) 检查文件在用各种输入输出函数进行读写时时都出错
clearerr() clearerr(文件指针) 清除出错标志和文件结束标志

1.2 本章学习体会

学习体会:
感觉这学期也要过去了,但是我并没有成为我想要的样子。看一眼开学时写的第一篇博客,确实信誓旦旦。这门课,怎么说,确实有难度。但是多动脑的话我觉得会更好吧。但我也觉得大作业也是一件很好的事情,我从刚开始很害怕很抗拒,到现在很坦然接受并且乐意接受,真的确确实实能学到很多东西!代码量也在慢慢的增多,看满满的代码也是成就感up。
代码量
大作业代码:363
Pta题集:216
2#.综合作业--“我爱成语”

2.1.文件介绍

1.头文件介绍

idiom.h:

类型 作用
结构体IDIOM 用于储存成语名称和成语意思
结构体USERS 用于存储用户名称和密码
void型函数 用于用户登陆系统
int型函数 用于检查用户登陆账号信息是否正确
int型函数 用于检查用户注册的账号是否已经存在
int型函数 用于得到用户的选择并输出菜单
void型函数 输出文档中所包含的成语
void型函数 对用户输入的成语进行查询输出其释义
结构指针型函数 对文本中内容进行整理,将成语名称和释义分开
void型函数 让用户进行选择并进入相应界面
void型函数 进行成语游戏
int型函数 用于生成随机成语
头文件idiom.h代码截图:

2.函数实现文件介绍。

文件一:main.cpp
main()代码截图:

首先我把界面背景颜色和字体颜色给改了,嘻嘻..感觉搞一搞这些小花样就很开心很满足怎么说呢,我第一次把main()写得这么...简练..因为我很多函数都是之间进行调用。我的代码中主要也就是两大块,一块是登陆,一块是进行选择。
文件二:login.cpp
主要是用于用户登陆及注册,若用户输入密码错误,会有5次的输入机会,否则将退出。
包含的函数有:

①CheckMessage():

②CheckMessage2():

③loginsystem():


主要运行是在loginsystem函数中,再利用if语句去跳转到checkmessage()函数中,因为两个check函数都是int类型之后会返回数据,我设置的是返回1则说明信息匹配相同。再利用if-else语句去进行一些输出信息之类的。
文件三:Getchoice()
主要是用于用户选择和输出菜单,以及通过选择进入不同的界面
包含的函数有:

①Choose():

②Getchoice():


主要运行的函数是Choose(),在这个函数中定义了一个choice,choice从Getchoice()函数中获取数值,再利用switch语句从而根据不同的选择去进入到不同的界面。再来说说Getchoice()这个函数,首先它会输出菜单,然后我设置了一个while语句让用户有5次输入的机会。
文件三:idiomList()
主要是用于输出文本内容中所含有的成语让用户进行了解。
包含的函数有:

idiomList()


其实主要输出语句就为

输出文件中包含的成语后,需要返回文件的开头,再进行输出菜单让用户进行选择。这边利用了一个goto语句,让用户在选择继续了解的时候返回到起始while循环中继续输出文件中内容。
文件四:InquirIdiom()
主要功能使用让用户进行成语释义查询
包含的函数有:

InquirIdiom()

SortIdiom()


该功能的主要运行函数是InquirIdiom(),首先,利用了SortIdiom()函数对成语进行分装,将:改为\0从而把成语名称与成语释义分开,之后返回ptr。利用循环将用户输入的成语名称和ptr[i].idiomName进行比较,若相同则输出ptr[i].idiomMean。接下来,用户将再次进行选择。
文件五:IdiomGame()
主要功能是要进行成语游戏
包含的函数有:

IdiomGame()

RandomIdiom()


其实这里的主要函数是RandomIdiom()。IdiomGame()主要功能是输出菜单和让用户再次进行选择。RandomIdiom()这里也需要分装文件里边的成语内容,所以再次利用了SortIdiom()进行分装。然后取随机数i,获得其中一个成语,通过挖空输出成语题目并在后面输出成语释义以提示用户输出。并将成语名称与用户输入的名称进行比较,相同则提示正确。之后返回正确的题数到IdiomGame()中,去计算用户得到的分数。

2.2.运行结果

1.登录界面

这是我的登陆界面:

这是我的注册界面:

注册成功后就直接进入菜单无需重新注册

2.了解界面


···(这里省略很多个成语)

按1可再次进行查询

3.查询界面


按2继续查询

4.游戏界面


正确时给出正确提示

在你错误的情况下输出正确的成语

在一轮游戏结束后,给出正确的题数,并再次给出菜单供用户选择。

2.3大作业总结

1.碰到问题及解决办法

①注册账号
我在每次注册完写入时发现,我新填入的账户信息都放在了第一行并且覆盖了原有的信息。后来发现它扫描到文本的第一行,于是就加入fseek使其到最后一行再填入
②重现菜单
就是我新学到的goto语句,我真的觉得这个语句很好用,他能直接调回原来的界面也解决刚开始我在烦恼要写一堆代码来重回界面的问题。
③分装成语
刚开始在SortIdiom()之后并没有返回ptr,就导致他根本就没有变,后来是同学告诉我的也就是他说的他在自己的函数里自己玩

2.小结

这次的大作业有两个功能没有实现,一个是成语接龙一个是排名。但确实从这次大作业中我学到了很多,就很综合的涉及到了之前和新学的知识,也对新学的知识比如文件中fseek()函数等有了一个更好的应用和理解。挺好。

posted @ 2019-12-15 21:29  林浈  阅读(275)  评论(4编辑  收藏  举报