过去我们已经学习过C语言的一些数据类型,如基本数据类型和创建这些类型的数组。那么这些数据类型是否都能解决所有实际问题呢?请看以下的例子:
例1:试编写一个学生成绩管理系统,包括每个学生的姓名,学号,性别,成绩等信息。如下表:
姓名 | 学号 | 性别 | 成绩 |
张三 | 202001 | M | 85 |
李四 | 202002 | F | 90 |
如何解决这个问题?根据我们过去学习过的数据类型,我们会联想到数组来存储表中的每个信息。而数组的特点是,数组中的每个元素数据类型要相同。我们横看发现数据类型明显不同,竖看呢?我们发现好像可以定义一个二维数组。比如我们就看学号这一列吧,也就是第二列,char型的二维数组确实可以存储张三和李四的学号。如char[2][10],表示一个二行十列的二维数组。类似地,字符型二维数组也可以存储第一列的姓名。一维字符数组可以存储性别列,一维int型数组可以存储成绩列。代码归纳如下:
char ID[2][10]; //用数组ID存储所有学生学号
char Name[2][10]; //用数组Name存储所有学生姓名
char sex[2]; //用数组sex存储所有学生性别
float score[2]; //用数组score存储所有学生成绩
用ID[i], Name[i],sex[i],score[i]分别存储第i个学生的学生号,姓名,性别,成绩。
char ID[2][10] = {"202001","202002"};
char Name[2][10] = {"张三","李四"};
char sex[2] = {'M', 'F'};
float score[2] = {85,90};
试问,这样麻烦吗?上述定义方法的缺点是什么?有没有什么更简单的存储方法呢?
缺点:【1】内存分配不集中,局部数据的关联性不强,寻址效率低。【2】对数组赋值易发生错位;【3】逻辑上最紧密相关的数据(如同一个学生的几个信息),存储位置不相邻,结构零散,不易管理。
思考有没有什么可以改进的方法呢?
如果说我们能够把每个学生的信息集中在一起,也就相当于把一个学生的各个属性(学号,姓名,性别,成绩)打包在一起,作为一个包裹。如果我们要存取张三的学号,就找到属于张三的包裹,打开然后找到里面的学号物件,就可以对其进行操作了。这是一种思想,如果能这样,解决例1这样的问题就会得心应手。C语言中的确提供了一种数据类型,可以方便地解决此类问题。这种类型叫做结构。
定义:结构是同一名字下一组相关变量的集合。形象地比喻成一件包裹,里面有很多物件。
特点:这组相关变量可以是不同数据类型的变量。而数组是只包含相同数据类型的元素,也就是说打包的物件必须是同一类物件(例如都是衣服),形成一个包裹。结构类型可以将不同的物件一起打包(衣服,裤子,帽子),形成一个包裹。例如可以用一个结构变量存储某个学生的学号,姓名,性别,成绩等信息。这一点是数组做不到的。
知道了,结构的概念,我们如何定义结构类型和结构变量呢?
我们说结构就像一个包裹,由不同类型的物件组成。这些不同的物件就相当于int,char,数组等基本数据类型。总之,结构属于派生数据类型,是用其它数据类型的对象来构建的。下面是一个简单的结构类型定义的例子:
struct person //person为结构标识符,struct为关键字,它引出一个结构类型定义
{
char name[16];
int age;
};
struct是结构的关键字,这个例子声明了一个结构person。即person是一个结构。结构内部的变量名称name和age称为结构成员,它们位于结构标识符person后的花括号内。也就是说结构标识符就相当于一个包裹,结构内部定义的变量相当于包裹中的物件。
总结:结构类型定义的标准格式如下:
struct 结构标识符
{
数据类型 结构成员1的名字
数据类型 结构成员2的名字
......
数据类型 结构成员n的名字
};//一定不能忘记此分号
对于例1,定义结构类型如下:
struct student
{
char ID[10];
char Name[10];
char sex;
float score;
};
注意:上述只是结构模板,结构模板只是声明了一种数据类型,定义了数据的组织形式,并未声明结构类型的变量,因而编译器不为其分配内存,就像编译器不会为int分配内存一样。
有了结构模板,还不够,因为就好比我们已经把包裹打包好了,还不行,因为我们在收包裹的时候,上面得有信息,这个包裹是属于谁的?也就是得有物主信息。而结构类型中的结构变量就好比是物主了。
结构变量的定义:
【1】先声明结构类型,再定义结构变量。例如,利用前面已经声明的结构类型struct student,定义一个该类型的变量stu: struct student stu;
【2】在声明结构的同时定义结构变量。(不常用)
struct student
{
char ID[10];
char Name[10];
char sex;
float score;
}stu;
定义好结构变量后,系统为其分配的内存空间是多大?理论上,结构变量所占的内存空间应等于每个成员类型所占内存字节数之和,但实际情况不是这样。系统为结构变量分配内存的大小,并非所有成员所占内存字节数总和,它不仅与所定义的结构类型有关,还与计算机系统本身有关。所以通常使用sizeof运算符计算结构变量实际所占用的内存量。