1.本章学习总结

1.1 学习内容总结

1.结构的介绍


结构(Structure)类型是一种允许程序员把一些数据分量聚合成一个整体的数据类型,一个结构中包含的每个数据分量都有名字。这些数据分量称为结构成员或者结构分量,结构成员可以是C语言中的任意变量类型,程序员可以使用结构类型来创建适合于问题的数据聚合。
像数组和指针一样,结构也是一种构造数据类型(或叫派生数据类型),它与数组的区别在于:数组中所有元素的数据类型必须是相同的,而结构中各成员的数据类型可以不同。


2.结构是C语言中一种新的构造数据类型,它能够把有内在联系的不同类型的数据汇聚成一个整体,使它们相互关联;同时,结构又是一个变量的集合, 可以按照对基本数据类型的操作方达单独使用其成员变量。

3.在C语言中,整型、实型等基本数据类型是被系统预先定义好了的,程序员可以用其直接定义变量。而结构类型是由用户根据需要,按规定的格式自行定义的数据类型。

4.结构类型定义的一般形式为:


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


5.struct是定义结构类型的关量字,在struct之后,自行命名一个结构名,它必须是一个合法的C标识符。struct与结构名两者合起来共同组成结构类型名,大括号内的内容是结构所包括的结构成员,也叫结构分量。结构成员可以有多个,这样,大括号中定义的成员信息被聚合为一个整体并形成了一个新的数据类型。

6.关键字struct和它后面的结构名一起组成一个新的数据类型名。结构的定义以分号结束,这是因为C语言中把结构的定义看做一条语句。

7.结构变量可以通过结构成员操作符“.”对某个成员进行引用。

8.如果两个结构变量的类型相同,可以直接赋值,将一个结构变量的所有成员值都赋给另一个。

9.结构的嵌套定义

  • 一个结构的成员是由合法的C语言数据类型和变量名组成的,进一步地说,在定义结构成员时所用的数据类型也可以是结构类型,这样就形成了结构类型的嵌套。
  • 结构类型的嵌套定义使成员数据被进一步细分,有利于对数据的深入分析与处理。
  • 在定义嵌套的结构类型时,必须先定义成员的结构类型,再定义主结构类型。

10.结构体变量的定义


<1>单独定义
单独定义是指先定义一个结构类型,再定义这种结构类型的变量。
一般形式为:
struct 结构名 {
   类型名 结构成员名1;
   类型名 结构成员名2;
   …
   类型名 结构成员名n;
};
struct 结构名 结构变量名表;

<2>混合定义
混合定义是指在定义结构类型的同时定义结构变量。
一般形式为:
struct 结构名 {
   类型名 结构成员名1;
   类型名 结构成员名2;
   …
   类型名 结构成员名n;
} 结构变量名表;

<3>无类型名定义
无类型名定义是指在定义结构变量时省略结构名,定义结构类型并且同时定义结构变量。
一般形式为:
struct {
   类型名 结构成员名1;
   类型名 结构成员名2;
   …
   类型名 结构成员名n;
} 结构变量名表;

ps:第3种定义形式省略了结构名。要注意的是,由于没有给出结构名,在此定义语句后面无法再定义这个类型的其他结构变量,除非把定义过程再写一遍。


11.结构变量的初始化:

  • 结构变量可以初始化,即在定义时对其赋初值。
  • 结构变量的初始化采用初始化表的方法,大括号内各数据项间用逗号隔开,将大括号内的数据项按顺序对应地赋给结构变量内各个成员,且要求数据类型一致。

12.C语言规定,结构类型变量的存储布局按其类型定义中成员的先后顺序排列。

13.通常,一个结构类型变量所占的内存空间是其各个成员所占内存空间之和,可以用sizeof计算其所需存储空间,如sizeof( struct student)或者sizeof(s1),sizeof的运算对象可以是结构类型名,也可以是结构变量名,计算结果以字节为单位。

14.结构变量的使用


1.结构变量成员的引用
使用结构变量主要就是对其成员进行操作。在C语言中,使用结构成员操作符“.”来引用结构成员,格式为:
结构变量名. 结构成员名
在C语言中,对结构变量成员的使用方法与同类型的变量完全相同。
对嵌套结构成员的引用方法和一般成员的引用方法类似,也是采用结构成员操作符“.”进行的。
此外,由于结构成员运算符的优先级属最高级别,所以一般情况下都是优先执行,即和一般运算符混合运算时,结构成员运算符优先。

2.结构变量的整体赋值
如果两个结构变量具有相同的类型,则允许将一个结构变量的值直接赋给另一个结构变量。赋值时,将赋值符号右边结构变量的每一个成员的值都赋给了左边结构变量中相应的成员。这是结构中唯一的整体操作方式。
只有相同结构类型的变量之间才可以直接赋值。

3.结构变量作为函数参数
在一个由多个函数组成的C语言程序中,如果程序中含有结构类型的数据,就有可能需要用结构变量作为函数的参数或返回值,以便在函数间传递数据。
结构变量作为函数参数的特点是,可以传递多个数据且参数形式较简单。但是,对于成员较多的大型结构,参数传递时所进行的结构数据复制使得效率较低。


15.一个结构变量只能表示一个实体的信息(比如,变量s1只能表示一个学生信息),如果有许多相同类型的实体,就需要使用结构数组。

16.结构数组


结构数组是结构与数组的结合体,与普通数组的不同之处在于每个数组元素都是一个结构类型的数据,包括多个成员项。

结构数组的定义方法与结构变量类似,例如:
struct student students[50];
定义了一个结构数组 students,它有50个数组元素,从 students[0]到 students [49],每个数组元素都是结构类型 struct student,这样就可以存储50个学生的信息。

在定义结构数组时,也可以同时对其进行初始化,其格式与二维数组的初始化类似。

在C语言中,编译程序为所有结构数组元素分配足够的存储单元,结构数组的元素是连续存放的。

由于每个结构数组元素的类型都是结构类型,其使用方法就和相同类型的结构变量一样。

对结构数组元素成员的引用是通过使用数组下标与结构成员操作符“.”相合的方式来实现的,其一般格式为:
结构数组名 [下标]. 结构成员名

由于结构数组中的所有元素都属于相同的结构类型,因此,数组元素之间可以直接赋值。


17.指针可以指向任何一种类型的变量,而结构变量也是C语言中的一种合法变量,因此,指针也可以指向结构变量,这就是结构指针。结构指针就是指向结构类型变量的指针。

18.结构类型的数据往往由多个成员组成,结构指针的值实际上是结构变量的首地址,即第一个成员的地址。

19.有了结构指针的定义,既可以通过结构变量直接访问结构成员,也可以通过结构指针变量间接访问它所指向的结构变量中的各个成员。具体有两种形式:


(1)用*p访问结构成员
如:(*p).num=101;
其中*p表示的是指向的结构变量。注意,(*p)中的括号是不可少的,因为成员运算符“.”的优先级高于“*“的优先级,若没有括号,则*p.num等价于*(p.num),含义发生了变化,从而会产生错误。

(2)用指向运算符->访问指针指向的结构成员
如:p->num=101;


20.当p指向结构变量s1时,下面3条语句的效果是一样的:


s1.num=101;
(*p).num=101;
p->num=101;


21结构变量也可以作为函数参数,在参数传递时,把实参结构中的每一个成员值传递给形参结构的成员。但是,当结构成员数量众多时,在参数传递过程中就需要消耗很多空间。而使用结构指针作为函数参数只要传递一个地址值,因此,能够极大地提高参数传递的效率。

22.文件的作用


(1)许多程序在实现过程中,依赖于把数据保存到变量中,而变量是通过内存单元存储数据的,数据的处理完全由程序控制。当一个程序运行完成或终止运行,所有变量的值不再保存。另外,一般的程序都会有数据输入与输出,如果输入输出数据量不大,通过键盘和显示器即可解决。当输入输出数据量较大时,就会受到限制,带来不便。

(2)文件是解决上述问题的有效办法,它通过把数据存储在磁盘文件中,得以长久保存。当有大量数据输入时,可通过编辑工具事先建立输入数据的文件,程序运行时将不再从键盘输入,而从指定的文件上读入,从而实现数据一次输入多次使用。同样量数据输出时,可以将其输出到指定文件,不受屏幕大小限制,并且任何时候可以查看结果文件。一个程序的运算结果还可以作为其他程序的输入,进行进一步加工。


23.文件的概念


(1)文件系统功能是操作系统的重要功能和组成部分。每个文件都有文件名,并且有自己的属性。文件可以通过应用程序创建,如运行“记事本”程序,输入一些数据,输入文件名,就会在磁盘中产生一个文本文件。

(2)在操作系统中,文件是指驻留在外部介质(如磁盘等)中的一个有序数据集,可以是源文件、目标程序文件、可执行程序,也可以是待输入的原始数据,或是一组输出的结果。

(3)源文件、目标文件和可执行程序可称为程序文件,输入输出数据可称为数据文件。数据文件还可分为各种类型,如文本文件、图像文件、声音文件等。

(4)使用应用程序时,通常保存功能实现把数据从内存写入到文件,这就是所谓的“存盘”。打开功能实现把磁盘文件的内容读入到内存。

(5)C语言处理的文件与 Windows XP等操作系统的文件概念相同,但C语言中的文件类似于数组、结构等,是一种数据组织方式,是C语言程序处理的对象。

(6)编辑文件时,输入的数据先是在内存中,保存后,数据才被写入到磁盘中。


24.文件的特点:数据永久保存,数据长度不定,数据按顺序存取。

25.文本文件和二进制文件


(1)在C语言中,按数据存储的编码形式,数据文件可分为文本文件和二进制文件两种。

(2)文本文件是以字符ASCII码值进行存储与编码的文件, 其文件的内容就是字符。二进制文件是存储二进制数据的文件。

(3)从文件的逻辑结构上看,C语言把文件看作数据流,并将数据按顺序以一维方式组织存储,这正好与数据文件的动态存取和操作顺序一致。根据数据存储的形式,文件的数据流又分为字符流和二进制流,前者称为文本文件(或字符文件),后者称为二进制文件。

(4)C语言源程序是文本文件,其内容完全由ASCII码构成,通过”记事本”等编辑工具可以对文件内容进行查看、修改等。

(5)C程序的目标文件和可执行文件是二进制文件,它包含的是计算机才能识机器代码,如果也用编辑工具打开,会看到稀奇古怪的符号,即通常所说的乱码。

(6)对于具体的数据选择哪一类文件进行存储,应该由需要解决的问题来决定,并在程序的一开始就定义好。


26.缓冲文件系统


应用程序进行文件数据的访问:
由于系统对磁盘文件数据的存取速度与内存数据存取访问的速度不同,面且文件数量较大,数据从磁盘读到内存或从内存写到磁盘文件不可能瞬间完成,所以为了提高数据存取访问的效率,C程序对文件的处理采用缓冲文件系统的方式进行,这种方式要求程序与文件之间有一个内存缓冲区,程序与文件的数据交换通过对该缓冲区来进行。


27.fopen()、fscanf()、fclose()是文件操作的函数,在stdio.h中定义。

28.共用体

  • 共同体和结构体类似,也是一种构造类型的数据结构。
  • 在进行某些算法得时候,需要使几种不同类型的变量存到同一段内存单元中,几个变量间相互重叠,这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作"共用体"类型结构,共用体所有成员占有同一段地址空间。
  • 共用体的大小是其占内存长度最大的成员的大小。
  • 一般定义形式

  union 共用体名
  { 
       成员声明
       成员声明  
       ...
    } 变量表列;


29.枚举类型

  • 枚举是指将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。枚举类型也是构造类型。
  • 一般定义方法

enum 枚举名 { 枚举值1, 枚举值2, ...} 变量列表


  • 在定义枚举类型的时候枚举元素可以用等号给它赋值,用来代表它的数值,在程序中,不能再次对枚举元素赋值,因为枚举元素是常量。
  • 定义一个变量是枚举类型,可以先定义一个枚举类型名,然后再说明这个变量是该枚举类型。

例如: 
enum weekday{sun,mon,tue,wed,thu,fri,sat}; 
定义了一个枚举类型名 enum weekday,然后定义变量为该枚举类型。
例如: 
enum weekday day; 
当然,也可以直接定义枚举类型变量。
例如: 
enum weekday{sun,mon,tue,wed,thu,fri,sat} day; 
其中,sum,mon,…,sat 等称为枚举元素或枚举常量,它们是用户定义的标识符。


30.文件读写and将文件中数据读进结构体数组

①打开文件


使用fopen可以创建文件,还可以用来打开已经存在的文件、向文件中追加数据或者覆盖已经存在的文件中的数据,具体是哪种取决于文件的打开方式。


文件打开方式
使用方式 含义
"r" 打开一个文本文件只读
"w" 打开一个文本文件只写
"a" 对一个文本文件添加
"rb" 打开一个二进制文件只读
"wb" 打开一个二进制文件只写
"ab" 对一个二进制文件添加
"r+" 打开一个文本文件读/写
"w+" 生成一个文本文件读/写
"a+" 打开一个文本文件读/写
"rb+" 打开二进制文件读/写
"wb+" 生成二进制文件读/写
"ab+" 打开二进制文件读/写

②关闭文件


文件一旦使用完毕,应用关闭文件函数把文件关闭,以避免文件的数据丢失等错误。

关闭文件通过调用fclose()函数,其一般形式是:    
fclose(文件指针);

正常完成关闭文件操作时,fclose()函数返回值为0。如返回非零值则表示有错误发生。


③将文件中数据读进结构体数组


(1)字符读写函数:fgetc和fputc 
(2)字符串读写函数:fgets和fputs 
(3)数据块读写函数:fread和fwrite 
(4)格式化读写函数:fscanf和fprintf 
ps:使用以上函数都要求包含头文件stdio.h


1.2 本章学习体会

1.2.1 学习体会

  • 这一段时间电脑总是坏[・`Д´・ ],生气啊,导致这段时间代码写得比较少,比较匆匆忙忙的。
  • 这次PTA中把上次上机考试的题目放了进去,考试时考得很差,结构后来翻回去一写,也不止当时的分数啊,ε=(´ο`*)))唉,努力学习吧,不过还是有的题不太理解,望老师能在超星平台上多发布些讲解视频。
  • 嵌套的题比较少,一些地方也不知道为什么,运算过程有时候也写不对,(╯‵□′)╯︵┻━┻,返回return不清楚为什么只返回刚开始输入的参数
  • 学习了结构之后,发现结构是一个比较好用的东西,(`∀´)ノ亻!可以在里面定义不同类型的变量,引用时也很方便,还可以用typedef来重新换个简单的名字。
  • 学习文件中,我真的认认真真,仔仔细细地把书看了好几遍,但是有些代码还是读不懂o(╥﹏╥)o,好郁闷,不过,文件的好处在我看来就是使得代码更条理清晰,就是关于文件的函数有点多,不太好区别。
  • 最后想要说的就是这次的大作业,好难(# ̄…… ̄#)…………具体困难看下面吧......

1.2.2 代码累计

我的代码量(不包括重复)

代码量(行)
4 241
5 506
6 771
7 842
8 793
9 724
10 1980
11 983
12 879
13 545
14 479
15 539
16 721
累计 11224

2.综合作业--“我爱成语”

2.0题目介绍


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


主要功能:

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

要求:

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

数据说明:

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

扩展功能:

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

2.1文件介绍

2.1.1头文件介绍

idiom.h

  • 结构体
    • 结构体IDIOM:用于存储成语本身及其释义
  • 函数
    • 函数ListMenu:主菜单
    • 函数GetChoice:用户作出选择
    • 函数GetIdiomData:查看成语及释义
    • 函数GetIdiomVocabulary:查看成语
    • 函数FillBlanks:成语填字
    • 函数IdiomSolitaire:成语接龙

users.h

  • 结构体
    • 结构体USER:用户登录名称及密码
  • 函数
    • 函数Landing:用户输入账号及密码
    • 函数Checking:检测账号及密码是否匹配


2.1.2函数实现文件介绍

文件1:Main.cpp

  • 调用目录列表函数ListMenu()和用户做选择函数GetChoice()

文件2:ListMenu.cpp

  • 定义ListMenu函数输出菜单,并且调用用户登录界面,以及用户做出选择
    • ListMenu()函数是主菜单
    • 调用Landing()函数引入账号和密码的代码

文件3:GetChoice.cpp

  • 用户做出选择并且调用相应的函数
    • GetChoice()函数输入选择


文件4:Function.cpp

  • 用户选择后相应的函数进行相应的功能
    • GetIdiomData()函数用来输出文件中的内容,也就是查看成语及释义
    • GetIdiomVocabulary()函数是只输出‘:’前面的成语
    • InPut()函数可以实现在文件中添加成语及其释义



文件5:FillBlanks.cpp

  • 成语填字游戏的程序
    • FillBlanks()函数用来进行填字游戏



2.2运行结果

2.2.1登录界面


2.2.2游戏界面


ps:还有一些问题

2.2.3排名界面


ps:还有一些问题

2.3大作业总结

2.3.1碰到问题及解决办法

  • 在分装成语和释义时,刚开始运用老师上课的办法,会出现乱码,后来老师重新发了一个分装的代码,比较好理解。
  • 在成语填字游戏中不知道如何去挖空,然后通过同学的指导知道了可以在输出字符串时用‘_’来代替输出
  • 新增成语时增加的总会把第一个成语代替掉,还没有找到解决办法
  • 排名中不知道怎么弄出所用时间

2.3.2小结

  • 在这次的大作业中,我学会了很多,尤其是关于结构体方面的知识,通过几位同学代表的演示,我清晰地认识到了自己与他人的差距很大,我现在在老师的基础作业上还有问题的时候,他们已经学会拓展创新,由此,我更需要赶紧向前。
posted on 2019-12-15 16:39    阅读(2605)  评论(0编辑  收藏  举报

/*
*/