一、定义结构体的一般格式:
struct 结构体名
{
成员表
};
说明:
1、结构体名是用户自定义的名字,在以后定义结构体变量时使用该名字进行类型标识。
2、成员表是结构体数据中每一个数据项的变量说明,格式一般为:
数据类型名 成员名;
3、struct是关键字 ,struct 结构体名 是结构体类型标识符,在类型定义及使用时都不能忽略“struct”。
下面是三种不同的结构体定义及初始化的方式:
结构体定义初始化1:
struct student
{
int age;
char id[20];
char name[20];
char sex;
int score;
}stu1;
int main()
{
scanf("%d %s %s %c %d", &stu1.age, &stu1.id, &stu1.name, &stu1.sex, &stu1.score);
printf("the result is:");
printf("%s %d %c %s %d", stu1.name, stu1.age, stu1.sex, stu1.id, stu1.score);
}
上述代码中的stu1是结构体变量,可在结构体的末端定义,也可以在main()函数中定义
运行结果:
结构体定义初始化2:
struct student
{
int age;
char id[20];
char name[20];
char sex;
int score;
}stu1 = {20,"20201111","lihua",'M',60};
int main()
{
printf("%s %d", stu1.name, stu1.age);
return 0;
}
运行结果:
结构体定义初始化3:
struct student
{
int age;
char id[20];
char name[20];
char sex;
int score;
};
int main()
{
struct student stu1 = { 20,"20201111","lihua",'M',60 };
printf("%s %d", stu1.name, stu1.age);
return 0;
}
运行结果:
二、结构体数组和指针
struct student
{
int age;
char id[20];
char name[20];
char sex;
int score;
};
int main()
{
struct student information[60]; //定义一个结构体数组
struct student* ps = information; //定义一个结构体指针指向结构体变量information
int i = 0;
for (i = 0; i < 3; i++)
{
printf("请输入学生%d号的姓名和年龄:",i+1);
scanf("%s %d", &information[i].name, &information[i].age);
}
for (i = 0; i < 3; i++)
{
printf("%s %d\n", ps->name, ps->age);
ps++;
}
return 0;
}
运行结果:
三、结构体指针用法示例
struct STU
{
char name[20];
int score;
char sex;
char id[20];
}stu;
int main()
{
struct STU stu1, * p;
p = &stu1;
//struct STU* p= &stu; 也可以直接这样写
//对结构体成员赋值
strcpy(p->name, "lihua");
//p->name = "lihua"; //错误的写法
p->score = 89;
p->sex = 'M';
strcpy(p->id, "111222");
printf("%s %d %c %s", p->name, p->score, p->sex, p->id);
return 0;
}
运行结果:
四、结构体传参
两种写法:传变量(传值调用)、传地址(传址调用)
struct B
{
int a;
char b[10];
};
struct STU
{
int age;
char name[10];
char id[10];
struct B b;
};
void print1(struct STU t)
{
printf("%d %s %s %d %s\n", t.age, t.name, t.id, t.b.a, t.b.b);
}
void print2(struct STU* ps)
{
printf("%d %s %s %d %s\n", ps->age, ps->name, ps->id, ps->b.a, ps->b.b);
}
int main()
{
struct STU s = { 20,"张三","20210001" ,{10,"zhangsan"} };
//传变量(传值调用)
print1(s);
//传地址(传址调用)
print2(&s);
return 0;
}
运行结果:
两者方法的利弊:
1、传值调用时,若结构体过大,会压栈、降低效率,浪费空间。使用传址调用可以节省空间利用率,加快程序执行速度。
2、传值调用,函数内形参数据改变不可以改变实参的值。传址调用,函数可随时改变实参的值。前者更安全,后者更方便。
总结:结构体传参建议用传地址
扩展知识:
给栈中传入数据:压栈。
给从栈中传出数据:出栈。
栈是一种数据结构。先进的后出,后进的先出。
五、例题
输入一组学生数据,1、输出成绩85以上同学的姓名和成绩 2、统计男生个数与女生个数
代码实现:
#define N 5
struct STU
{
char name[20];
int score;
char sex;
char id[20];
}stu[N];
int main()
{
int i = 0;
for (i = 0; i < N; i++)
{
printf("请输入学生%d号的姓名和学号、性别和成绩:\n", i + 1);
printf("请输入学生姓名:");
scanf("%s", &stu[i].name);
printf("请输入学生学号:");
scanf("%s", &stu[i].id);
printf("请输入学生性别:");
scanf(" %c", &stu[i].sex);
printf("请输入学生成绩:");
scanf(" %d", &stu[i].score);
}
int count = 0;
printf("成绩85以上同学的姓名和成绩如下:\n");
for (i = 0; i < N; i++)
{
if (stu[i].sex == 'm' || stu[i].sex == 'M')
count++;
if (stu[i].score >= 85)
printf("%s %d\n", stu[i].name, stu[i].score);
}
printf("班级中共有男生%d人,共有女生%d人。", N - count, count);
return 0;
}
运行结果: