C/C++ 第十讲 结构
10.1 结构体类型
例:输入5个学生的信息,如何将这些信息按平均分倒序排序并输出?学生信息:学号、姓名、语文、数学、外语三门课成绩。
- 独立变量:30个;
- 通常的数组:定义多个数组,分别存放5人的姓名、学号、成绩
- 使用结构类型数组!
1 2 3 4 5 6
| struct Student { char name[20]; char no[7]; int Chinese,English,math; }s[5];
|
结构类型的概念
按类型和性质将可能不同但有关联的数据组合在一起构成的集合。
结构类型如何声明
1 2 3 4 5 6 7
| struct 结构类型标识符 { 结构成员1定义; 结构成员2定义; ...; 结构成员n定义; };
|
结构类型可以嵌套定义,即一个结构类型的变量可以作为另一结构类型的成员。(但不能作为自身的)
例:先声明结构类型date,再声明结构类型person
1 2 3 4 5 6 7 8 9 10 11 12 13
| struct date { int month; int day; int year; }; struct person { char name=[]; char sex; int age; struct date birthday; };
|

结构成员 birthday
是内嵌在 struct person
类型中的另一个结构类型的变量。
结构变量如何定义
结构类型不是程序操作的对象,不占用内存空间,只有在定义结构变量后,系统才会为之分配内存单元。定义方式:
- 先声明结构类型再定义结构变量
- 在声明结构类型的同时定义结构变量
- 省略结构标识符直接定义结构变量
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| struct person { char name[15]; char sex; int age; struct date birthday; }p1,p2;
struct person { char name[15]; char sex; int age; struct date birthday; }; struct person p1,p2;
struct { char name[15]; char sex; int age; struct date birthday; }p1,p2;
struct student { char name[30]; char num[10]; double score; }s= {"FangMin", "1300010", 87};
|
10.2 结构体变量
结构变量的访问
结构成员的访问
结构变量多数情况下需访问到成员,而不能整体访问。
通过结构变量访问成员:
结构变量名.成员名
通过指向结构的指针访问成员:
(*指向结构的指针).成员名
注:括号不能省略,否则优先.
运算
p->name
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct date { int month; int day; int year; };
struct person { char name[15]; char sex; int age; date birthday; }p1,*p=&p1;
|
可如下访问:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| p1.age=21; strcpy(p->name,"Fang Min"); p->birthday.month=8;
strcpy (p1.name, "Fang Min"); p1.sex = 'F'; p1.age = 24; p1.birthday.month = 8; p1.birthday.day = 10; p1.birthday.year = 1989;
strcpy(p->name, "Fang Min"); p->sex = 'F'; p->age = 24; p->birthday.month = 8; p->birthday.day = 10; p->birthday.year = 1988;
|
其中,
name
成员为字符数组,对字符数组赋值必须通过调用 strcpy
函数实现,而不能直接用赋值语句;
而 birthday
成员本身又是一个内嵌的结构类型变量,所以也要按结构成员访问方式访问到它的具体成员 year、 month、 day。
总结:小心字符数组char s[N]和内嵌型结构变量。
访问原则
- 不允许整体输入输出结构变量,必须逐成员输入输出;
- 允许整体赋值和做函数参数;
- 引用成员时若成员本身又属复杂类型,则需逐级找到最低一级成员;
- 成员需遵循同类型普通变量的使用规则及其各种运算。
初始化
10.3 结构的应用
引例的实现
输入5个学生的信息,如何将这些信息按平均分倒序排序并输出?学生信息:学号、姓名、语文、数学、外语三门课成绩。
分析:
- 数据结构的选取:应将平均分也定义在“学生”结构类型中;
- 正确理清层次关系;
- 明确输入、输出、赋值等操作数据的访问要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include "iostream" #define N 5 using namespace std; struct student { char name[20]; char no[7]; double Chinese,Engilsh,math,avg; }; int main() { int i,j; student s[N],t; for(i=0;i<N;i++) { cin>>s[i].name>>s[i].Chinese>>s[i].English>>s[i].math; s[i].avg=(s[i].Chinese+s[i].English+s[i].math)/3; } for(i=0;i<N-1;i++) for(j=0;j<N-1-i;j++) if(s[j].avg>s[j+1].avg) { t=s[j]; s[j]=s[j+1]; s[j+1]=t; } for(i=0;i<N-1;i++) { cout<<s[i].name<<" "<<s[i].no<<" "<<s[i].Chinese<<" "; cout<<s[i].English<<" "<<s[i].math<<" "<<s[i].avg<<endl; } system('pause'); return 0; }
|
附:如果对学号(字符串)排序,则需要使用strcmp():
1
| if(strcmp(s[i].no,s[i+1].no)>0)
|
结构变量在函数中的应用
例:定义包含小时、分钟、秒三个成员的时间结构类型,写一转换函数 ,将24小时制的时间转换成12小时制。
分析:
- 函数参数:接受时间,参数为结构类型变量
- 函数返回值:同为结构类型。
- 为方便输出,将是否转换的判断放在主函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include "iostream" #define N 5 using namespace std; struct time { int hour; int minute; int second; }; struct time change(struct time t) { t.hour=t.hour%12; return t; } int main() { struct time t; cin>>t.hour>>t.minute>>t.second; if(t.hour>12) { t=change(t); cout<<t.hour<<":"<<t.minute<<":"<<t.second<<"pm"; } else cout<<t.hour<<":"<<t.minute<<":"<<t.second<<"am"; system('pause'); return 0; }
|
总结
- 结构数组是元素为结构类型变量的数组,对该数组操作时需遵循数组的使用原则,对每个元素操作时要符合结构变量的引用原则;
- 结构变量在输入输出时必须引用到最低级成员;
- 结构变量做函数参数及赋值运算时可整体引用。
附
指针:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct student { char* name; int grade; }p[2]; int main() { char s; gets(s); char* p=s; p=new char[20]; s[i].name=new char[10]; }
|
作业
测试:各类型变量所占内存字节
sizeof(char) = 1;
sizeof(int) = 4;
sizeof(long) = 4;
sizeof(float) = 4;
sizeof(double) = 8.
指针类型的sizeof
指针用于存放地址,它等于计算机内部地址总线的宽度,所以32位计算机中,一个[指针变量]的返回值是4字节(与指针变量的类型无关)。可以预计,在64位系统中指针变量的sizeof等于8。
sizeof(p) = 4;
数组的sizeof
数组的sizeof值等于数组所占用的内存字节数,如:
char a1[] = “abc”;
int a2[3];
sizeof( a1 ); // 结果为4,字符串末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3_4=12(3_sizeof(int))
数组元素个数的求法:
sizeof(a1)/sizeof(*a1);
编程
1
有一组关于学生成绩的信息,编写函数max,该函数返回值为分数最高的学生的信息(包括学号和分数)。再编写主函数对其进行调用并输出最高分者的信息。假设结构类型定义为:
1 2 3 4 5
| struct student { char *num; int score; };
|
提示:num定义为指针类型,注意向其复制内容之前要先为其申请空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| # include <iostream> #define N 256 using namespace std; struct student { char* num; int score; }; struct student max(struct student s[N],int n) { struct student t = {0,s[0].score }; t.num = (char*)malloc(sizeof(char)); for (int i = 0; i < n; i++) { if (s[i].score > t.score) { t.score = s[i].score;
t.num = s[i].num;
} } return t; } int main() { struct student s[N] = {}, t = {}; int n,i; t.num = (char*)malloc(sizeof(char)); cout << "输入学生数:" << endl;
cin >> n; cout << "输入各学生序号及成绩:" << endl; for (i = 0; i < n; i++) { s[i].num = (char*)malloc(sizeof(char)); cin >> s[i].num >> s[i].score; } t=max(s,n); cout << "最高分者序号为" << *t.num <<",分值为:" << t.score << endl; system("pause"); return 0; }
|
标答:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <iostream> using namespace std; #define N 5 struct student { char *num; int score; }; student max(student s[],int n) { student t=s[0]; for(int i=1;i<n;i++) if(s[i].score>t.score) t=s[i]; return t; } int main() { student s[N],maxs; int i; for(i=0;i<N;i++) { s[i].num=new char[10]; cin>>s[i].num>>s[i].score; } maxs=max(s,N); cout<<maxs.num<<' '<<maxs.score<<endl; system("pause"); return 0; }
|
2
编写程序,定义一个日期结构变量,计算某日期是本年度的第几天。提示:为简单起见,可定义一个存放12个月中每个月总天数的数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| # include <iostream> #define N 256 using namespace std; struct time { int month; int date; }; int change(struct time t,bool run) { int i,num=0, a[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }, b[12] = { 31,29,31,30,31,30,31,31,30,31,30,31 }; if (run == 1) for (i = 0; i < t.month-1; i++) num += b[i]; else for (i = 0; i < t.month-1; i++) num += a[i]; num += t.date; return num; } int main() { struct time t; bool run; int num; cout << "今年是不是闰年?(是:1;否:0)" << endl; cin >> run; cout << "输入一日期(月/日)" << endl; cin >> t.month >> t.date; num = change(t, run); cout << "这是今年的第" << num << "天" << endl; system("pause"); return 0; }
|
3
使用结构数组输入10本书的名称和单价,调用函数按照书名的字母顺序序进行排序,在主函数输出排序结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include <iostream> #define N 5 using namespace std; struct book { char name[100]; int price; };
struct book *sort(struct book b[]) { int i, j; struct book a; for(i=0;i<N-1;i++) for (j = 0; j < N - 1 - i; j++) { if (strcmp(b[j].name, b[j+1].name) > 0) { a = b[j]; b[j] = b[j + 1]; b[j + 1] = a; } } struct book* p = b; return p; } int main() { struct book b[N],*p; int i; for (i = 0; i < N; i++) cin >> b[i].name >> b[i].price; p = sort(b); cout << "排序后结果:" << endl; for (i = 0; i < N; i++) cout << p[i].name << ' ' << p[i].price << endl; system("pause"); return 0; }
|