Day 06 C++入门 之 结构体

一、结构体的基本概念

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。是一些类型集合组成的一个大类型家庭。

在这个结构体中可以包含多个类型的变量,比如学生类型可以包含学号、姓名、性别、成绩等。里面的学号等叫做这个结构体的成员变量,使用成员变量用:**结构体名.成员名;**或者 结构体指针- > 成员名

二、结构体的定义和使用
1. 定义结构体语法:struct 结构体名 {结构体成员列表}
// 创建一个学生的数据类型(结构体类型)
struct Student
{
    int num;// 成员1-学号
    string name;// 成员2-姓名;
    int age; // 成员3-年龄
    int score;// 成员4-成绩
};

这个结构体的数据类型为:struct Student

2. 通过结构体创建变量的方式有三种:
  1. struct 结构体名 变量名,稍后单独进行赋值
  2. struct 结构体名 变量名 = { 成员1值,成员2值…},在创建变量的时候就进行赋值了
  3. 定义结构体的时候顺便创建变量,有时候找不到,一般不推荐使用。
// 1. struct  结构体名 变量名
struct Student S1;// 创建学生变量1-学生1号
S1.num = 01;// 给成员变量赋值
S1.name = "李四";
S1.age = 20;
S1.score = 77;

// 2. struct  结构体名 变量名 = { 成员1值,成员2值...}
struct Student S2 = {02,"张三",20,88};
// 3. 定义结构体的时候顺便创建变量
struct Student
{
    int num;// 成员1-学号
    string name;// 成员2-姓名;
    int age; // 成员3-年龄
    int score;// 成员4-成绩
}S3;
S3.num = 03;// 给成员变量赋值
S3.name = "懒羊羊";
S3.age = 7;
S3.score = 100;

在C++中,结构体创建变量时,struct 关键字可以省略,但定义不可以省略。通过字符 “ . ” 访问成员

三、结构体数组

作用:将自定义的结构体放入到数组中方便维护。即这个数组的每一个元素都是一个结构体

语法:struct 结构体名 数组名 [ 元素个数 ] = {{结构体1},{结构体2},{结构体3}… };

// 结构体定义
struct Student
{
    int num;// 成员1-学号
    string name;// 成员2-姓名;
    int age; // 成员3-年龄
    int score;// 成员4-成绩
};
// 创建一个结构体数组
struct Student A[3] =
{
    {01,"张三",20,88},
    {02,"李四",20,66},
    {03,"懒羊羊",7,100}
};
// 给结构体数组的元素进行赋值
A[1].name = "喜羊羊";

结构体数组先是一个数组,所以访问的时候通过下标进行索引,其次内部元素是一个结构体,访问内部的成员变量就用 . 进行访问、赋值等操作。

四、结构体指针

作用:通过指针访问结构体中的成员;利用操作符 “ -> ”可以通过结构体指针访问结构体的成员变量。

//创建结构体
...
//创建结构体变量
struct Student S5 = {05,"沸羊羊",20,88};

//通过指针指向结构体变量
struct Student* p = &S5;//创建变量时,关键字struct可以省略,写成Student* p = &s5

// 通过指针访问
p->name = "暖羊羊";

结构体变量本身是一个变量,所以用指针指向时,要用取地址符 &。

五、结构体嵌套结构体

作用:一个结构体的成员可以是另一个结构体

比如:老师本身可以是一个结构体(编号、年龄、名字、所带学生),学生也是一个结构体

//定义学生的结构体
struct Student
{
    int num;// 成员1-学号
    string name;// 成员2-姓名;
    int age; // 成员3-年龄
    int score;// 成员4-成绩
};
//定义老师的结构体
struct teacher
{
    int num;
    int age;
    string name;
    struct Studen s1;//这里要使用学生的结构体,所以要将学生的结构体写在前面
};

//使用
teacher t1;
t1.s1.num =7;//成员变量也是一个结构体,结构体引用成员用 . 来访问,逐层访问即可 

成员变量也是一个结构体,结构体引用成员用 . 来访问,逐层访问即可

六、结构体做函数参数

作用:将结构体作为参数向函数中传递。传递方式有两种:值传递、址传递

//将学生传入到一个参数中,进行打印
struct Student
{
    int num;// 成员1-学号
    string name;// 成员2-姓名;
    int age; // 成员3-年龄
    int score;// 成员4-成绩
};
//1. 值传递
void Print1(struct Student s)
{
    cout<<s.name<<endl;
}
//2. 址传递
void Print2(struct Student* s)
{
    cout<< s->name<<endl;
}
//主函数main()中
struct Student s6 = {06,"美羊羊",20,88};
Print1(s6);
Print2(&s6);

自定义的函数要写在主函数之外,但是定义的结构体可以写在主函数中也可以写在主函数之外,但是二者的定义一定要写在调用之前。

注意:值传递中,形参的修改不影响实参;址传递中,形参的改变会影响实参,形参改变,实参也会改变。

七、结构体中 const 使用场景

作用:用const来防止误操作。值传递不会影响,但是址传递会影响。

void Print2(const struct Student* s)//加const,就是只读不写
{
    cout<< s->name<<endl;
}
struct Student
{
    int num;// 成员1-学号
    string name;// 成员2-姓名;
    int age; // 成员3-年龄
    int score;// 成员4-成绩
};
struct Student s7 = {07,"小灰灰",3,88};
//通过函数打印信息
Print2(&s7);

值传递是进行拷贝赋值的,一般会占用空间,造成浪费,所以更推荐址传递,这样就减少了很多空间的浪费,但是要注意误操作(不小心改值),这个时候就可以用const来防止误操作,在函数定义时的参数列表中加上const。

例子1:

每名老师带5个学生,总共3个老师,设计学生和老师的结构体,老师(姓名、5个学生的数组),学生(姓名、成绩)。创建数组存放3名老师,通过函数给每个老师及其所带的学生的成绩赋值,最终打印出老师数据以及老师所带学生的数据。

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

//创建学生的结构体
struct Student
{
    string sName;
    int score;
};

//创建老师的结构体
struct teacher
{
    string tName;
    struct Student sA[5];
};

//信息赋值
void giving(struct teacher B[], int n)
{
    string nameSeed = "ABCDE";
    //给老师赋值
    for (int i = 0; i < n; i++)
    {
        B[i].tName = "teacher_";
        B[i].tName += nameSeed[i];//string类型可以通过加法拼接
        //给学生赋值
        for (int j = 0; j < 5; j++)
        {
            B[i].sA[j].sName = "Student_";
            B[i].sA[j].sName += nameSeed[j];
            //int random = rand()%60+40;//0+40~59+40
            int random = rand()%61+40;//0+40~60+40
            B[i].sA[j].score = random;
        }
    }
}

//打印信息函数
void print1(struct teacher B[], int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << B[i].tName << endl;
            for (int j = 0; j < 5; j++)
            {
                //\t,转义字符,让学生的缩进一下 
                cout <<"\t"<< B[i].sA[j].sName << "    " << B[i].sA[j].score << endl;
            }
    }
}

int main()
{
    //随机数种子
    srand((unsigned int)time(NULL));//让随机数每次都不一样
    //创建3个老师的数组
    struct teacher A[3];
    int len = sizeof(A) / sizeof(A[0]);
    //通过函数给老师赋值以及给学生赋值
    giving(A, len);//数组名是一个地址

    //打印老师及所带学生的信息
    print1(A,len);
    system("pause");
    return 0;

}

数组名是一个地址,是一个变量,表示传的是地址,是址传递,形参的改变就是实参的改变

在这里插入图片描述

例子2:

设计一个羊村结构体,羊村(姓名,年龄,性别),创建结构体数组,数组中存放5名羊羊,通过冒泡排序,将数组中的羊羊们按照年龄进行升序排序,最终打印排序后的结果。

//定义结构体
struct goat
{
    string name;
    int age;
    string sex;
};
//排序函数
void bubbleSort( struct goat A[], int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = 0; j < n - i - 1; j++)
        {
            if (A[j].age > A[j + 1].age)
            {
                struct goat temp = A[j];
                A[j] = A[j + 1];
                A[j + 1] = temp;
            }
        }
    }
}

int main()
{
    //创建变量并赋值
    struct goat B[5] =
    {
        {"沸羊羊",13,"男"},
        {"懒羊羊",10,"男"},
        {"喜羊羊",13,"男"},
        {"美羊羊",12,"女"},
        {"暖羊羊",13,"女"},
    };
    //计算数组长度
    int len = sizeof(B) / sizeof(B[0]);
    cout << "排序前" << endl;
    for (int i = 0; i < len; i++)
    {
        cout << B[i].name << "   " << B[i].age << "   " << B[i].sex << endl;
    };
    //调用函数进行排序
    bubbleSort(B, len);
    cout << "排序后" << endl;
    for (int i = 0; i < len; i++)
    {
        cout << B[i].name << "   " << B[i].age << "   " << B[i].sex << endl;
    };
    system("pause");
    return 0;
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐