有时要传很多数据
C语言可以处理很多不同类型的数据:小数字、大数字、浮
点数、字符与文本。但现实世界中的事物往往需要一条以上
的数据来记录。比如:
/* 打印目录项 */
void catalog(const char *name, const char *species, int teeth, int age)
{
printf("%s is a %s with %i teeth. He is %i\n",
name, species, teeth, age);
}
/* 打印贴在水缸上的标签 */
void label(const char *name, const char *species, int teeth, int age)
{
printf("Name:%s\nSpecies:%s\n%i years old, %i teeth\n",
name, species, teeth, age);
}
int main()
{
catalog("Snappy", "Piranha", 69, 4);
label("Snappy", "Piranha", 69, 4);
return 0;
}
两个不同的函数都传了
相同的4条
数据,显然这种方式是累赘的。怎么才能解决这个问题?
用结构创建结构化数据类型
如果需要把一批数据打包成一样东西,就可以使用结构
(struct)。 struct 是structured data type(结构化数据类型)
的缩写。有了结构,就可以像下面这样把不同类型的数据写
在一起,封装成一个新的大数据类型:
struct fish {
const char *name;
const char *species;
int teeth;
int age;
};
结构与数组有些相似,除了以下两点:
1.结构的大小固定。
2.结构中的数据都有名字。
给结构赋值
和新建数组很像,你只需
要保证每条数据按照它们在结构中定义的顺序出现即可:
struct fish snappy = { "Snappy", "Piranha", 69, 4};
问: fish结构会保存字符串吗?
答: 在这个例子中不会,这里的
fish结构中只保存了字符串指针,也
就是字符串的地址,字符串保存在存
储器中其他位置。
问: 但还是可以把整个字符串保存在结构中吧?
答: 对,只要把字符串定义成字
符数组就行了,像char name[20];。
只要把“鱼”给函数就行了
现在,你只要把新的自定义数据传给函数就行了,而不必传
递一大批零散的数据。
/* 打印目录项 */
void catalog(struct fish f)
{
...
}
/* 打印贴在水缸上的标签 */
void label(struct fish f)
{
...
}
int main(){
struct fish snappy = { "Snappy", "Piranha", 69, 4};
catalog(snappy);
label(snappy);
}
把参数封装在结构中,代码会更稳定。
把数据放在结构中传
递有一个好处,就是
修改结构的内容时,
不必修改使用它的函数。比如
要在fish中多加一个字段:
struct fish {
const char *name;
const char *species;
int teeth;
int age;
- // 新增字段
int favorite_music;
};
catalog()和label()知道有
人会给它们一条fish,但却不
知道fish中现在有了更多的数
据,它们也不关心,只要fish
有它们需要的所有字段就行了。
这就意味着,使用结构,不但
代码更好读,而且能够更好地
应对变化------>早期的面向对象思想体现。
使用“.”运算符读取结构字段
struct fish snappy = { "Snappy", "piranha", 69, 4};
printf("Name = %s\n", snappy.name); // snappy.name这是snappy中的name属性
问: 数组变量就是一个指向数组的指针,那么结构变量是一个指向结构的指针吗?
答: 不是,结构变量是结构本身的名字。
问: 结构就相当于其他语言中的类?
答: 它们很相似,但在结构中添加方法可就没那么
容易了。
存储器中的结构
在定义结构时,你并没有让计算机在存储器中创建任何东西,
只是给了计算机一个模板,告诉它你希望新的数据类型长什
么样子。
struct fish {
const char *name;
const char *species;
int teeth;
int age;
};
当定义新变量时,计算机则需要在存储器中为结构的实例创建
空间,这块空间必须足够大,以装下结构中的所有字段:
struct fish snappy = { "Snappy", "Piranha", 69, 4};
那么当把一个结构变量赋给另一个结构变量时会发生什么?
计算
机会创建一个全新的结构副本,也就是说,计算机需要再分配一
块存储器空间,大小和原来相同,然后把每个字段都复制过去。
struct fish snappy = { "Snappy", "Piranha", 69, 4};
struct fish gnasher = snappy;
切记:为结构变量赋值相当于叫计算机复制数据。
注意:字符串字段复制的是指向字符串的
指针,而非字符串本身。
当把一个结构变量赋给
另一个结构变量,计算
机会复制结构的内容。如果结构中
含有指针,那么复制的仅仅是指针
的值,像这里,gnasher和snappy
的name和species字段指向相同字
符串。
结构中的结构
既然结构可以用现有数据类型创建数据类型,也就能用其他
结构创建结构。举个例子:
struct preferences {
const char *food;
float exercise_hours;
};
struct fish {
const char *name;
const char *species;
int teeth;
int age;
struct preferences care; //结构中的结构,即嵌套
};
上述代码向计算机描述了一个结构中的结构。你可以像之前
一样用数组语法创建变量,但现在可以在数据中包含结构中
的结构。
struct f