【C++コア】構造体と共用体の詳細解説

1. 構造

1.1 構造の基本概念

構造体はユーザーに属しますカスタムデータ型、ユーザーがさまざまなデータ型を保存できるようにします

1.2 構造体の定義と使用法

文法: struct 结构体名 { 结构体成员列表 };

構造体を通じて変数を作成するには、次の 3 つの方法があります。

  • struct 構造体名 変数名
  • struct 構造体名 変数名 = { メンバー 1 の値、メンバー 2 の値...}
  • 構造体を定義するときについでに変数を作成する

例:

#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student
{
    
    
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
}stu3; //结构体变量创建方式3 


int main() {
    
    

	//结构体变量创建方式1
	struct student stu1; //struct 关键字可以省略

	stu1.name = "张三";
	stu1.age = 18;
	stu1.score = 100;
	cout << "姓名:" << stu1.name << " 年龄:" << stu1.age  << " 分数:" << stu1.score << endl;

	//结构体变量创建方式2
	struct student stu2 = {
    
     "李四",19,60 };
	cout << "姓名:" << stu2.name << " 年龄:" << stu2.age  << " 分数:" << stu2.score << endl;

	stu3.name = "王五";
	stu3.age = 18;
	stu3.score = 80;
	cout << "姓名:" << stu3.name << " 年龄:" << stu3.age  << " 分数:" << stu3.score << endl;

	return 0;
}

まとめ 1: 構造体を定義するときのキーワードは struct であり、省略できません
まとめ 2: 構造体変数を作成するときのキーワード struct は省略できます
まとめ 3: 構造体変数は演算子 ''.'' を使用してメンバーにアクセスします

1.3 構造体配列

機能:メンテナンスを容易にするためにカスタム構造を配列に配置します。

文法: struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }

例:

#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student
{
    
    
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
}

int main() {
    
    
	
	//结构体数组
	struct student arr[3]=
	{
    
    
		{
    
    "张三",18,80 },
		{
    
    "李四",19,60 },
		{
    
    "王五",20,70 }
	};

	for (int i = 0; i < 3; i++)
	{
    
    
		cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 分数:" << arr[i].score << endl;
	}

	system("pause");
	return 0;
}

1.4 構造体ポインタ

機能:ポインターを介して構造体のメンバーにアクセスし、演算子を使用して-> 構造体のポインターを介して構造体のプロパティにアクセスします。

例:

#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student
{
    
    
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};


int main() {
    
    
	
	struct student stu = {
    
     "张三",18,100, };
	
	struct student * p = &stu;
	
	p->score = 80; //指针通过 -> 操作符可以访问成员

	cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;

	return 0;
}

概要: 構造体ポインタは、-> 演算子を介して構造体のメンバーにアクセスできます。

1.5 構造の入れ子構造

役割:構造体のメンバーは別の構造体になることができます

例:各教師が生徒を指導し、教師の構造に生徒の構造を記録します。

例:

#include<iostream>
#include<string>

using namespace std;

//学生结构体定义
struct student
{
    
    
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

//教师结构体定义
struct teacher
{
    
    
    //成员列表
	int id; //职工编号
	string name;  //教师姓名
	int age;   //教师年龄
	struct student stu; //子结构体 学生
};


int main() {
    
    

	struct teacher t1;
	t1.id = 10000;
	t1.name = "老王";
	t1.age = 40;

	t1.stu.name = "张三";
	t1.stu.age = 18;
	t1.stu.score = 100;

	cout << "教师 职工编号: " << t1.id << " 姓名: " << t1.name << " 年龄: " << t1.age << endl;
	
	cout << "辅导学员 姓名: " << t1.stu.name << " 年龄:" << t1.stu.age << " 考试分数: " << t1.stu.score << endl;

	return 0;
}

概要:構造体では、実際的な問題を解決するために別の構造体をメンバーとして定義できます。

1.6 関数パラメータとしての構造体

役割:構造体をパラメータとして関数に渡します。

配送方法は2種類ございます值传递地址传递

例:

#include<iostream>
#include<string>

using namespace std;

//学生结构体定义
struct student
{
    
    
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

//值传递
void printStudent(student stu )
{
    
    
	stu.age = 28;
	cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;
}

//地址传递
void printStudent2(student *stu)
{
    
    
	stu->age = 28;
	cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age  << " 分数:" << stu->score << endl;
}

int main() {
    
    

	student stu = {
    
     "张三",18,100};
	//值传递
	printStudent(stu);
	cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl;

	cout << endl;

	//地址传递
	printStudent2(&stu);
	cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;

	return 0;
}

概要: main 関数のデータを変更したくない場合は値で渡し、それ以外の場合はアドレスで渡します。

1.7 構造体での const の使用シナリオ

機能: const を使用して誤操作を防止します

例:

#include<iostream>
#include<string>
using namespace std;

//学生结构体定义
struct student
{
    
    
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

//const使用场景
void printStudent(const student *stu) //加const防止函数体中的误操作
{
    
    
	//stu->age = 100; //操作失败,因为加了const修饰
	cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;

}

int main() {
    
    

	student stu = {
    
     "张三",18,100 };

	printStudent(&stu);
	
	return 0;
}

1.8 構造の場合

1.8.1 ケース 1

ケースの説明:

この学校では卒業制作を行っており、各教師が5人の生徒を指導し、合計3人の教師がいます。

  • 学生と教師の構造を設計します。教師の構造には、教師の名前と 5 人の学生をメンバーとして保存する配列があります。
  • 生徒のメンバーには名前とテストのスコアがあり、3 人の教師を保存する配列を作成し、関数を通じて各教師とその教師が連れてきた生徒に値を割り当てます。
  • 最後に、教師データと教師が持参した生徒データをプリントアウトします。

例:

#include<iostream>
#include<string>
#include<ctime>
using namespace std;

struct Student
{
    
    
	string name;
	int score;
};
struct Teacher
{
    
    
	string name;
	Student sArray[5];
};

void allocateSpace(Teacher tArray[] , int len)
{
    
    
	string tName = "教师";
	string sName = "学生";
	string nameSeed = "ABCDE";
	for (int i = 0; i < len; i++)
	{
    
    
		tArray[i].name = tName + nameSeed[i];
		
		for (int j = 0; j < 5; j++)
		{
    
    
			tArray[i].sArray[j].name = sName + nameSeed[j];
			tArray[i].sArray[j].score = rand() % 61 + 40;
		}
	}
}

void printTeachers(Teacher tArray[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		cout << tArray[i].name << endl;
		for (int j = 0; j < 5; j++)
		{
    
    
			cout << "\t姓名:" << tArray[i].sArray[j].name << " 分数:" << tArray[i].sArray[j].score << endl;
		}
	}
}

int main() {
    
    

	srand((unsigned int)time(NULL)); //随机数种子 头文件 #include <ctime>

	Teacher tArray[3]; //老师数组

	int len = sizeof(tArray) / sizeof(Teacher);

	allocateSpace(tArray, len); //创建数据

	printTeachers(tArray, len); //打印数据

	return 0;
}

1.8.2 ケース 2

ケースの説明:

メンバー名、年齢、性別を含むヒーローの構造を設計し、構造の配列を作成し、配列に 5 人のヒーローを保存します。

バブルソートアルゴリズムを通じて、配列内のヒーローを年齢に従って昇順にソートし、最後にソート結果を出力します。

5人の英雄の情報は以下の通りです。

		{"刘备",23,"男"},
		{"关羽",22,"男"},
		{"张飞",20,"男"},
		{"赵云",21,"男"},
		{"貂蝉",19,"女"},

例:

#include<iostream>
#include<string>
using namespace std;

//英雄结构体
struct hero
{
    
    
	string name;
	int age;
	string sex;
};
//冒泡排序
void bubbleSort(hero arr[] , int len)
{
    
    
	for (int i = 0; i < len - 1; i++)
	{
    
    
		for (int j = 0; j < len - 1 - i; j++)
		{
    
    
			if (arr[j].age > arr[j + 1].age)
			{
    
    
				hero temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
//打印数组
void printHeros(hero arr[], int len)
{
    
    
	for (int i = 0; i < len; i++)
	{
    
    
		cout << "姓名: " << arr[i].name << " 性别: " << arr[i].sex << " 年龄: " << arr[i].age << endl;
	}
}

int main() {
    
    

	struct hero arr[5] =
	{
    
    
		{
    
    "刘备",23,"男"},
		{
    
    "关羽",22,"男"},
		{
    
    "张飞",20,"男"},
		{
    
    "赵云",21,"男"},
		{
    
    "貂蝉",19,"女"},
	};

	int len = sizeof(arr) / sizeof(hero); //获取数组元素个数

	bubbleSort(arr, len); //排序

	printHeros(arr, len); //打印

	system("pause");
	return 0;
}

二. 共用体(union)

Union はUnionであり、特殊なクラスです。キーワード Union によって定義されるユニオンは、複数のデータ メンバーを持つことができます。例えば

union Token{
    
    
   char cval;
   int ival;
   double dval;
};

上記のコードは、3 つのデータ メンバーを含む Token という名前のユニオンを定義します。

2.1 組合の利点

組合のメリットは以下の通りです。

1. セグメント化された使用
2. スペースの節約: 一定期間内に同時に出現しない複数の変数については、ユニオンを使用してメモリスペースを節約します。
3. 強力な型変換の代わりに。例えば:ネットワーク プログラミングでは、パラメーターの形式でさまざまな関数に渡されるデータ文字列を渡すためによく使用されます。したがって、共用体を使用すると、共用体が関数ポインターでいっぱいになり、同時に異なる関数を指すようになります。したがって、プログラミング効率が向上し、スペースが節約されます。

2.2 結合の限界

Union 内のオブジェクト メンバーはコンストラクター、デストラクター、およびオーバーロードされたコピー代入演算子を持つことができません。また、オブジェクト メンバーのオブジェクト メンバーがこれらを持つことはできません。同様に、
Union は継承できません。

2.3 ユニオンの場合

Union を使用してグレード情報を保存し、出力します

#include <iostream>
using namespace std;

class ExamInfo {
    
    
    
public:
    ExamInfo(string n, char g):name(n),mode(GRADE),grade(g){
    
    }
    ExamInfo(string n, bool p):name(n),mode(PASS),grade(p){
    
    }
    ExamInfo(string n, int p):name(n),mode(PERCENTAGE),grade(p){
    
    }

    void show();

private:
    string name;
    enum {
    
    GRADE, PASS, PERCENTAGE} mode;
    union {
    
    
        char grade;
        bool pass;
        int percent;
    };

};

void ExamInfo::show() {
    
    
    cout << name << ": ";

    switch(mode) {
    
    
        case GRADE: cout << grade;break;
        case PASS: cout << pass ? "PASS" : "FAIL";break;
        case PERCENTAGE: cout << percent;break;
    }

    cout << endl;
}

int main() {
    
    

    ExamInfo examInfo1("English", 'B');
    ExamInfo examInfo2("Calculus", true);
    ExamInfo examInfo3("C++ Programming", 85);

    examInfo1.show();       // English: B
    examInfo2.show();       // Calculus: 1
    examInfo3.show();       // C++ Programming: 85
    
    return 0;
}

おすすめ

転載: blog.csdn.net/cui_yonghua/article/details/131364481