C语言--结构体和枚举
* 在前面我们已经介绍了C语言中的数组,用法跟其他语言差不多。当一个整体由多个数据构成时,我们可以用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据。
* 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。
* 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的
一、数组和结构体的对比
数组:只能有多个同一类型的数据构成
结构体:可以有多个不同类型的数据构成
1>、结构体定义格式:
struct 结构体名{
类型名1 成员名1;
类型名2 成员名2;
……
类型名n 成员名n;
};
struct是关键字,是结构体类型的标志
通过结构体例子,看一下定义
#include<stdio.h>
int main()
{
//1.定义结构体类型 (并不分配存储空间) 格式:struct 类型 {};
struct Person
{ //里面的3个变量可以说是结构体的成员或属性
int age;
char *name;//char name[10];
double height;
};
//2.根据结构体类型,定义结构体变量,并赋值(分配存储空间 大小为最大成员字节的倍数(补齐算法)))
// struct Person p ={21,"Jack",1.78};
//struct Person p2 = {.age = 34, .name = "lonsv", .height = 1.65};
struct Person p3;
p3.age = 25;
p3.name = "tom";
p3.height = 1.87;
/*这是一种错误的格式
srtuct Person p4;
p4 = {21,"alice",1.75};
结构体赋值方式和数组相似,只能在初始化时进行赋值
*/
p3.age = 23;//对初始值进行修改
p3.name = "rose";//对初始值进行修改
printf("age = %d,name = %s,height = %f\n", p3.age, p3.name, p3.height);
return 0;
}
二、下面看一下结构体内存的分配情况:
#include <stdio.h>
int main()
{
struct Date
{
int year;
int month;
int day;
};
//执行完后如图1
struct Date d1= {2011,4,10};struct Date d2= {2012,12,9};
//执行完后如图2
d2 = d1;
//只会对d2修改,对d1没任何影响
d2.year = 1998;
printf("%d-%d--%d\n",d1.year, d1.month, d1.day);
}
图 1
图 2
三、结构体定义的3种形式:
定义结构体变量的3中形式:
1>先定义类型,在定义变量(分开定义)
struct Student
{
int age;
int name;
};
struct Student stu;
2>定义类型的同时定义变量
struct Student
{
int age;
int name;
} stu;
3>定义类型的同时定义变量 (省略类型名称)
struct
{
int age;
int name;
} stu;
具体实例如下:
#include <stdio.h>
int main()
{
/*第一种形式
struct Student
{
int age;
int name;
};
struct Student stu;
struct Student stu2;
*/
/*第二种形式:定义类型的同时定义变量
这句代码做了两件事:
1.定义结构体类型
2.利用新定义好的类型来定义结构体变量
struct Student
{
int age;
int name;
} stu;
struct Student stu2;
*/
/*第三种形式:缺点不能重用
//这个可以这样用,因为不存在结构体名称,不存在重复定义
struct
{
int age;
int name;
} stu;
struct
{
int age;
int name;
} stu2;
*/
/*这是一种错误的定义,类型重复定义
struct Student
{
int age;
int name;
};
struct Date d1= {2011,4,10};
struct Student
{
int age;
int name;
};
struct Date d1= {2011,4,10};
*/
}
四、结构体的初始化
将各成员的初值,按顺序地放在一对大括号{}中,并用逗号分隔,一一对应赋值。
比如初始化Student结构体变量stu
struct Student {
char *name;
int age;
};
struct Student stu = {"MJ", 27};
只能在定义变量的同时进行初始化赋值,初始化赋值和变量的定义不能分开,下面的做法是错误的:
struct Student stu;
stu = {"MJ", 27};
五、结构体的作用域:
从定义类型的那一行开始,一直到代码块结束
void test()
{
//这时运行会报错,因为此时Date该没有被定义,不能使用
struct Date d1;
}
struct Date
{
int year;
int day
};
int main()
{
return 0;
}
那么为了让结构体在全局都能用,应该把结构体定义在代码行最前端(类似于全局变量),注意:再调用结构体时,会现在本块内部进行查找,如果内部能满足,则不调用外部的
<pre name="code" class="cpp">struct Date
{
int year;
int day
};
void test()
{
struct Date d1;
}
int main()
{<pre name="code" class="cpp">struct Date
{
int year;
};
struct Date d;//这时调用的是main方法内部的结构体Date,所以他的类型只有一个int
return 0;
}
六、结构体数组:对多个类型输出
例如这个排名
应该采用结构体数组:格式 :类型 名称[];(类似于普通数组 int a[];),下面是一个例子:
//结构体数组
#include <stdio.h>
struct Record
{
int no;//排名
char *name;//名称
int record;//分值
};
int main()
{
int i;
//定义结构体数组并赋初始值
struct Record r[3] =
{{1, "jack", 5000},{2, "Jim" ,500},{3, "jake", 300}};
//aaaaa r[0].record = 3000;//对数组值进行修改
for ( i = 0; i < 3; i++)//通过遍历对数组进行输出
printf("%d\t%s\t%d\t\n",r[i].no, r[i].name, r[i].record);
}
输出结果如图:
七、指向结构体的指针
1.格式:struct 结构体类型 *p; (类似于int *p)
p = &结构体名称;
2.利用指针访问结构体成员
1>. (*p).成员名称
2>. p->成员名称
3> 结构体变量名.成员名称
具体实例如下:
int main()
{
struct Student
{
char *name;
int age;
};
//结构体变量
struct Student stu = {"star", 21};
//指针变量p将来指向 struct Student 类型的数据
struct Student *p;
//指针变量p指向stu变量的地址
p = &stu;
p->age = 23;//对结构体的属性值进行修改
// printf("姓名:%s\t年龄:%d\n",stu.name, stu.age);第一种
// printf("姓名:%s\t年龄:%d\n",(*p).name, (*p).age);第二种
//第三种,也是最常用的一种
printf("姓名:%s\t年龄:%d\n",p->name, p->age);
}
八、结构体的嵌套
struct 大结构体名称{ struct 小结构体名称 大结构体属性 };
#include <stdio.h>
//结构体的嵌套
struct Date
{
int year;
int month;
int day;
};
int main()
{
struct Student
{
int no;//学号
struct Date birthday;//出生日期
struct Date ruxueDate;//入学日期
//struct Student stu;//这是错误的,结构体不能包含自己
};
//赋值时结构体要用大括号括起来
struct Student stu = {3012, {1992, 5, 21}, {2013, 9, 10}};
//访问时是通过,大结构体名称.大结构体属性.小结构体属性
printf("生日是:%d-- %d-- %d\n",stu.birthday.year, stu.birthday.month, stu.birthday.day);
}
九、枚举:当变量有几个固定的取值时用枚举
枚举是C语言中的一种基本数据类型,并不是构造类型,它可以用于声明一组常数。当一个变量有几个固定的可能取值时,可以将这个变量定义为枚举类型。比如,你可以用一个枚举类型的变量来表示季节,因为季节只有4种可能的取值:春天、夏天、秋天、冬天
枚举类型定义:enum 枚举名称{a,b,c};注意:中间是逗号” ,“ 不是分号“ ;”
调用时:enum 枚举名称 变量 = 枚举内容;
枚举类型是默认顺序,从0开始依次累加,也可以自定义开始序号
#include <stdio.h>
int main()
{
//枚举类型定义:enum 枚举名称{a,b,c};
enum Season
{
spring,
summer,
autumn,
winter
};
//调用时:enum 枚举名称 变量 = 枚举内容;
enum Season s = spring;//枚举类型是默认顺序,从0开始依次累加,也可以自定义开始序号
printf("%d\n",s);
return 0;
}
有3种方式定义枚举变量
1.先定义枚举类型,再定义枚举变量
enum Season {spring, summer, autumn, winter};
enum Season s;
2.定义枚举类型的同时定义枚举变量
enum Season {spring, summer, autumn, winter} s;
3.省略枚举名称,直接定义枚举变量
enum {spring, summer, autumn, winter} s;
枚举变量的基本操作
赋值:可以给枚举变量赋枚举常量或者整型值
enum Season {spring, summer, autumn, winter} s;
s = spring; // 等价于 s = 0;
s = 3; // 等价于 s = winter;
2.遍历枚举元素
enum Season {spring, summer, autumn, winter} s;
// 遍历枚举元素
for (s = spring; s <= winter; s++) {
printf("枚举元素:%d \n", s);
}
输出结果: