自定义类型:结构体
结构体
结构体是一种用户自定义的可用的数据类型,它允许存储不同类型的数据项。
结构体用于表示一条记录,假设您想要跟踪图书馆中书本的动态,您可能需要跟踪每本书的下列属性:
- Title
- Author
- Subject
- Book ID
结构体的声明
为了定义结构体,必须实验struct
语句。struct语句定义了一个包含多个成员的新的数据类型,struct语句的格式如下:
struct name{
member-list
member-list
member-list
......
}variable-list;
name
是结构体名称。
member-list
是标准的变量定义,比如int i;或者float f,或者其他有效的变量定义。
variable-list
结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构体变量。
成员变量
结构体的内部的变量我们称之为成员变量。
如果要访问结构体中的成员,我们可以通过结构体名定义一个结构体的对象,继而通过对象访问结构体中的成员。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
// 自定义类型-结构体
struct book{
string title;
string author;
string subject;
int book_id;
}b;
int main() {
book a;
a.title = "《三体》", a.author = "刘慈欣",
a.subject = "科幻小说", a.book_id = 1;
b.title = "《时间简史》", b.author = "霍金",
b.subject = "宇宙学", b.book_id = 2;
cout << a.title << " " << a.subject << " " << a.author << " " << a.book_id << endl;
cout << b.title << " " << b.subject << " " << b.author << " " << b.book_id << endl;
return 0;
}
运行结果:
《三体》 科幻小说 刘慈欣 1
《时间简史》 宇宙学 霍金 2
结构体的内存对齐方式
- 按最长字节对齐;
- 偶数字节作为起始字节;
#pragma pack()
指定对齐字节
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
// 默认按照最长字节对齐
struct node{
int a; // 4字节
int i; // 4字节
char c; //8字节,虽然char占1字节,但是要按照long long字节数对齐,后面先空着
long long b; // 8字节
};
int main() {
node d;
cout << sizeof(d) << "字节" << endl;
return 0;
}
运行结果:
24字节
实战演练:
定义一个学生结构体,包含三种信息:学号、姓名、成绩
分别创建三个具体的学生对象,分别输入每个学生的学号、姓名、成绩
#include <iostream>
using namespace std;
struct stu_info{
int id;
string name;
double grade;
};
int main() {
stu_info xh, xl, xm;
cin >> xh.id >> xh.name >> xh.grade;
cin >> xl.id >> xl.name >> xl.grade;
cin >> xm.id >> xm.name >> xm.grade;
cout << xh.id << " " << xh.name << " " << xh.grade << endl;
cout << xl.id << " " << xl.name << " " << xl.grade << endl;
cout << xm.id << " " << xm.name << " " << xm.grade << endl;
return 0;
}
运行结果:
1 小黑 99
2 小蓝 88
3 小明 77
1 小黑 99
2 小蓝 88
3 小明 77
结构体数组
对于刚刚我们定义的学生结构体,每次通过学生结构体只能定义一个学生对象,如果现在有很多学生怎么办呢?聪明的同学应该想到了数组,数组可以一次性存储多个元素,不同于之前的数组,现在数组中每个元素都是一个学生,也就是说每个学生都是一个学生结构体类型,这种数组我们称之为结构体数组
实战演练:
打印成绩:
输入n个学生的信息:学号、姓名、成绩,分别打印n个学生的信息
#include <iostream>
using namespace std;
struct stu_info{
int id;
string name;
double grade;
};
int n;
stu_info a[110];
int main() {
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i].id >> a[i].name >> a[i].grade;
for(int i = 1; i <= n; i++) cout << a[i].id << " " << a[i].name << " " << a[i].grade << endl;
return 0;
}
运行结果:
3
1 小河 99
2 小凡 88
3 小王 77
1 小河 99
2 小凡 88
3 小王 77
实战演练:
成绩最高分:
输入n个学生的信息:学号、姓名、语文成绩、英语成绩、数学成绩,找出其中总成绩最大的学生,打印该学生的学生信息
#include <iostream>
using namespace std;
struct stu{
int id;
string name;
double Chinese, English, Math;
double total;
};
int n;
stu a[110];
int main() {
cin >> n;
double maxv = 0;
int maxIndex = 0;
for(int i = 1; i <= n; i++){
cin >> a[i].id >> a[i].name >> a[i].Chinese >> a[i].English >> a[i].Math;
a[i].total = a[i].Chinese + a[i].English + a[i].Math;
if(a[i].total > maxv){
maxv = a[i].total;
maxIndex = i;
}
}
cout << a[maxIndex].id << " " << a[maxIndex].name << " " << a[maxIndex].total << endl;
return 0;
}
运行结果:
3
1 小黑 100 100 100
2 小兰 99 99 99
3 小明 88 88 88
1 小黑 300
实战演练:成绩单
输入n个学生的信息:学号、姓名、语文成绩、数学成绩、英语成绩,按学生总成绩对学生进行降序排序,打印n个学生的学生信息(为了提高编码效率,我们使用sort()对结构体数组进行排序)
#include <iostream>
#include <algorithm>
using namespace std;
struct stu{
int id;
string name;
double Chinese, English, Math;
double total;
};
int n;
stu a[110];
bool cmp(stu A, stu B){
return A.total > B.total;
}
int main() {
cin >> n;
double maxv = 0;
int maxIndex = 0;
for(int i = 1; i <= n; i++){
cin >> a[i].id >> a[i].name >> a[i].Chinese >> a[i].English >> a[i].Math;
a[i].total = a[i].Chinese + a[i].English + a[i].Math;
}
sort(a + 1, a + n + 1, cmp);
for(int i = 1; i <= n; i++){
cout << a[i].id << " " << a[i].name << " " << a[i].total << endl;
}
return 0;
}
运行结果:
3
3 小明 88 88 88
2 小蓝 99 99 99
1 小黑 100 100 100
1 小黑 300
2 小蓝 297
3 小明 264
#学生信息管理系统
写一个学生信息管理系统,学生信息管理系统包括添加、查询、删除、修改学生信息等功能
#include <iostream>
#include <algorithm>
using namespace std;
struct stu{
int id;
string name;
int Class;
};
int n = 3;
stu a[1010] = {
{0, "none", 0},
{1, "小黑", 2},
{2, "小蓝", 2},
{3, "小明", 1}
};
int query(int id){
for(int i = 0; i <= n; i++){
if(a[i].id == id){
return i;
}
}return -1;
}
int main() {
while(1){
cout << "-----------------" << endl;
cout << "student_info:" << endl;
for(int i = 1; i <= n; i++){
cout << "id:" << a[i].id << " name:" << a[i].name
<< " class:" << a[i].Class << endl;
}cout << "-----------------" << endl;
int opt; cin >> opt;
if(opt == 1){
cout << "请输入您想要查询的学生的学号:" << endl;
int id; cin >> id;
int ret = query(id);
if(ret == -1){
cout << "查无此人" << endl;
}
else{
cout << "id:" << a[ret].id << " name:" << a[ret].name
<< " class:" << a[ret].Class << endl;
}
}
else if(opt == 2){
cout << "请输入您想要添加的学生的信息:" << endl;
int id, Class; string name;
cin >> id >> name >> Class;
a[++n].id = id; a[n].name = name; a[n].Class = Class;
}
else if(opt == 3){
cout << "请输入您想要删除的学生的学号:" << endl;
int id; cin >> id;
int ret = query(id);
if(ret == -1){
cout << "查无此人";
}
else{
for(int i = ret + 1; i <= n; i++){
a[i - 1] = a[i];
}
n--;
}
}
else if(opt == 4){
cout << "请输入您想要修改的学生的信息:" << endl;
int id, Class; string name;
cin >> id >> name >> Class;
int ret = query(id);
if(ret == -1){
cout << "查无此人";
}
else{
a[ret].name = name; a[ret].Class = Class;
}
}
}
return 0;
}
联合体
union联合体
union [union tag]
{
member definition;
member definition;
...
member definition;
}[one or more union variables]
union Data
{
int i;
float f;
char str[20];
}data;
现在,Data类型的变量可以存储一个整数、一个浮点数,或者一个字符串。这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。您可以根据需要在一个共同体内使用任何内置的或者用户自定义的数据类型。
union的内存
union Data
{
int i;
float f;
char str[20];
}data;
联合体占用的内存应足够存储共用体中最大的成员。例如,在上面的实例中,Data将占用20个字节的内存空间,因为在各个成员中,字符串所占用的空间是最大的。
访问union的成员
union Data
{
int i;
float f;
char str[20];
}data;
调用之后,我们可以看到联合体的i和f成员的值有损坏,因为最后赋给变量的值占用了内存位置,这也是str成员能够完好输出的原因。联合体在同一时间只能使用一个变量。
#include <iostream>
#include <cstring>
using namespace std;
union Data{
int i;
float f;
char str[20];
};
int main() {
Data d;
d.i = 1;
d.f = 3.14;
// char数组的赋值语法
strcpy(d.str, "hello");
cout << d.i << " " << d.f << " " << d.str;
return 0;
}
运行结果:i, f值损坏
1819043176 1.14314e+027 hello
改成一次使用一个变量
#include <iostream>
#include <cstring>
using namespace std;
union Data{
int i;
float f;
char str[20];
};
int main() {
Data d;
d.i = 1;
cout << d.i << endl;
d.f = 3.14;
cout << d.f << endl;
// char数组的赋值语法
strcpy(d.str, "hello");
cout << d.str << endl;
return 0;
}
运行结果:
1
3.14
hello