一、枚举
1.概念
枚举(Enumeration)是C语言中的一种用户自定义数据类型,用于定义一组相关的常量。枚举使我们可以为这些常量分配有意义的名字,从而提高代码的可读性和可维护性。
如果我们定义一个变量,用来表示一周中的一天,该变量的值只能从七个有效值中选择,枚举可以帮助我们限制变量的有效值。
2.语法
enum 枚举名称
{
枚举元素1,
枚举元素2,
...
枚举元素N
};
3.特点
枚举元素也称为枚举成员或枚举常量,具有如下特点:
- 枚举元素的值必须在同一枚举中是唯一的
- 枚举元素的值必须是整数类型,通常是int
- 如果没有为枚举元素指定值,编译器会自动为它们分配值,从0开始,依次递增。
- 定义枚举的时候也可以为枚举元素自定义值,需保证唯一性和整型类型。
4.代码演示
#include <stdio.h>
int main()
{
enum Week{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FIRDAY,
SATURDAY,
SUNDAY
};//枚举成员周一到周日
enum Week a=MONDAY;
enum Week b=TUESDAY;
printf("%d %d",a,b);
return 0;
}
枚举元素的值自动分配,从0到6。
#include <stdio.h>
int main()
{
enum Week{
MONDAY=1,
TUESDAY,
WEDNESDAY,
THURSDAY,
FIRDAY,
SATURDAY,
SUNDAY
};//枚举成员周一到周日
enum Week a=MONDAY;
enum Week b=TUESDAY;
printf("%d %d",a,b);
return 0;
}
给枚举元素赋值1,后面依次增加。
5.枚举应用
(1)遍历
如果枚举常量的值是连续的,我们可以使用循环遍历;如果枚举常量的值不是连续的,则无法遍历。
#include <stdio.h>
int main()
{
enum Week{
MONDAY=1,
TUESDAY,
WEDNESDAY,
THURSDAY,
FIRDAY,
SATURDAY,
SUNDAY
};//枚举成员周一到周日
for(int i=MONDAY;i<=SUNDAY;i++)
{
printf("%d\n",i);
}
return 0;
}
(2)switch中应用
#include <stdio.h>
int main()
{
enum Week{
MONDAY=1,
TUESDAY,
WEDNESDAY,
THURSDAY,
FIRDAY,
SATURDAY,
SUNDAY
}day;//枚举成员周一到周日
printf("请输入今天的星期:");
scanf("%d",&day);//成员名就是数字,输入1就是星期一,2就是星期二
switch(day)
{
case MONDAY:
printf("今天是星期一");
break;
case TUESDAY:
printf("今天星期二");
break;//方便起见,只写到周二
}
return 0;
}
二、结构体
C语言提供了struct关键字,允许自定义复合数据类型,将不同类型的值组合在一起,这种类型称为结构体(structure)类型。
C语言没有其他语言的对象(object)和类(class)的概念,struct 结构很大程度上提供了对象和类的功能。
1.语法:
struct 结构体名
{
数据类型1 成员名1;
数据类型2 成员名2;
……
数据类型n 成员名n;
};
2.声明方式:
方式1 先定义结构体,然后再创建结构体变量
// 定义结构体
struct Student
{
int id; // 学号
int age; // 年龄
char *name; // 姓名
char gender; // 性别
char *address; // 家庭住址
};
// 定义结构体变量
struct Student stu1,stu2;
方式2 在定义结构体的同时定义结构体变量
// 定义结构体的同时定义 stu1和 stu2 两个变量
struct Student
{
int id; // 学号
int age; // 年龄
char *name; // 姓名
char gender; // 性别
char *address; // 家庭住址
} stu1, stu2;
方式3 在定义时也可以不给出结构体名
// 不给出结构体的名字
struct
{
int id; // 学号
int age; // 年龄
char *name; // 姓名
char gender; // 性别
char *address; // 家庭住址
} stu1, stu2;
3.成员的获取和赋值
成员是结构体的一个组成部分,一般是基本数据类型、也可以是数组、指针、结构体等。结构体的成员也可以称为属性。
结构体和数组类似,也是一组数据的集合,结构体使用点号 . 获取单个成员,可以进行赋值和取值。
(1)结构体成员逐个赋值
#include <stdio.h>
int main()
{
//声明结构体
struct Student
{
int age;
char *name;
char sex;//用字符代表性别,m为男,g为女。
char *phone;
};
struct Student stu;
stu.age=23;
stu.name="a chuan";
stu.sex='m';
stu.phone="1333333333";
printf("%d %s %c %s",stu.age,stu.name,stu.sex,stu.phone);
return 0;
}
(2)使用大括号一次性赋值
#include <stdio.h>
int main()
{
//声明结构体
struct Student
{
int age;
char *name;
char sex;//用字符代表性别,m为男,g为女。
char *phone;
}stu1={24,"a chuan",'m',"222234344"};
printf("%d %s %c %s",stu1.age,stu1.name,stu1.sex,stu1.phone);
return 0;
}
4.结构体指针
结构体指针是指向结构体的指针变量,允许间接访问和操作结构体的成员,它提供了一种方便的方式来处理结构体数据。
声明结构体指针的语法格式:
struct 结构体名 *结构体指针变量名;
通常需要先定义一个结构体变量,再创建结构体指针,并取结构体变量的地址作为结构体指针的值。
结构体指针指的是结构体变量的地址
// 声明结构体
struct Student
{
int id; // 学号
int age; // 年龄
char *name; // 姓名
char gender; // 性别
char *address; // 家庭住址
};
// 声明结构体变量
struct Student stu;
// 声明结构体指针并初始化
struct Student *ptr = &stu;
结构体指针可以通过“->” 操作符访问结构体的成员。
#include <stdio.h>
int main()
{
// 结构体
struct Student
{
char *name;
int age;
char gender;
};
// 结构体变量
struct Student s = {"张三", 20, 'M'};
// 通过结构体变量访问成员
printf("name=%s,age=%d,gender=%c \n", s.name, s.age, s.gender);
// 声明结构体指针
struct Student *ps = &s;
// 结构体指针通过解引用访问成员
printf("name=%s,age=%d,gender=%c\n", (*ps).name, (*ps).age, (*ps).gender);
// 结构体指针使用->访问成员
printf("name=%s,age=%d,gender=%c\n", ps->name, ps->age, ps->gender);
return 0;
}
输出结果:
name=张三,age=20,gender=M
name=张三,age=20,gender=M
name=张三,age=20,gender=M
总结:如果指针变量p指向一个结构体变量stu,以下3种用法等价:
- stu.成员名
- (*p).成员名
- p->成员名
#include <stdio.h>
int main()
{
struct Students
{
int id;
char *name;
char sex;
}stu={13,"achuan",'m'};
printf("%d %s\n",stu.id,stu.name);//操作成员体变量用的是点语法
struct Students *ptr=&stu;
printf("%d %s\n",ptr->id,ptr->name);//结构体指针访问成员数据
ptr->sex='g';
printf("%c %c\n",ptr->sex,stu.sex);
(*ptr).name="lin shuai";//有*有.优先级问题,需要括号
printf("%s",(*ptr).name);
return 0;
}
5.案例
#include <stdio.h>
struct Dog
{
char *name;
int age;
double weight;
}dog;
char *say(struct Dog)
{
static char sss[50];
sprintf(sss,"name=%s,age=%d,weight=%lf",dog.name,dog.age,dog.weight);
return sss;
}
int main()
{
struct Dog dog={"wang cai",5,2.4};
char *ptr=NULL;
ptr=say(dog);//默认值传递
printf("%s %d %lf",dog.name,dog.age,dog.weight);
return 0;
}
三、共用体
1.概念
有时需要一种数据结构,不同的场合表示不同的数据类型。比如,如果只用一种数据结构表示学生的“成绩”,这种结构就需要有时是整数(80、90),有时是字符('A'、'B'),有时是浮点数(80.5、60.5)。
C语言提供了共用体类型(Union 结构),用来自定义可以灵活变更的数据结构。它内部可以包含各种属性,但同一时间只能有一个属性,因为所有属性都保存在同一个内存地址,后面写入的属性会覆盖前面的属性。这样做的最大好处是节省空间。
“共用体”与“结构体”的定义形式相似,但它们的含义是不同的。
结构体变量所占内存长度,可以认为是各成员占的内存长度的叠加;每个成员分别占有其自己的内存单元。
共用体变量所占的内存长度等于最长的成员的长度;几个成员共用一个内存区。
2.语法
// 声明共用体类型
union data
{
short m;
float x;
char c;
};
// 声明共用体变量
union data a, b;
3.案例
现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、 分数,教师的信息包括姓名、编号、性别、职业、教学科目:可以参考下面的表格。
请利用共用体,只使用一个结构体保存每个人的信息。
#include <stdio.h>
#define TT 4 //人员
//定义结构体,将来用结构体存储学生和教师信息
struct People
{
char name[50];
int num;
char sex;
char zhiye;
union
{
double score;
char course[20];
}st;
};
int main()
{
//结构体类型数组
struct People arr[TT];
for(int i=0;i<TT;i++)
{
printf("请输入信息:");
scanf("%s %d %c %c",arr[i].name,&arr[i].num,&arr[i].sex,&arr[i].zhiye);
if(arr[i].zhiye=='s')
{
printf("请输入学生分数:");
getchar();
scanf("%lf",&arr[i].st.score);
}
else
{
printf("请输入老师课程:");
getchar();
scanf("%s",&arr[i].st.course);
}
}
printf("输出人员信息:\n");
for(int i=0;i<TT;i++)
{
if(arr[i].zhiye=='s')
{
printf("姓名:%s\t编号:%d\t性别:%c\t职业:%c\t分数:%lf\n",arr[i].name,arr[i].num,arr[i].sex,arr[i].zhiye,arr[i].st.score);
}
else
{
printf("姓名:%s\t编号:%d\t性别:%c\t职业:%c\t课程:%s\n",arr[i].name,arr[i].num,arr[i].sex,arr[i].zhiye,arr[i].st.course);
}
}
return 0;
}
四、typedef
typedef 命令用来为某个类型起别名。
typedef 类型名 别名;
typedef int zhengshu;
zhengshu a=100;//声明一个变量a
typedef为结构体、共用体起别名
struct Treenode
{
// ...
};
typedef struct Treenode Tree; //Tree 是 struct Treenode 的别名
为指针起别名
typedef int *intptr;
int a = 10;
intptr x = &a;
为数组类型起别名
// 举例1 给int[5] 取别名 fiveInts
typedef int fiveInts[5];
fiveInts x = {11, 22, 33, 44, 55}; // 相当于 int x[5] = {11, 22, 33, 44, 55};
// 举例2 给 int[100] 取别名 Num
typedef int Num[100]; // 声明Num为整型数组类型名
Num a; // 相当于 int a[100];