结构体
结构体是有许多数据项,每个数据项的数据类型可以不同,这些数据项也被称为分量,成员或属性。结构可以拷贝,赋值,传递给函数,还可以处理复杂的数据结构,因此被广泛应用到现代的大型信息管理系统。
结构体类型定义
struct stu{
char name[20]; //名字
int age; //年龄
char sex[5]; //性别
char id[20]; //学号
}; //分号不能丢
结构体变量的定义也可以在定义结构体类型的同时进行。也可以定义结构体数组类型。定义与初始化可以分开进行,也可以在定义时初始化。
结构体变量
在定义结构体变量时可以对它的成员初始化。初始化列表用花括号括起来,依次赋给结构体变量各成员。
C99 标准允许对某一成员初始化,如:
struct Student a = {.name = “Zhang San”};
1
“.name” 隐含代表结构体变量 a 中的成员 a.name 。其他未被指定初始化的数值型成员被系统化为 0 ;字符型初始化为 ‘\0’,指针型初始化为 NULL。
(2)结构体变量中的成员值引用方式为:
结构体变量名.成员名
如a.name 表示引用 a 变量的 name 成员值; “.” 是成员运算符,它在所有的运算符中优先级最高。
(3)如果成员本身又是一个结构体类型,则要用若干个成员运算符,一级一级地找到最低一级的成员,只能对最低一级的成员进行赋值或存取以及运算。
student.birthday.month (结构体变量 student 中的成员 birthday 中的成员 month)
1
(4)对结构体成员变量可以向普通变量一样进行各种运算。
student.age++ (自加运算)
1
(5)同类结构体变量可以相互赋值。
student1 = student2;
1
(6)使用 scanf 函数输入结构体变量时,必须分别输入各成员的值,不能再 scanf 函数中使用结构体变量名一揽子输入全部成员的值。
scanf("%d%s%c", &student.num, student.name, &student.sex);
1
注意 student.name 前没有 & 运算符,因为 name 是数组名,本身就代表地址。
Example:
#include <stdio.h>
int main() {
struct Student {
int num;
char name[20];
int age;
char sex;
} student = {1001, "Jun Chen", 23, 'M'};
printf("No.: %d\nname: %s\nage: %d\nsex: %c\n",
student.num, student.name, student.age, student.sex);
return 0;
}
Run result:
No.: 1001
name: Jun Chen
age: 23
sex: M
结构体数组
结构体数组与数值型的数组的不同之处在于每个数组元素都是一个结构体类型的数据,都分别包含各个成员项。
定义结构体数组的一般形式:
(1)
struct 结构体名 {
成员列表
} 数组名[数组长度];
1
2
3
(2)先声明一个结构体类型,然后在用此类型定义结构体数组:
结构体类型 数组名[数组长度];
(3)对结构体数组初始化的形式是在定义数组的后面加上:
={初值表列};
Example:
#include <stdio.h>
int main() {
struct Person {
char name[20];
int age;
} leader[2] = {"Jun Chen", 23, "Sally", 18};
int i = 0;
for(; i < 2; i++)
printf("name: %s, age: %d\n", leader[i].name, leader[i].age);
struct Person student[3];
student[2].name[0] = 'J';
student[2].name[1] = 'u';
student[2].name[2] = 'n';
student[0].age = 100;
printf("name: %s, age: %d\n", student[2].name, student[0].age);
return 0;
}
Run result:
name: Jun Chen, age: 23
name: Sally, age: 18
name: Jun, age: 100
结构体指针
结构体指针就是指向结构体变量的指针,一个结构体变量的起始地址就是这个结构体变量的指针。
指向结构体变量的指针
指向结构体对象的指针变量既可指向结构体变量,也可指向结构体数组中的元素。
Example:
#include <stdio.h>
#include <string.h>
int main() {
struct Student {
char name[20];
float score;
};
struct Student *p, student;
p = &student;
strcpy(student.name, "Jun Chen");
student.score = 98;
printf("name: %s, score: %f\n\n", student.name, student.score);
printf("name: %s, score: %f\n", (*p).name, (*p).score);
return 0;
}
Run result:
name: Jun Chen, score: 90.000000
name: Jun Chen, score: 90.000000
(*p) 表示 p 指向结构体变量, (*p).name 是 p 指向的结构体变量中的成员 score 。注意 *p 两侧的括号不可省略,因为成员运算符 “.” 优先于 “ * ” 运算符。*p.score 等价于 *(p.score) 。
说明: 为了方便和直观,C 语言允许把 (*p).name 用 p->name 来代替, “->” 代表一个箭头,p->name 表示 p 指向的结构体变量中的 name 成员。“->” 称为指向运算符。
指向结构体数组的指针
将一个结构体变量的值传递给另一个函数,有三个方法:
1、用结构体变量的成员作参数;(值传递)
2、用结构体变量做实参;(值传递)
3、用指向结构体变来那个的指针作实参,将结构体变量的地址做实参。(址传递)
Example:
#include <stdio.h>
#define N 3
struct Student {
long num;
char name[20];
float score[3];
float aver;
};
int main() {
void input(struct Student stu[]);
struct Student max(struct Student stu[]);
void print(struct Student);
struct Student stu[N], *p = stu;
input(p);
print(max(p));
return 0;
}
void input(struct Student stu[]) {
int i;
printf("Please input three students's grade:\n");
for(i = 0; i < N; i++) {
scanf("%ld %s %f %f %f", &stu[i].num, stu[i].name,
&stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);
stu[i].aver = (stu[i].score[0] + stu[i].score[1] + stu[i].score[2]) / 3.0;
}
}
struct Student max(struct Student stu[]) {
int i, m = 0;
for(i = 0; i < N; i++)
if(stu[i].aver > stu[m].aver) m = i;
return stu[m];
}
void print(struct Student stu) {
printf("\nMaximum grade student is: \n");
printf("No.: %ld\nName: %s\nScore: %5.1f, %5.1f, %5.1f\nAverage: %6.2f\n",
stu.num, stu.name, stu.score[0], stu.score[1], stu.score[2], stu.aver);
}
run result
Please input three students's grade:
10101 Jun 80 83 85
10102 Sam 90 93 98
10103 Tom 78 96 68
Maximum grade student is:
No.: 10102
Name: Sam
Score: 90.0, 93.0, 98.0
Average: 93.67