一、结构体
5.1 概述
5.2 结构体的定义
C++ 中的结构体是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。
struct date //日期结构类型:由年、月、日三项组成
{ int year;
int month;
int day;
}; //分号不能少
struct std_info //学生信息结构类型:由学号、姓名、性别和生日组成
{ char no[11];
char name[9];
char sex[3];
struct date birthday;
}; //分号不能少
struct score //成绩结构类型:由学号和三门成绩共4项组成
{ char no[11];
int score1;
int score2;
int score3;
}; //分号不能少
5.3 结构体变量的初始化
struct std_info stud={“2000281021”, “张红“ , "男”, {1983,9,20} };
5.4 访问结构成员
#include<bits/stdc++.h>
struct date
{ int year;
int month;
int day;
};
struct std_info
{ char no[11];
char name[9];
char sex[3];
struct date birthday;
} stud={"2000281021","张红","男",{1983,9,20}};
int main()
{ printf("No: %s\n",stud.no);
printf("Name: %s\n",stud.name);
printf("Sex: %s\n",stud.sex);
printf("Birthday: %d-%d-%d\n",stud.birthday.year,
stud.birthday.month,
stud.birthday.day );
}
5.5 结构体数组 (具有相同结构类型的变量集合)
1、定义一个结构体数组:
#include<bits/stdc++.h>
#define N 4
using namespace std;
struct sct
{ char cno[4];
char cname[20];
int chour;
char teacher[10];
};
int main()
{ struct sct course[N];
int i;
for(i=0;i<N;i++)
{ printf("Enter cnum:");
scanf("%s",course[i].cno);
printf("Enter cname:");
scanf("%s",course[i].cname);
printf("Enter chour:");
scanf("%d",&course[i].chour);
printf("Enter teacher:");
scanf("%s",course[i].teacher);
}
printf("学号\t 课程名\t 学时\t 教师 \n");
for(i=0;i<N;i++)
printf("%-8s%-12s%-8d%-20s\n",course[i].cno,
course[i].cname,
course[i].chour,
course[i].teacher);
}
#include<bits/stdc++.h>
struct date{ int year; int month; int day; };
struct std_info{ char no[11]; char name[9]; char sex[3];
struct date birthday; } ;
struct std_info stud[3]={{"20028102","张明","男",{1982,9,20}},
{"20028105","李明","男",{1983,8,15}},
{"20028112","王琳","女",{1983,3,10}}};
int main()
{ int i;
printf("No.\tName\tSex\tBirthday\n"); /*打印表头*/
for(i=0; i<3; i++) /*输出三个学生的基本情况*/
{ printf("%s\t",stud[i].no);
printf("%s\t",stud[i].name);
printf("%s\t",stud[i].sex);
printf("%d-%d-%d\n",stud[i].birthday.year,
stud[i].birthday.month,
stud[i].birthday.day );
}
}
#include<bits/stdc++.h>
using namespace std;
struct student
{ string name;
int yw,sx;
int total;
} a[100];
int n;
int main()
{ cin>>n;
for(int i=1;i<=n;i++)//对结构体中成员的赋值、取值。
{ cin>>a[i].name>>a[i].yw>>a[i].sx;
a[i].total=a[i].yw+a[i].sx;
}
for(int i=1;i<n;i++)
for (int j=1; j<=n-i;j++) //冒泡排序
if (a[j].total<a[j+1].total) swap(a[j],a[j+1]);
for(int i=1;i<=n;i++)//输出
cout<<a[i].name<<" "<<a[i].yw<<" "<<a[i].sx<<" "<<a[i].total<<endl;
return 0;
}
输入:
#include<bits/stdc++.h>
using namespace std;
struct student
{ string name;
int yw,sx;
int total;
} a[100];
int n;
bool cmp(student a,student b)
{ return a.total>b.total;
}
int main()
{ cin>>n;
for(int i=1;i<=n;i++)//对结构体中成员的赋值、取值。
{ cin>>a[i].name>>a[i].yw>>a[i].sx;
a[i].total=a[i].yw+a[i].sx;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)//输出
cout<<a[i].name<<" "<<a[i].yw<<" "<<a[i].sx<<" "<<a[i].total<<endl;
return 0;
}
输入:
5.6 结构体的扩展
#include<bits/stdc++.h>
using namespace std;
struct worktime // 声明一个结构体类型 worktime 记录学生完成作业的时间
{ int hr,minut,sec; // hr,minut,sec 分别代表时分秒
worktime operator +(const worktime x)const // 对 + 进行重新定义
{ worktime tmp;
tmp.sec = (sec + x.sec) % 60;
tmp.minut = (minut + x.minut + (sec + x.sec) / 60) % 60;
tmp.hr = hr + x.hr + (minut + x.minut + (sec + x.sec) / 60) / 60;
return tmp;
}
};
int main(){
worktime stu,sum;
int n;
cin >> n;
sum.hr = sum.minut = sum.sec = 0;
for(int i = 1; i <= n; i++){
cin >> stu.hr >> stu.minut >> stu.sec;
sum = sum + stu;// 两个结构体 sum 和 stu 通过重载 + 运算符进行加法运算
}
cout <<sum.hr<<"hour"<<sum.minut<<"minute" <<sum.sec<<"second" ;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct stu
{ string name;
int heigh;
int num;
void input()
{ cin >> name >> heigh >> num; }
void output()
{ cout<<name<<" "<<heigh <<" "<<num<<endl; }
} a[110];
int main()
{ int n;
stu maxn;
maxn.heigh = maxn.num = 0;
cin >> n;
for(int i = 1; i <= n; i++)
{ a[i].input();
if(a[i].heigh > maxn.heigh) maxn = a[i];
else if(a[i].heigh == maxn.heigh && a[i].num < maxn.num) maxn = a[i];
}
maxn.output();
return 0;
}
二、共用体
#include<bits/stdc++.h>
using namespace std;
int main()
{ union res // 声明一个共用体 res
{ char rank[5]; // 用等级表示成绩
int x; // 用分数表示成绩
};
struct stu
{ char f; // 代表学生用哪种方式记录成绩
res score; // 定义 score 为共用体
} a[1001];
int n,count = 0, num = 0;
cin >> n;
for(int i = 1; i <= n; i++)
{ cin >> a[i].f;
switch(a[i].f)
{ case 'C':for(int j=0;j<4;j++) cin>>a[i].score.rank[j]; count++;break;
case 'N':cin>>a[i].score.x; num += a[i].score.x;
}
}
cout<<count<<" "<<num/(n-count)<<endl;
return 0;
}
三、结构体练习:
1、近似排序
试题描述
读入一对正整数,将这两个数之间(包括这两个数本身)的所有数按下述特别规则排序后输出,该特别规则是按两数倒过来的值进行比较决定其大小,如30倒过来为3,29倒过来为92,则29大于30.
输入要求
1行两个正整数x和y,用一个空格隔开,1<=x<=y<=10000,y-x<=100
输出要求
包括y-x+1行,每行一个正整数,按两数到过来的值进行比较决定其大小,然后由小到大输出。
输入样例
22 39
输出样例
30
31
22
32
23
33
24
34
25
35
26
36
27
37
28
38
29
2、奖学金 NOIP普及组 2007 第一题
题目描述
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学 排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是:
7 279
5 279
这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是 279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:
5 279
7 279
则按输出错误处理,不能得分。
输入格式
共n+1行。
第1行为一个正整数n(≤300),表示该校参加评选的学生人数。
第2到n+1行,每行有3个用空格隔开的数字,每个数字都在0到100之间。第 j 行的3个数字依次表示学号为j−1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为1~n(恰好是输入数据的行号减1)。
所给的数据都是正确的,不必检验。
输出格式
共5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。
输入输出样例
样例输入一
6
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
样例输出一
6 265
4 264
3 258
2 244
1 237
样例输入二
8
80 89 89
88 98 78
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
样例输出二
8 265
2 264
6 264
1 258
5 258
3、生日相同
描述
在一个有180人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的名字,出生月日。试找出所有生日相同的学生。
输入
第一行为整数n,表示有n个学生,n ≤ 180。此后每行包含一个字符串和两个整数,分别表示学生的名字(名字第一个字母大写,其余小写,不含空格,且长度小于20)和出生月(1 ≤ m ≤ 12)日(1 ≤ d ≤ 31)。名字、月、日之间用一个空格分隔
输出
每组生日相同的学生,输出一行,其中前两个数字表示月和日,后面跟着所有在当天出生的学生的名字,数字、名字之间都用一个空格分隔。对所有的输出,要求按日期从前到后的顺序输出。 对生日相同的名字,按名字从短到长按序输出,长度相同的按字典序输出。如没有生日相同的学生,输出”None”
样例输入
6
Avril 3 2
Candy 4 5
Tim 3 2
Sufia 4 5
Lagrange 4 5
Bill 3 2
样例输出
3 2 Tim Bill Avril
4 5 Candy Sufia Lagrange