char name[20]; //姓名 int num; //学号 char sex; //性别 int age; //年龄 float score; //成绩 char addr[30]; //家庭住址而且问题是这样写的话,只是定义了一个学生,如果要定义第二个学生就要再写一遍。这样不仅麻烦,而且很容易混淆。要是能定义一个变量,而且这个变量正好包含这六个项,即将它们合并成一个整体的话就好了。
struct结构体名
{
成员列表
};
struct STUDENT
{
char name[20];
int num;
char sex;
int age;
float score;
char addr[30];
}; //最后的分号千万不能省略
说明:
struct STUDENT
{};
struct STUDENT
{
};
char name[20]; int num; char sex; int age; float score; char addr[30];成员名的命名规则与变量名相同。
int a;其中 int 是类型,而 a 是用这个类型定义的变量。结构体也是一样的,上一节只是声明了一个类型,而本小节要使用这个类型来定义变量,就这么简单。一个是类型,一个是用这个类型定义的变量。
struct STUDENT stud1, stud2;stud1 和 stud2 就是我们定义的结构体变量名。定义了结构体变量之后,系统就会为之分配内存单元。与前面讲的局部变量一样,如果 stud1 和 stud2 是在某个函数中定义的局部变量,那么就只能在该函数中使用。在其他函数中可以定义重名的结构体变量而不会相互产生影响。
struct STUDENT
{
char name[20];
int num;
char sex;
int age;
float score;
char addr[30];
}stud;
这样就声明了一个结构体类型,并用这个类型定义了一个结构体变量 stud。这个变量是一个全局变量。结构体变量名.成员名
如果成员名是一个变量名,那么引用的就是这个变量的内容;如果成员名是一个数组名,那么引用的就是这个数组的首地址。student1.num = 1207041;2) 如果结构体类型中的成员也是一个结构体类型,则要用若干个“.”,一级一级地找到最低一级的成员。因为只能对最低级的成员进行操作。
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20];
int num;
struct AGE birthday;
float score;
};
完全可以写成:
struct STUDENT
{
char name[20];
int num;
int year;
int month;
int day;
float score;
};
但这样看起来很长、很乱。而使用结构体将 year、month、day 封装起来,代码看起来就会好很多。因为 year、month、day 都是生日的组成部分,所以将它们进行进一步的封装可以使代码看起来很整齐,很有层次感,便于操作。
# include <stdio.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20];
int num;
struct AGE birthday; //就有点类似于C++中的封装了
float score;
};
int main(void)
{
struct STUDENT student1 = {"小明", 1207041, {1989, 3, 29}, 100};
printf("name : %s\n", student1.name);
printf("birthday : %d-%d-%d\n", student1.birthday.year, student1.birthday.month, student1.birthday.day);
printf("num : %d\n", student1.num);
printf("score : %.1f\n", student1.score);
return 0;
}
输出结果是:
printf("name : %s\n", &student1);
原因是 %s 要求输出参数要么是字符数组名,要么是字符指针变量名,总之是 char* 型的。而 &student1 和 student1.name 在前面讲过,虽然它们是等价的,但它们的等价指的仅仅是“它们表示的是同一个内存空间的地址”,但它们的类型是不同的。&student1 是 struct STUDENT* 型的,而 student1.name 是 char* 型的,所以只能写 student1.name。
# include <stdio.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20];
int num;
struct AGE birthday;
float score;
};
int main(void)
{
struct STUDENT student1 = {"小明", 1207041, {1989, 3, 29}, 100};
return 0;
}
注意,同字符、字符数组的初始化一样,如果是字符那么就用单引号括起来,如果是字符串就用双引号括起来。
# include <stdio.h>
# include <string.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20]; //姓名
int num; //学号
struct AGE birthday; /*用struct AGE结构体类型定义结构体变量birthday, 即生日*/
float score; //分数
};
int main(void)
{
struct STUDENT student1; /*用struct STUDENT结构体类型定义结构体变量student1*/
strcpy(student1.name, "小明"); //不能写成&student1
student1.num = 1207041;
student1.birthday.year = 1989;
student1.birthday.month = 3;
student1.birthday.day = 29;
student1.score = 100;
printf("name : %s\n", student1.name); //不能写成&student1
printf("num : %d\n", student1.num);
printf("birthday : %d-%d-%d\n", student1.birthday.year, student1.birthday.month, student1.birthday.day);
printf("score : %.1f\n", student1.score);
return 0;
}
输出结果是:
# include <stdio.h>
struct AGE
{
int year;
int month;
int day;
};
struct STUDENT
{
char name[20];
int num;
struct AGE birthday;
float score;
}; //分号不能省
int main(void)
{
struct STUDENT student1; /*用struct STUDENT结构体类型定义结构体变量student1*/
printf("请输入姓名:");
scanf("%s", student1.name); //不能写成&student1
printf("请输入学号:");
scanf("%d", &student1.num);
printf("请输入生日:");
scanf("%d", &student1.birthday.year);
scanf("%d", &student1.birthday.month);
scanf("%d", &student1.birthday.day);
printf("请输入成绩:");
scanf("%f", &student1.score);
printf("name: %s\n", student1.name); //不能写成&student1
printf("num: %d\n", student1.num);
printf("birthday: %d-%d-%d\n", student1.birthday.year, student1.birthday.month, student1.birthday.day);
printf("score: %.1f\n", student1.score);
return 0;
}
输出结果是:
scanf("%s",student1.name);
也可以这么写:
scanf("%s", &student1.name);
虽然在编译器中,&student1.name 代表的也是 name 的首地址,但是不建议初学者这么写,原因如下:
版权说明:Copyright © 广州松河信息科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州松河信息科技有限公司 版权所有