C++ 黑马程序员-笔记(C++基础入门)

C++ B站黑马程序员

cpp基础入门

Hello World!

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

int main()
{
    printf("Hello world!\n");
    cout << "Hello World!!!" << endl;
    system("pause");
    return 0;
}

Annotation

  • 单行注释
// 单行注释
  • 多行注释
/*
       给代码段或者函数进行注释
   */

Variable

变量

  • 数据类型 变量名;

常量

  • #define 常量名 常量值

  • const 数据类型 常量名 = 常量值
    通常在变量定义前加关键字 const,修饰该变量为常量,不可修改。

关键字(标识符)

  • 关键字不能用于变量的命名。
  • 标识符命名规则
    1. 标识符不能是关键字
    2. 标识符只能由字母、数字、下滑线组成
    3. 第一个字符必须为字母或下划线
    4. 标识符中字母区分大小写

Data Type

数据类型:整型、浮点型(实型)、字符型、字符串类型、布尔类型 bool

整型

数据类型占用空间取值范围
short(短整型)2字节(-2^15 ~ 2^15-1)
int(整型)4字节(-2^31 ~ 2^31-1)
long(长整形)Windows为4字节,Linux为4字节(32位),8字节(64位)(-2^31 ~ 2^31-1)
long long(长长整形)8字节(-2^63 ~ 2^63-1)

Relevant:[[sizeof]]

浮点型 (实型)

  1. 单精度 float
  2. 双精度 double
数据类型占用空间有效数字范围
float4字节7位有效数字
double8字节15~16位有效数字

示例:

int main() {

    float f1 = 3.14f;
    double d1 = 3.14;

    cout << f1 << endl;
    cout << d1<< endl;
    cout << "float  sizeof = " << sizeof(f1) << endl;
    cout << "double sizeof = " << sizeof(d1) << endl;

    //科学计数法
    float f2 = 3e2; // 3 * 10 ^ 2
    cout << "f2 = " << f2 << endl;
    
    float f3 = 3e-2;  // 3 * 0.1 ^ 2
    cout << "f3 = " << f3 << endl;

    system("pause");
    return 0;
}

字符型

语法:char ch = 'a';

  • 在显示字符型变量时,用单引号将字符括起来,不要用双引号
  • 单引号内只能有一个字符,不可以是字符串
  • C 和 cpp中字符型变量只占用1个字节 ( 1 B)。
  • 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII 编码放入到存储单元

示例:

int main() {
    char ch = 'a';
    cout << ch << endl;
    cout << sizeof(char) << endl;
    
    //ch = "abcde"; //错误,不可以用双引号
    //ch = 'abcde'; //错误,单引号内只能引用一个字符
    
    cout << (int)ch << endl;  //查看字符a对应的ASCII码
    ch = 97; //可以直接用ASCII给字符型变量赋值
    cout << ch << endl;
  
    system("pause");
    return 0;
}

Relevant:[[ASCII]]、[[转义字符]]

字符串型

  1. C 风格字符串char 变量名[] = "字符串值"
  2. cpp风格字符串string 变量名 = "字符串值"
  • C 风格的字符串要用双引号括起来
  • cpp风格字符串,需要加入头文件 #include<string>

布尔类型 bool

  • bool 类型只有两个值:

    • true — 真(本质是1)
    • false — 假(本质是0)
  • bool 类型占1个字节大小

数据的输入

int main(){
    //整型输入
    int a = 0;
    cout << "请输入整型变量:" << endl;
    cin >> a;
    cout << a << endl; 

    //浮点型输入
    double d = 0;
    cout << "请输入浮点型变量:" << endl;
    cin >> d;
    cout << d << endl;

    //字符型输入
    char ch = 0;
    cout << "请输入字符型变量:" << endl;
    cin >> ch;
    cout << ch << endl;

    //字符串型输入
    string str;
    cout << "请输入字符串型变量:" << endl;
    cin >> str;
    cout << str << endl;

    //布尔类型输入
    bool flag = true;
    cout << "请输入布尔型变量:" << endl;
    cin >> flag;
    cout << flag << endl;
    system("pause");
    return EXIT_SUCCESS;
}

Operator

运算符类型作用
算术运算符用于处理四则运算
赋值运算符用于将表达式的值赋给变量
比较运算符用于表达式的比较,并返回一个真值或假值
逻辑运算符用于根据表达式的值返回真值或假值

算术运算符

运算符术语示例结果
+正号+33
-负号-3-3
+10 + 515
-10 - 55
*10 * 550
/10 / 52
%取模(取余)10 % 31
++前置递增a=2; b=++a;a=3; b=3;
++后置递增a=2; b=a++;a=3; b=2;
前置递减a=2; b=–a;a=1; b=1;
后置递减a=2; b=a–;a=1; b=2;
  • 加减乘除
    • 两个整数相除结果依然是整数
    • 除数不可以为0
    • 两个小数可以相除
  • 取模
    • 取模运算时,除数也不能为0
    • 两个小数不可以取模,只有整型变量可以进行取模运算

赋值运算符

运算符术语示例结果
=赋值a=2; b=3;a=2; b=3;
+=加等于a=0; a+=2;a=2;
-=减等于a=5; a-=3;a=2;
*=乘等于a=2; a*=2;a=4;
/=除等于a=4; a/=2;a=2;
%=模等于a=3; a%2;a=1;

比较运算符

运算符术语示例结果
==相等于4 == 30
!=不等于4 != 31
<小于4 < 30
>大于4 > 31
<=小于等于4 <= 30
>=大于等于4 >= 11
  • C 和 cpp 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示。

逻辑运算符

运算符术语示例结果
!!a如果a为假,则!a为真; 如果a为真,则!a为假。
&&a && b如果a和b都为真,则结果为真,否则为假。
||a || b如果 a 和 b 有一个为真,则结果为真,二者都为假时,结果为假。

Program Flow Structure

C/cpp支持最基本的三种程序运行结构:

  • 顺序结构:程序按顺序执行,不发生跳转
  • 选择结构:依据条件是否满足,有选择的执行相应功能
  • 循环结构:依据条件是否满足,循环多次执行某段代

选择结构

if 语句

单行格式 if 语句

语法:if(条件){ 条件满足执行的语句 }

  • if 条件表达式后不要加分号

多行格式 if 语句

语法:if(条件){ 条件满足执行的语句 }else{ 条件不满足执行的语句 };

多条件的 if 语句

语法:if(条件1){ 条件1满足执行的语句 }else if(条件2){条件2满足执行的语句}... else{ 都不满足执行的语句}

嵌套 if 语句

在 if 语句中,可以嵌套使用 if 语句,达到更精确的条件判断

三目运算符

语法:表达式1 ? 表达式2 :表达式3

  • 如果表达式1的值为真,执行表达式2,并返回表达式2的结果;
  • 如果表达式1的值为假,执行表达式3,并返回表达式3的结果。

示例:

int main() {
    int a = 10;
    int b = 20;
    int c = 0;

    c = a > b ? a : b;
    cout << "c = " << c << endl;
  
    //cpp中三目运算符返回的是 变量 ,可以继续赋值
    (a > b ? a : b) = 100;
    
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
    system("pause");
    return 0;
}
  • 总结:和 if 语句比较,三目运算符优点是短小整洁,缺点是如果用嵌套,结构不清晰
switch 语句
switch(表达式)
{
    case 结果1:执行语句;break;
    case 结果2:执行语句;break;
    ...
    default:执行语句;break;
}
  • switch 语句中表达式类型只能是整型或者字符型
  • case 里如果没有 break,那么程序会一直向下执行
  • 与 if 语句比,对于多条件判断时,switch 的结构清晰,执行效率高,缺点是 switch 不可以判断区间

循环结构

while 循环语句

语法: while(循环条件){ 循环语句 }

  • 在执行循环语句时候,程序必须提供跳出循环的出口,否则出现死循环
do…while 循环语句

语法: do{ 循环语句 } while(循环条件);

  • 与 while 的区别在于 do…while 会先执行一次循环语句,再判断循环条件
for 循环语句

语法: for(起始表达式;条件表达式;末尾循环体) { 循环语句; }

int main() {
    for (int i = 0; i < 10; i++)
    {
        cout << i << endl;
    }
    system("pause");
    return 0;
}
  • for 循环中的表达式,要用分号进行分隔
  • for 循环结构比较清晰,比较常用

跳转语句

break 语句

break 使用的时机:

  • 出现在switch条件语句中,作用是终止case并跳出switch
  • 出现在循环语句中,作用是跳出当前的循环语句
  • 出现在嵌套循环中,跳出最近的内层循环语句
continue 语句

循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环

  • continue 并没有使整个循环终止,而 break 会跳出循环
goto 语句

语法: goto 标记;

  • 可以无条件跳转语句
  • 如果标记的名称存在,执行到 goto 语句时,会跳转到标记的位置

示例:

int main() {
    cout << "1" << endl;
    
    goto FLAG;
    
    cout << "2" << endl;
    cout << "3" << endl;
    cout << "4" << endl;

    FLAG:

    cout << "5" << endl;
    
    system("pause");
    return 0;
}
  • 在程序中不建议使用 goto 语句,以免造成程序流程混乱

Array

特点1:数组中的每个数据元素都是相同的数据类型
特点2:数组是由连续的内存位置组成的

一维数组

一维数组定义的三种方式:

  1. 数据类型 数组名[ 数组长度 ];
  2. 数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};
  3. 数据类型 数组名[ ] = { 值1,值2 ...};

示例

int main() {

    //定义方式1
    //数据类型 数组名[元素个数];
    int score[10];
    
    //利用下标赋值
    score[0] = 100;
    score[1] = 99;
    score[2] = 85;
    
    //利用下标输出
    cout << score[0] << endl;
    cout << score[1] << endl;
    cout << score[2] << endl;
    
    //第二种定义方式
    //数据类型 数组名[元素个数] =  {值1,值2 ,值3 ...};
    //如果{}内不足10个数据,剩余数据用0补全
    int score2[10] = { 100, 90,80,70,60,50,40,30,20,10 };
    
    //逐个输出
    //cout << score2[0] << endl;
    //cout << score2[1] << endl;
    //一个一个输出太麻烦,因此可以利用循环进行输出
    for (int i = 0; i < 10; i++)
    {
        cout << score2[i] << endl;
    }
    
    //定义方式3
    //数据类型 数组名[] =  {值1,值2 ,值3 ...};
    int score3[] = { 100,90,80,70,60,50,40,30,20,10 };
    for (int i = 0; i < 10; i++)
    {
        cout << score3[i] << endl;
    }
    
    system("pause");
    return 0;
}
  • 数组名的命名规范与变量名命名规范一致,不要和变量重名
  • 数组中下标是从0开始索引

一维数组数组名

  1. 可以统计整个数组在内存中的长度
  2. 可以获取数组在内存中的首地址

示例:

int main() {
    //数组名用途

    //1、可以获取整个数组占用内存空间大小
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    cout << "整个数组所占内存空间为: " << sizeof(arr) << endl;
    cout << "每个元素所占内存空间为: " << sizeof(arr[0]) << endl;
    cout << "数组的元素个数为: " << sizeof(arr) / sizeof(arr[0]) << endl;

    //2、可以通过数组名获取到数组首地址
    cout << "数组首地址为: " << (int)arr << endl;
    cout << "数组中第一个元素地址为: " << (int)&arr[0] << endl;
    cout << "数组中第二个元素地址为: " << (int)&arr[1] << endl;
    //arr = 100; 错误,数组名是常量,因此不可以赋值

    system("pause");
    return 0;
}
  • 数组名是常量,不可以赋值
  • 直接打印数组名,可以查看数组所占内存的首地址
  • 对数组名进行 sizeof,可以获取整个数组占内存空间的大小

Relevant: [[冒泡排序]]

二维数组

二维数组定义的四种方式

  1. 数据类型 数组名[ 行数 ][ 列数 ];
  2. 数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };
  3. 数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};
  4. 数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};
  • 以上4种定义方式,利用第二种更加直观,提高代码的可读性

示例:

int main() {
    //方式1  
    //数组类型 数组名 [行数][列数]
    int arr[2][3];
    arr[0][0] = 1;
    arr[0][1] = 2;
    arr[0][2] = 3;
    arr[1][0] = 4;
    arr[1][1] = 5;
    arr[1][2] = 6;

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    
    //方式2
    //数据类型 数组名[行数][列数] = { {数据1,数据2 } ,{数据3,数据4 } };
    int arr2[2][3] =
    {
        {1,2,3},
        {4,5,6}
    };
    
    //方式3
    //数据类型 数组名[行数][列数] = { 数据1,数据2 ,数据3,数据4  };
    int arr3[2][3] = { 1,2,3,4,5,6 };
    
    //方式4
    //数据类型 数组名[][列数] = { 数据1,数据2 ,数据3,数据4  };
    int arr4[][3] = { 1,2,3,4,5,6 };
    
    system("pause");
    return 0;
}
  • 在定义二维数组时,如果初始化了数据,可以省略行数

二维数组数组名

  • 查看二维数组所占内存空间
  • 获取二维数组首地址

示例:

int main() {
    //二维数组数组名
    int arr[2][3] =
    {
        {1,2,3},
        {4,5,6}
    };
    cout << "二维数组大小: " << sizeof(arr) << endl;
    cout << "二维数组一行大小: " << sizeof(arr[0]) << endl;
    cout << "二维数组元素大小: " << sizeof(arr[0][0]) << endl;
    cout << "二维数组行数: " << sizeof(arr) / sizeof(arr[0]) << endl;
    cout << "二维数组列数: " << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;
    //地址
    cout << "二维数组首地址:" << arr << endl;
    cout << "二维数组第一行地址:" << arr[0] << endl;
    cout << "二维数组第二行地址:" << arr[1] << endl;
    cout << "二维数组第一个元素地址:" << &arr[0][0] << endl;
    cout << "二维数组第二个元素地址:" << &arr[0][1] << endl;

    system("pause");
    return 0;
}
  • 二维数组名就是这个数组的首地址(使用取地址符号&)
  • 对二维数组名进行 sizeof 时,可以获取整个二维数组占用的内存空间大小

Function

函数的定义

函数的定义一般主要有 5 个步骤

  1. 返回值类型
  2. 函数名
  3. 参数表列
  4. 函数体语句
  5. return 表达式

语法:

返回值类型 函数名 (参数列表)
{
    函数体语句 
    return表达式
}

示例:定义一个加法函数,实现两个数相加

//函数定义
int add(int num1, int num2)
{
    int sum = num1 + num2;
    return sum;
}

函数的调用

语法: 函数名(参数)

  • 函数定义里小括号内称为形参,函数调用时传入的参数称为实参

值传递

  • 所谓值传递,就是函数调用时实参将数值传入给形参
  • 值传递时,如果形参发生,并不会影响实参

示例:

void swap(int num1, int num2)
{
    cout << "交换前:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;

    int temp = num1;
    num1 = num2;
    num2 = temp;

    cout << "交换后:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;
    //return ; 当函数声明时候,不需要返回值,可以不写return
}

int main() {
    int a = 10;
    int b = 20;

    swap(a, b);

    cout << "mian中的 a = " << a << endl;
    cout << "mian中的 b = " << b << endl;

    system("pause");
    return 0;
}

函数的常见样式

常见的函数样式有 4种

  1. 无参无返
  2. 有参无返
  3. 无参有返
  4. 有参有返

示例:

//函数常见样式

//1、 无参无返
void test01()
{
    //void a = 10; //无类型不可以创建变量,原因无法分配内存
    cout << "this is test01" << endl;
    //test01(); 函数调用
}

//2、 有参无返
void test02(int a)
{
    cout << "this is test02" << endl;
    cout << "a = " << a << endl;
}

//3、无参有返
int test03()
{
    cout << "this is test03 " << endl;
    return 10;
}

//4、有参有返
int test04(int a, int b)
{
    cout << "this is test04 " << endl;
    int sum = a + b;
    return sum;
}

函数的声明

告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

  • 函数的声明可以多次,但是函数的定义只能有一次

示例:

//声明可以多次,定义只能一次

//声明
int max(int a, int b);
int max(int a, int b);

//定义
int max(int a, int b)
{
    return a > b ? a : b;
}

int main() {
    int a = 100;
    int b = 200;
  
    cout << max(a, b) << endl;
    
    system("pause");
    return 0;
}

函数的分文件编写

函数分文件编写一般有 4 个步骤

  1. 创建后缀名为.h 的头文件
  2. 创建后缀名为. cpp的源文件
  3. 在头文件中写函数的声明
  4. 在源文件中写函数的定义

示例:

//swap.h文件

#include<iostream>

using namespace std;
//实现两个数字交换的函数声明
void swap(int a, int b);
//swap.cpp文件

#include "swap.h"

void swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
}
//main函数文件

#include "swap.h"   //双引号表示自定义的头文件
int main() {
    int a = 100;
    int b = 200;
    
    swap(a, b);
    
    system("pause");
    return 0;
}

Pointer

指针变量的定义和使用

指针变量定义语法: 数据类型 * 变量名;

示例:

int main() {
    //1、指针的定义
    int a = 10; //定义整型变量a
    //指针定义语法: 数据类型 * 变量名 ;
    int * p;
    //指针变量赋值
    p = &a; //指针指向变量a的地址
    cout << &a << endl; //打印数据a的地址
    cout << p << endl;  //打印指针变量p

    //2、指针的使用
    //通过*操作指针变量指向的内存
    cout << "*p = " << *p << endl;
    
    system("pause");
    return 0;
}

指针变量和普通变量的区别

  • 普通变量存放的是数据,指针变量存放的是地址
  • 指针变量可以通过" * "操作符,操作指针变量指向的内存空间,这个过程称为解引用

总结:

  • 我们可以通过 & 符号获取变量的地址
  • 利用指针可以记录地址
  • 对指针变量解引用,可以操作指针指向的内存

指针所占内存空间

示例:

int main() {
    int a = 10;
    int * p;
    p = &a; //指针指向数据a的地址

    cout << *p << endl; //* 解引用
    cout << sizeof(p) << endl;
    cout << sizeof(char *) << endl;
    cout << sizeof(float *) << endl;
    cout << sizeof(double *) << endl; 

    system("pause");  
    return 0;
}
  • 所有指针类型在32位操作系统下是4个字节

空指针和野指针

空指针:指针变量指向内存中编号为0 的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的

示例1:空指针

int main() {
    //指针变量p指向内存地址编号为0的空间
    int * p = NULL;
    //访问空指针报错
    //内存编号0 ~255为系统占用内存,不允许用户访问
    cout << *p << endl;

    system("pause");
    return 0;
}

野指针:指针变量指向非法的内存空间

示例2:野指针

int main() {
    //指针变量p指向内存地址编号为0x1100的空间
    int * p = (int *)0x1100;

    //访问野指针报错
    cout << *p << endl;

    system("pause");
    return 0;
}
  • 空指针和野指针都不是我们申请的空间,因此不要访问

const 修饰指针

const 修饰指针有三种情况

  1. const 修饰指针 — 常量指针
  2. const修饰常量 — 指针常量
  3. const 即修饰指针,又修饰常量

示例:

int main() {
    int a = 10;
    int b = 10;

    //const修饰的是指针,指针指向可以改,指针指向的值不可以更改
    const int * p1 = &a;
    p1 = &b; //正确
    //*p1 = 100;  报错

    //const修饰的是常量,指针指向不可以改,指针指向的值可以更改
    int * const p2 = &a;
    //p2 = &b; //错误
    *p2 = 100; //正确

    //const既修饰指针又修饰常量
    const int * const p3 = &a;
    //p3 = &b; //错误
    //*p3 = 100; //错误

    system("pause");
    return 0;
}
  • 看 const 右侧紧跟着的是指针还是常量, 是指针就是常量指针,是常量就是指针常量

指针和数组

示例:

int main() {
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int * p = arr;  //指向数组的指针

    cout << "第一个元素: " << arr[0] << endl;
    cout << "指针访问第一个元素: " << *p << endl;

    for (int i = 0; i < 10; i++)
    {
        //利用指针遍历数组
        cout << *p << endl;
        p++;
    }
    
    system("pause");
    return 0;
}

指针和函数

利用指针作函数参数,可以修改实参的值。

//值传递
void swap1(int a ,int b)
{
    int temp = a;
    a = b;
    b = temp;
}

//地址传递
void swap2(int * p1, int *p2)
{
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

int main() {

    int a = 10;
    int b = 20;

    swap1(a, b); // 值传递不会改变实参
    swap2(&a, &b); //地址传递会改变实参

    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    system("pause");
    return 0;
}
  • 如果不想修改实参,就用值传递,如果想修改实参,就用地址传递

指针、数组、函数

//冒泡排序函数
void bubbleSort(int * arr, int len)  //int * arr 也可以写为int arr[]
{
    for (int i = 0; i < len - 1; i++)
    {
        for (int j = 0; j < len - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

//打印数组函数
void printArray(int arr[], int len)
{
    for (int i = 0; i < len; i++)
    {
        cout << arr[i] << endl;
    }
}

int main() {
    int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
    int len = sizeof(arr) / sizeof(int);

    bubbleSort(arr, len);
    printArray(arr, len);

    system("pause");
    return 0;
}
  • 当数组名传入到函数作为参数时,被退化为指向首元素的指针

Structure

结构体基本概念

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型

结构体定义和使用

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

通过结构体创建变量的方式有三种:

  • struct 结构体名变量名
  • struct 结构体名 变量名 = { 成员1值 , 成员2值…}
  • 定义结构体时顺便创建变量
//结构体定义
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;
  
    system("pause");
    return 0;
}
  • 定义结构体时的关键字是 struct,不可省略
  • 创建结构体变量时,关键字 struct 可以省略
  • 结构体变量利用操作符 ‘’.‘’ 访问成员

结构体数组

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

//结构体定义
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;
}

结构体指针

  • 利用操作符 -> 可以通过结构体指针访问结构体属性
//结构体定义
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;
    
    system("pause");
    return 0;
}

结构体嵌套结构体

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

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

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

int main() {
    struct student stuArray[3] = {
            {"July", 19, 100},
            {"Home", 20, 89},
            {"Kean", 23,90}};
            
	struct teacher t1 = {123, "Peter", 40, stuArray};
    
    cout << "教师 职工编号: " << t1.id << " 姓名: " << t1.name << " 年龄: " << t1.age << endl;
    cout << "辅导学员 姓名: " << t1.stu[0].name << " 年龄:" << t1.stu[0].age << " 考试分数: " << t1.stu[0].score << endl;

    system("pause");
    return 0;
}

结构体做函数参数

传递方式有两种

  • 值传递
  • 地址传递
//学生结构体定义
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;

    system("pause");
    return 0;
}
  • 如果不想修改主函数中的数据,用值传递,反之用地址传递

结构体中 const 使用场景

  • 用 const 来防止误操作
//学生结构体定义
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);
    
    system("pause");
    return 0;
}

结构体案例

案例1

案例描述:

学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据。

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); //打印数据
    
    system("pause");
    return 0;
}

案例2

案例描述:

设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。

//英雄结构体
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;
}
  • 20
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值