相关内容来自B站黑马程序员:C++教程从0到1入门编程

C++起步知识

注释

和Java一样,C++的注释分为单行注释和多行注释

单行注释://

多行注释:/* */

例如:

1
2
3
4
5
6
7
// 1. 这是单行注释

/*
1. 这是多行注释
2. 这是多行注释
3. 这是多行注释
*/

入口函数

在C++中,入口函数为main函数,每个程序有且仅有一个入口函数,对应Java中的public static void main

1
2
3
4
5
6
7
8
9
#include <iostream>

using namespace std;

int main() {
cout << "Hello World" << endl;

return 0;
}

变量

作用:给一段指定的内存空间起名,方便操作这段内存

语法:数据类型 变量 = 值;

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

using namespace std;

int main() {
int a = 10;

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

return 0;
}

变量命名规则:

  1. 字母、数字和下划线:变量名可以包含字母(A-Z, a-z)、数字(0-9)和下划线(_)。
  2. 以字母或下划线开头:变量名必须以字母或下划线开头,不能单独使用数字开头。
  3. 区分大小写:C++是区分大小写的语言,因此variableVariable会被视为两个不同的标识符。
  4. 避免使用保留关键字:避免使用C++的保留关键字作为变量名。例如,int, class, if, for等是C++的关键字,不能用作变量名。
asm do if return typedef
auto double inline short typeid
bool dynamic_cast int signed typename
break else long sizeof union
case enum mutable static unsigned
catch explicit namespace static_cast using
char export new struct virtual
class extern operator switch void
const false private template volatile
const_cast float protected this wchar_t
continue for public throw while
default friend register true
delete goto reinterpret_cast try

常量

作用:用于记录程序中不可更改的数据

定义方式:

  1. #define宏常量:#define 常量名 常量值
    • 通常在文件上方定义,表示一个常量,常量名一般都是以全部大写命名
  2. const修饰的变量:const 数据类型 常量名 = 常量值
    • 通常在变量定义前加关键字const,修饰该变量为常量,不可修改
    • 命名规则与变量一样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#define PI 3.141

using namespace std;

int main() {
// PI = 10 报错!

cout << "PI = " << PI << endl;

const int minutesInOneHour = 60;

// minutesInOneHour = 100 报错!

cout << "一小时有:" << minutesInOneHour << "分钟" << endl;

return 0;
}

数据类型

C++规定在创建一个变量或常量时,必须要指定相应的数据类型,否则无法给变量分配内存

整型

整型也称整数类型,C++有以下几种整型类型:

数据类型 占用空间 取值范围
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)

sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占内存大小

语法:sizeof(数据类型/变量)

1
2
3
4
5
6
7
8
9
10
#include <iostream>

using namespace std;

int main() {
char h = 'h';
cout << sizeof(int) << endl; // 4
cout << sizeof(h) << endl; // 1
return 0;
}

浮点型

作用:表示小数

浮点型分为两种:

  1. 单精度float
  2. 双精度double
数据类型 占用空间 有效数字范围
float 4字节 7位有效数字
double 8字节 15~16位有效数字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

using namespace std;

int main() {
float a = 3.1415f;
double b = 1.01;

float c = 1.0000001f;

cout << a << endl; // 3.1415
cout << b << endl; // 1.01
cout << c << endl; // 1 默认情况下,输出一个小数只会显示6位有效数字

// 科学计数法
float f1 = 3e2; // 表示 3 * 10 ^ 2,即300
float f2 = 3e-2; // 表示 3 * 0.1 ^ 2,即0.03

return 0;
}

精度丢失问题:

  • 十进制 0.1 的二进制是无限循环小数
    0.1(十进制) = 0.00011001100110011...(二进制),就像十进制的 1/3 = 0.3333…。

案例:

1
float count = 0.1 + 0.2;	// 如果将小数后全部显示出来,结果是:0.30000000000000004

字符型

作用:字符型变量用于显示单个字符

语法:char ch = 'a';

注意:在显示字符变量时,用单引号将字符括起来,而不是双引号

注意:单引号内只能有一个字符,不能是字符串

  • C和C++中字符型变量只占用1个字节
  • 字符型变量并不是把字符本身放到内存中存储,而是将字符对应的ASCII编码放入到存储单元
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main() {
char c1 = 'h';
cout << c1 << endl; // 输出:h
cout << sizeof(c1) << endl; // 输出:1

//char c2 = "h"; 报错,不能使用双引号
//char c3 = 'hello' 报错,单引号内不能是为字符串
char c4 = 'a';
cout << (int)c4 << endl; // 97

return 0;
}

ASCII表:

ASCII 控制字符 ASCII 字符 ASCII 字符 ASCII 字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 ! 65 A 97 a
2 STX 34 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 `
31 US 63 ? 95 _ 127 DEL

ASCII 码大致由以下两部分组成:

  • ASCII 非打印控制字符: ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。
  • ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。

转义字符

作用:用于表示一些不能显示出来的ASCII字符

常用转移字符有:\n \\ \t

转义字符 含义 ASCII码值(十进制)
\a 警报 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\\ 代表一个反斜线字符”" 092
' 代表一个单引号(撇号)字符 039
" 代表一个双引号字符 034
? 代表一个问号 063
\0 数字0 000
\ddd 8进制转义字符,d范围0~7 3位8进制
\xhh 16进制转义字符,h范围09,af,A~F 3位16进制
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

int main() {
cout << "Hello World" << endl;
cout << "\t Hello World" << endl;
cout << "\n Hello World" << endl;
cout << "\\ Hello World" << endl;

return 0;
}

字符串型

作用:用于表示一串字符

两种风格:

  1. C风格字符串:char 变量名[] = "字符串值";

  2. C++风格字符串:string 变量名 = "字符串值";

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main() {
string s1 = "Hello World";
char s2[] = "Hello World";

cout << s1 << endl;
cout << s2 << endl;

cout << sizeof(s1) << endl; // 40
cout << sizeof(s2) << endl; // 12

return 0;
}

注意:字符串一定要用双引号括起来

注意:虽然string和char数组都可以表示字符串,但是所占的内存大小并不一样

类型 string类对象(s1) char[]数组(s2)
内存布局 类实例,含指针、容量、大小等元数据 连续字符序列,结尾可能含\0
sizeof结果 固定元数据大小(与字符串无关) 整个数组的字节数(包含所有元素)

布尔类型

作用:布尔类型表示值的真或假

布尔类型只有两种值:

  1. true:表示值为真,本质是1
  2. false:表示值为假,本质是0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

using namespace std;

int main() {
bool flag_1 = true;
bool flag_2 = false;

cout << flag_1 << endl; // 1
cout << flag_2 << endl; // 0
cout << sizeof(flag_1) << endl; // 1

return 0;
}

数据输入

作用:通过键盘输入数据

语法:cin >> 变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

using namespace std;

int main() {
int number = 0;

cout << "请输入数据:" << endl;
cin >> number;

cout << "您输入的是数字:" << number << endl;

return 0;
}

数据类型之间的转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string> // 引入string库,用于处理string数据类型
#include <typeinfo> // 引入typeinfo,用于判断数据类型

using namespace std;

int main() {
// 字符串转整数
string s1 = "123";
int n1 = stoi(s1);
n1++;
cout << n1 << endl; // 124

// 整数转字符串
int n2 = 11;
string s2 = to_string(n2) + to_string(n2);
cout << s2 << endl; // 1111

// 浮点数转整数
float f1 = 3.11f;
int n3 = (int)f1;
cout << n3 << endl; // 3 向下取整,也称为小数部分截断

// 整数转浮点数
int n4 = 10;
float f2 = (float)n4;
f2 += 0.1;
cout << f2 << endl; // 10.1

// 浮点数转字符串
float f3 = 0.5f;
string s3 = to_string(f3) + to_string(f3);
cout << s3 << endl; // 0.5000000.500000

// 字符串转浮点数
string s4 = "0.345";
float f4 = stof(s4);
f4 += 0.1;
cout << f4 << endl; // 0.445

return 0;
}

运算符

作用:用于执行代码的运算

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

算数运算符

运算符 术语 示例 结果
+ 正号 +3 3
- 负号 -3 -3
+ 10 + 5 15
- 10 - 5 5
* 10 * 5 50
/ 10 / 5 2
% 取模(取余) 10 % 3 1
++ 前置递增 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;

注意:整数与整数相除,结果一定是整数,如果除不尽则向下取整,如10 / 3 = 3

注意:整数与浮点数进行加减乘除,结果一定是浮点数

注意:小数不能做取模运算

赋值运算符

作用:用于将表达式的值赋给变量

运算符 术语 示例 结果
= 赋值 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 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0
> 大于 4 > 3 1
<= 小于等于 4 <= 3 0
>= 大于等于 4 >= 1 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main() {
int num_01 = 10;
int num_02 = 20;

cout << (num_01 < num_02) << endl; // 1
cout << (num_01 > num_02) << endl; // 0
cout << (num_01 == num_02) << endl; // 0
cout << (num_01 <= num_02) << endl; // 1
cout << (num_01 >= num_02) << endl; // 0

return 0;
}

逻辑运算符

作用:用于根据表达式的值返回真值或假值

运算符 术语 示例 结果
! !a 如果a为假,则!a为真; 如果a为真,则!a为假。
&& a && b 如果a和b都为真,则结果为真,否则为假。
|| a || b 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

using namespace std;

int main() {
int num_01 = 10;
int num_02 = 20;
int num_03 = 30;

cout << !(num_01 < num_02) << endl; // 0
cout << !(num_01 > num_02) << endl; // 1

cout << (num_01 < num_02 && num_02 < num_03) << endl; // 1
cout << (num_01 < num_02 && num_02 > num_03) << endl; // 0

cout << (num_01 > num_02 || num_02 > num_03) << endl; // 0
cout << (num_01 < num_02 || num_02 < num_03) << endl; // 1



return 0;
}

程序流程结构

C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构

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

选择结构

if语句

作用:执行满足条件的语句

if语句的三种形式:

  • 单行格式if语句
  • 多行格式if语句
  • 多条件的if语句
  1. 单行格式if语句if (条件) {条件满足执行的语句}

clip_image002

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

int main() {
int num = 0;
cout << "请输入一个数字:" << endl;
cin >> num;

if (num < 10) {
cout << "你输入的数字比10小" << endl;
}

if (num >= 10 && num <= 20) {
cout << "你输入的数字在10 ~ 20之间" << endl;
}

if (num > 20) {
cout << "你输入的数字比20大" << endl;
}



return 0;
}
  1. 多行格式if语句if (条件) {条件满足执行的语句} else { 条件不满足执行的语句 };

clip_image002-1541662519170

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;

int main() {
int num = 0;
cout << "请输入一个数字:" << endl;
cin >> num;

if (num < 10) {
cout << "你输入的数字比10小" << endl;
}
else {
cout << "你输入的数字比10大" << endl;
}

return 0;
}
  1. 多条件if语句if (条件1) {条件1满足执行的语句} else if (条件2) {条件2满足执行的语句} ... else {都不满足执行的语句}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>

using namespace std;

int main() {
int num = 0;
cout << "请输入一个数字:" << endl;
cin >> num;
/*
if (num > 0) {
cout << "你输入的数字比0大" << endl; // 只要数字比0大,就只会执行部这一条,后面的条件都会跳过
}
else if (num > 10){
cout << "你输入的数字比10大" << endl;
}
else if (num > 20) {
cout << "你输入的数字比20大" << endl;
}
else {
cout << "你输入的数字很大" << endl;
}
*/

if (num < 10) {
cout << "你输入的数字比10小" << endl;
}
else if (num < 20) {
cout << "你输入的数字比10大比20小" << endl;
}
else if (num < 30) {
cout << "你输入的数字比20大比30小" << endl;
}
else {
cout << "你输入的数字大于等于30" << endl;
}

return 0;
}
  1. if语句嵌套
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;

int main() {
int age;
double height;

cout << "请输入年龄: ";
cin >> age;
cout << "请输入身高(cm): ";
cin >> height;

// 外层判断年龄
if (age >= 18) {
// 内层判断身高
if (height >= 160.0) {
cout << "符合条件,允许乘坐过山车!" << endl;
} else {
cout << "年龄达标,但身高不足160cm,不可乘坐" << endl;
}
} else {
cout << "年龄未满18岁,禁止乘坐" << endl;
}

return 0;
}

三目运算符

作用:通过三目运算符实现简单的判断

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

解释:

如果表达式1的值为真,执行表达式2,并返回表达式2的结果

如果表达式2的值为假,执行表达式3,并返回表达式3的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

using namespace std;

int main() {

int a = 10;
int b = 20;
int c = 0;

a < b ? cout << "a小于b" << endl : cout << "a大于b" << endl;

c = a > b ? a : b; // 三目运算符能返回结果,所以可以用于赋值
cout << "c的值为:" << c << endl;

return 0;
}

switch语句

作用:执行多条件分支语句

语法:

1
2
3
4
5
6
7
switch(表达式)
{
case 结果1: 执行语句1;break;
case 结果2: 执行语句2;break;
...
default:执行结果;break;
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

int main() {
int a = 0;

cout << "请输入一个数:" << endl;
cin >> a;

switch (a) {
case 1:
cout << "值为1" << endl;
break;
case 2:
cout << "值为2" << endl;
break;
default:
cout << "值不为1也不为2" << endl;
break;
}

return 0;
}

如果不写break,switch会继续向下寻找符合条件的case并执行语句,这也称为case穿透

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>

using namespace std;

int main() {
int a = 0;

cout << "请输入一个数:" << endl;
cin >> a;



switch (a) {
case 0:;
case 1:;
case 2:;
case 3:;
case 4:
cout << "值在0到4之间";
break;
case 5:;
case 6:;
case 7:;
case 8:;
case 9:
cout << "值在5到9之间";
break;
default:
cout << "值大于等于10";
break;
}

return 0;
}

循环结构

while循环语句

作用:满足循环条件,执行循环语句

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

解释:只要循环条件的结果为真,就执行循环语句

clip_image002-1541668640382

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

using namespace std;

int main() {
int i = 0;
while (i < 10) {
cout << "我今年" << i << "岁了" << endl;
i++;
}

i = 0;


while (i < 100) {
if (i == 18) {
cout << "我成年啦" << endl;
break; // 跳出循环
}
else {
cout << "我今年" << i << "岁了" << endl;
i++;
}
}

i = 0;

while (i < 100) {
if (i > 30 && i < 50) {
i++;
cout << "我要开始认真工作了" << endl;
continue; // 跳过一次循环
}
cout << "我今年" << i << "岁了" << endl;
i++;
}

return 0;
}

注意:一定要注意避免死循环,如while (1),如果循环体中没有中断循环的代码,程序会一直运行直到内存资源消耗殆尽

do…while循环语句

作用:满足循环条件,执行循环语句

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

解释:在循环前先执行一次操作再判断循环条件

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

using namespace std;

int main() {
int password;
do {
cout << "请输入密码(必须>0):";
cin >> password;
} while (password <= 0); // 强制用户至少输入一次

return 0;
}

练习案例——水仙花数

水仙花数是指一个三位数,它的每个位上的数字的3次幂之和等于它本身

例如:1^3 + 5^3 + 3^3 = 153

利用do…while求出三位数中所有的水仙花数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

int main() {
int num = 100;

do {
int ge = num % 100 % 10;
int shi = num / 10 % 10;
int bai = num / 100;

if (pow(ge, 3) + pow(shi, 3) + pow(bai, 3) == num) {
cout << num << "是水仙花数" << endl;
num++;
continue;
}

num++;

} while (num < 1000);

return 0;
}

for循环语句

作用:满足循环条件,执行循环语句

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

1
2
3
4
5
6
7
int main() {
for (int i = 0;i < 10; i++) {
cout << i << endl;
}

return 0;
}

嵌套循环

作用:在循环体中再嵌套一层循环

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

int main() {

for (int i = 1; i < 10; i++)
{
for (int j = 1; j <= i; j++) {
cout << j << "x" << i << "=" << i * j << " ";

}

/*
// 下面这种写法更繁琐,消耗资源更多,但是好理解
for (int j = 1; j < 10; j++) {
if (j > i) {continue;}
cout << j << "x" << i << "=" << i * j << " ";
}
*/
cout << " " << endl;
}

return 0;
}

goto语句

作用:可以无条件跳转到语句

语法:goto 标记;

解释:如果标记的名称存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

using namespace std;

int main() {

cout << "1" << endl;
goto Flag;
cout << "2" << endl;
cout << "3" << endl;
cout << "4" << endl;
Flag:
cout << "5" << endl;
cout << "6" << endl;
cout << "7" << endl;
cout << "8" << endl;

return 0;
}

注意:由于goto代码会打乱代码的执行顺序,导致代码可读性变差,所以尽量避免使用

数组

数组就是一个集合,里面存放了相同类型的数据元素

特点1:数组中的每个数据元素都是相同的数据类型

特点2:数组是由连续的内存位置组成的

静态初始化

方式1(静态显式初始化):

语法:数据类型 数组名[数组长度] = {值1,值2,...,不能超过数组最大长度} ;

1
2
3
4
int arr_01[5] = {1,2,3,4,5};	// 完全显式初始化
int arr_02[5] = {1,2,3}; // 部分显式初始化,没有声明具体值的部分记为0
int arr_03[5] = {1,2,3,4,5,6}; // 报错!超过数组最大长度
int arr_04[5]{1,2,3} // C++11统一初始化,没有声明具体值的部分记为0

方式2(零初始化):

当前不考虑局部作用域

语法:数据类型 数组名[数组长度];

1
2
3
4
5
6
7
8
int arr_01[5];
int arr[5]{}; // C++11统一初始化(推荐)
arr_01[0] = 1;
arr_01[1] = 2;
arr_01[2] = 3;
arr_01[3] = 4;
arr_01[4] = 5;
arr_01[5] = 6; // 报错!超过数组最大长度

方式3(推导式静态显式初始化):

语法:数据类型 数组名[] = {1,2,3,4,...,没有长度限制}

1
2
3
int arr_01[] = {1,2,3,4,5};
int arr_02[] = {1,2};
int arr_03[] = {1,2,3,4,5,6,7,8,9,10,11,...}

获取数组长度

C++17以前没有Python中len(数组名)或Java中数组名.length()来快速获取数组长度,需要进行单独的计算

计算公式:sizeof(数组名) / sizeof(数组数据类型)

解释:sizeof(数组名)表示数组中所有元素在内存中所占的大小,sizeof(数组数据类型)表示数组的数据类型所占内存空间大小

例如:

1
2
3
4
5
int arr[] = {1,2,3,4,5,6,7,8,9};

int len_01 = sizeof(arr) / sizeof(int);
// 或者
int len_02 = sizeof(arr) / sizeof(arr[0]); // 用于当不能确定数组的具体数据类型时(推荐)

C++17之后可以使用size()快速获取数组长度:

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;

int main() {

int arr[]{ 5,2,3,6,9,7,8,1,4 };
cout << size(arr) << endl;

return 0;
}

冒泡排序

作用:最常用的排序算法,对数组内元素进行排序

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个
  2. 对每一个相邻元素做同样的工作,执行完毕后,找到第一个最大值
  3. 重复以上的步骤,每次比较次数-1,直到不需要比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>

using namespace std;

void coutArr(int arr[],int length) {
for (int i = 0; i < length; i++)
{
cout << arr[i];
}
}


int main() {

int arr[]{ 5,2,3,6,9,7,8,1,4 };

int length = sizeof(arr) / sizeof(arr[0]);

for (int i = 0; i < length - 1; i++)
{
for (int j = 0; j < length - 1 - i; j++) { // 这里-1-i的原因是假设第一轮比完后最后一位一定是最大的,可以跳过检测
if (arr[j] > arr[j + 1]) { // 改变符号就等于改变排序
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}

coutArr(arr, length);

return 0;
}

二维数组

二维数组定义的四种方式:

  1. 数据类型 数组名[行数][列数];
  2. 数据类型 数组名[行数][列数] = {{值1,值2}, {值3,值4}};
  3. 数据类型 数组名[行数][列数] = {数据1, 数据2, 数据3, 数据4};
  4. 数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4};

推荐使用第二种方式,更加直观,提升代码可读性

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

int main() {
int arr[2][3] = {
{1,2,3},
{4,5,6}
};

int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);
cout << "col列:" << col << endl;
cout << "row行:" << row << endl;


for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++) {
cout << "第" << i + 1 << "行" << "第" << j + 1<< "列的数字是" << arr[i][j] << endl;
}
}

return 0;
}

案例

将下表内容输出的控制台中:

语文 数学 英语
张三 100 100 100
李四 90 50 100
王五 60 70 80

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

using namespace std;

int main() {
// 输出成绩
int score[3][3] = {
{100,100,100},
{90,50,100},
{60,70,80}
};

string name[] = {"张三","李四","王五"};

int row = sizeof(score) / sizeof(score[0]);
int col = sizeof(score[0]) / sizeof(score[0][0]);

cout << " 语文 数学 英语" << endl;

for (int i = 0; i < row; i++)
{
cout << name[i] << " ";
for (int j = 0; j < col; j++) {

cout << score[i][j] << " ";
}
cout << endl;
}


return 0;
}

函数

作用:将一段经常使用的代码封装起来,减少重复代码

函数的定义

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

语法:

1
2
3
4
5
返回值类型 函数名 (参数列表)
{
函数体语句;
return 表达式;
}

基本使用案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

void saySomeThing(string strs) {
cout << strs << endl;
};

int sum(int num1, int num2) {
return num1 + num2;
}

int main() {

saySomeThing("Hello World");
saySomeThing("你好!!");
//saySomeThing(12345); 报错,实参数据类型与形参不匹配

int count = sum(1, 2); // 有返回值可以用变量接收
cout << sum(5, 6) << endl; // 也可以直接打印


return 0;
}

注意:函数必须在main之前声明,否则运行时会检测不到函数而引起报错

1
2
3
4
5
int main() {
func(); // 报错
}

void func() {...}; // 后声明

但是以下写法是可以的:

1
2
3
4
5
6
7
8
9
void func();	// 先声明

int main() {
func(); // 正确运行
}

void func() {
cout << "Hello World" << endl; // 再实现
}

函数的调用

以上代码已经包含了函数的调用,简单来说,调用一个函数只需要函数名(函数参数)即可

如:sum(1,2)sayHello()checkMission()

函数的值传递

函数定义时,括号里的参数表示形参,函数调用时,括号里的参数表示实参

值的传递流程就是:调用函数 => 修改/添加实参 => 对应位置上的形参被替换为实参 => 执行函数体内容

所以,只要实参和形参的类型相同,形参名是什么都无所谓,只要每个形参之间不重名即可

函数的常见形式

常见的函数样式有4种:

  1. 无参无返
  2. 有参无返
  3. 无参有返
  4. 有参有反
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

// 无参无返
void test_01() { cout << "无参无返" << endl; }

// 有参无返
void test_02(int nums[]) {
for (int i = 0; i < sizeof(nums) / sizeof(nums[0]); i++)
{
cout << nums[i] << " ";
}
}
// 无参有返
bool test_03() { return true; }
// 有参有返
string test_04(string s1,string s2,string s3) {
return s1 + s2 + s3;
}

int main() {

cout << "无参无返调用结果:";
test_01();

cout << "有参无返调用结果:";
int arr[]{ 1,2,3,4,5 };
test_02(arr);
cout << endl;

cout << "无参有返调用结果:";
bool b1 = test_03();
cout << b1 << endl;

cout << "有参有返调用结果:";
string s1 = test_04("你好", "世界", "Hello World");
cout << s1 << endl;



return 0;
}

函数的声明

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

  • 函数的声明可以多次,但是函数的定义只能一次
1
2
3
4
5
6
7
8
9
10
11
12
13
// 声明可以多次,定义只能一次
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() {
cout << max(1,2) << endl;
}

函数的重载

虽然正常情况下函数定义只能定义一次,但实际上只要形参数量不重复就可以多次定义,当实参数对应到了函数的形参数就调用哪个函数

1
2
3
4
5
6
7
8
9
10
11
12
int max(int a,int b) {	// 这个函数暂时可以叫做函数一
return a > b ? a : b;
}

int max(int a,int b,int c) { // 这个函数暂时叫做函数二
return max(max(a,b),c);
}

int main() {
max(1,2); // 这里调用的是函数一
max(1,2,3); // 这里调用的是函数二
}

函数的分文件编写

作用:让代码结构更加清晰

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

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

示例:

1
2
3
4
5
6
// swap.h文件
#include<iostream>
using namespace std;

// 实现两个数字交换的函数声明
void swap(int a, int b);
1
2
3
4
5
6
7
8
9
10
11
12
// 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;
}
1
2
3
4
5
6
7
8
9
10
11
12
// main函数文件
#include "swap.h"
int main() {

int a = 100;
int b = 200;
swap(a, b);

system("pause");

return 0;
}

指针

指针的作用:可以通过指针间接访问内存

  • 内存编号是从0开始记录,一般用十六进制数字表示
  • 可以利用指针变量保存地址

指针变量的定义和使用

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

int main() {
// 1. 定义指针
int a = 10;

// 指针定义的语法:数据类型 * 指针变量名
int* p;
// 让指针记录变量a的地址
p = &a; // & 表示取址符号
cout << "a的内存地址为:" << &a << endl; // 控制台输出:000000C7B31CF894
cout << "指针p的值为:" << p << endl; // 控制台输出:000000C7B31CF894
// // *指针名 表示解引用
cout << "指针p指向内存地址的具体值为:" << *p << endl; // 控制台输出:10

// 通过 *p 修改a的值
*p = 255;
cout << "*p修改a的值后,a当前的值为:" << a << endl; // 控制台输出:255



return 0;
}
  1. &表示取值符号
  2. *指针名 = 值表示对指针所指的变量的值进行修改
1
2
3
int a = 10;	// 将整数值10存入变量a的内存空间,此时a对应的内存地址中存储的值为10
int* p = &a; // &a获取变量a的内存地址,并将其赋值给指针变量p。此时p保存的是a的内存地址
*p = 255; // 通过解引用操作符*访问p指向的内存地址(即a的地址),修改该地址存储的值为20。此时a的值变为20。

指针所占内存空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

using namespace std;

int main() {
int a = 10;
int* p = &a;

cout << sizeof(p) << endl; // 8
cout << sizeof(char*) << endl; // 8
cout << sizeof(float*) << endl; // 8
cout << sizeof(double*) << endl; // 8

return 0;
}
系统架构 地址总线宽度 指针大小 寻址空间
32位 32位 4字节 4GB(2^32)
64位 64位 8字节 16EB(2^64)
  • 64位系统:指针统一占用 8字节(无论指向何种数据类型)。
  • 32位系统:指针统一占用 4字节
  • 原理:指针存储的是内存地址,其大小由 系统寻址能力 决定(64位系统地址总线为64位,需8字节存储)

空指针和野指针

空指针:指针变量指向内存中编号为0的空间

用途:初始化指针变量

注意:空指针指向的内存是不可以访问的

示例:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

using namespace std;

int main() {
int* p= NULL;
cout << p << endl; // 报错
cout << *p << endl; // 报错

return 0;
}

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

示例:

1
2
3
4
5
6
7
8
9
10
#include <iostream>

using namespace std;

int main() {
int* p = (int *)0x1100;
cout << *p << endl; // 报错

return 0;
}

const修饰指针

const修饰指针有三种情况:

  1. const修饰指针
    • 称为:常量指针
    • 语法:const int * p = a;
    • 特点:指针的指向可以修改,但是指针指向的值不可以该。如p = &b是可以的,但是*p = 20是错误的
  2. const修饰常量
    • 称为:指针常量
    • 语法:int * const p = a;
    • 特点:与常量指针正好相反。p = &b是错误的,*p = 20是可以的
  3. const即修饰指针,又修饰常量
    • 无特定名称
    • 语法:const int * const p = a;
    • 特点:指针的指向、指针指向的值都不可以修改。*p = 20p = &b都是错误的

记忆技巧:

  1. const在*之前,表示对*进行了限制,当操作*时就是错误的,如*p = 20
  2. const在*之后,表示对指针变量进行了限制,当操作指针变量时就是错误的,如p = &b
类型 术语 特性总结
const int *p 指向常量的指针 值不可改,地址可改
int *const p 指针常量 地址不可改,值可改
const int *const p 指向常量的指针常量 值和地址均不可改

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

using namespace std;

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

const int* p1 = &a;
*p1 = 20; // 编译器直接报错,提示表达式必须是可以修改的左值
p1 = &b;

int* const p2 = &a;
*p2 = 20;
p2 = &b; // 编译器直接报错,提示表达式必须是可以修改的左值

const int* const p3 = &a;
*p3 = 20; // 编译器直接报错,提示表达式必须是可以修改的左值
p3 = &b; // 编译器直接报错,提示表达式必须是可以修改的左值


return 0;
}

指针和数组

作用:利用指针访问数组中元素

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;

int main() {
int arr[]{ 1,2,3,4,5,6,7,8,9,10 };
int* p = arr; // arr存储的就是地址,不用取址符号

for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
cout << "数组中索引为" << i << "的值是:" << *p << endl; // 打印的是具体的值
cout << "数组中索引为" << i << "的值的地址是:" << p << endl;
p++; // p++等价于 p = p + sizeof(int)
}


return 0;
}

关于p++的详细说明:

机制 说明
类型依赖步长 指针加减运算根据指向类型自动调整步长(int→4字节,double→8字节)
编译器隐式转换 p+1实际执行 p + 1*sizeof(int)

指针和函数

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>

using namespace std;

// 值传递函数
void swap_01(int a, int b) {
int tmp = a;
a = b;
b = tmp;
}

// 地址传递函数
void swap_02(int* p1, int* p2) {
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}

// 无效的指针交换(错误原因:交换指针副本)
void swap_03(int* p1, int* p2) {
int* tmp = p1;
p1 = p2;
p2 = tmp;
}

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

// 调用值传递函数,a和b的值并不会发生改变
swap_01(a, b);
cout << "a的值为:" << a << endl; // 10
cout << "b的值为:" << b << endl; // 20

// 调用地址传递函数,a和b的值是会发生改变的
swap_02(&a, &b);
cout << "a的值为:" << a << endl; // 20
cout << "b的值为:" << b << endl; // 10

swap_03(&a, &b);
cout << "a的值为:" << a << endl; // 20
cout << "b的值为:" << b << endl; // 10

return 0;
}

指针、函数、数组

案例:利用冒泡排序,编写一个函数对数组进行从小到大的排序

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>

using namespace std;

void coutArr(int arr[],int length) {
for (int i = 0; i < length; i++)
{
cout << arr[i];
}
}

void BubbleSort(int arr[], int length) {
for (int i = 0; i < length - 1; i++)
{
for (int j = 0; j < length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}


int main() {

int arr[]{ 5,2,3,6,9,7,8,1,4 };

int length = sizeof(arr) / sizeof(arr[0]);

BubbleSort(arr, length);

coutArr(arr, length);

return 0;
}

结构体

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

结构体定义和使用

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

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

  • struct 结构体名 变量名
  • struct 结构体名 变量名 = {成员值1, 成员值2...}
  • 定义结构体时顺便创建变量

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>

using namespace std;

// 1. 创建学生数据类型:学生包括(姓名、年龄、分数)
struct Student
{
// 成员列表
string name;
int age;
int score;
string gender;
};


/*
// 创建具体的学生(方式3)不推荐,了解即可
struct Student
{
// 成员列表
string name;
int age;
int score;
string gender;
} s3;
*/



int main() {
// 创建具体的学生(方式1)
struct Student s1 = { "zhangsan",5,200,"男" }; // 按照顺序赋值

cout << "学生叫做:" << s1.name << ";学生年龄为:" << s1.age << ";学生的成绩为:" << s1.score << ";学生的性别是:" << s1.gender << endl;

// 创建具体的学生(方式2)
struct Student s2;
s2.name = "李四";
s2.age = 8;
s2.gender = "男";
s2.score = 180;
cout << "学生叫做:" << s2.name << ";学生年龄为:" << s2.age << ";学生的成绩为:" << s2.score << ";学生的性别是:" << s2.gender << endl;

return 0;
}

注意1:当定义结构体时,struct关键字是不可以被省略的

注意2:创建结构体变量时,如struct Student s1可以省略struct=>Student s1

访问结构体变量的成员时,可以用操作符"."访问成员

结构体数组

作用:将自定义的结构体放入到数组中方便维护

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <string>


using namespace std;

// 1. 创建学生数据类型:学生包括(姓名、年龄、分数)
struct Student
{
// 成员列表
string name;
int age;
int score;
string gender;
};

int main() {
Student stuArry[] = {
{"张三",18,172,"男"},
{"李四",18,178,"女"},
{"王五",17,180,"女"},
{"赵六",17,180,"男"},
};

cout << sizeof(stuArry) / sizeof(stuArry[0]) << endl; // 4
cout << size(stuArry) << endl; // 4

for (int i = 0; i < size(stuArry); i++)
{
stuArry[i].name = stuArry[i].name + to_string(i);
cout << "姓名:" << stuArry[i].name << " ";
cout << "年龄:" << stuArry[i].age << " ";
cout << "分数:" << stuArry[i].score << " ";
cout << "性别:" << stuArry[i].gender << " " << endl;
}

return 0;
}

结构体指针

作用:通过指针访问结构体中的成员

  • 利用操作符->可以通过结构体指针访问结构体数学

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

using namespace std;

struct Subject {
string name;
string level;
int point;
bool isOpened;
};

int main() {
Subject s1 = { "英语","高",5,true };

// 通过指针指向结构体变量
Subject* p = &s1;

// 通过指针访问结构体变量中的数据
cout << p->name << endl;


return 0;
}

结构体嵌套结构体

当结构体内存在另一个结构体,就称之为结构体嵌套结构体

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

struct Teacher
{
string name;
int age;
string gender;
};

struct Student
{
string name;
int age;

// 在结构体内直接声明
struct Subject {
string name;
string level;
int point;
bool isOpened;
} subject;

// 先在结构体外声明,最后在结构体中使用
struct Teacher teacher;
};

int main() {
Student s1;
s1.age = 18;
s1.name = "张三";
s1.subject.level = "中等";
s1.subject.name = "体育";
s1.subject.point = 3;
s1.subject.isOpened = false;

s1.teacher = { "老王",42,"男" };

cout << s1.name << "今年" << s1.age << "岁了,"
<< "他/她的班主任是" << s1.teacher.name << ",他/她是一名" << (s1.teacher.age > 35 ? "有经验的" : "年轻的") << s1.teacher.gender << "老师。"
<< s1.name << "同学喜欢" << s1.subject.name << "这门课,难度属于" << s1.subject.level << "水平,可以获得" << s1.subject.point << "点学分,这门课现在" << (s1.subject.isOpened ? "已经停止开放了" : "已经开放了") << endl;

// 张三今年18岁了,他/她的班主任是老王,他/她是一名有经验的男老师。张三同学喜欢体育这门课,难度属于中等水平,可以获得3点学分,这门课现在已经开放了


return 0;
}

结构体做函数参数

作用:将结构体作为参数向函数中传递

传递方式有两种:

  1. 值传递
  2. 地址传递

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string> // 引入string库,用于处理string数据类型
#include <typeinfo> // 引入typeinfo,用于判断数据类型

using namespace std;



struct Student
{
int id;
string name;
int age;
string province;
};

// 类型自动匹配函数
void coutStudent(Student s) {
cout << "姓名:" << s.name << " ";
cout << "年龄:" << s.age << " ";
cout << "学号:" << s.id << " ";
cout << "所在省份:" << s.province << endl;

s.name += "值传递";
s.age += 100;
s.id += 100000;
s.province += "值传递";
}

// 类型自动匹配函数
void coutStudent(Student* s) {
cout << "姓名:" << s -> name << " ";
cout << "年龄:" << s -> age << " ";
cout << "学号:" << s -> id << " ";
cout << "所在省份:" << s -> province << endl;

s->name = (s->name) + "地址传递";
s->age = (s->age) + 100;
s->id = (s->id) + 100000;
s->province = (s->province) + "地址传递";
}

int main() {
Student s1 = { 10001,"张三",14,"江苏" };

// 值传递
cout << endl;
coutStudent(s1);
cout << endl;
cout << "值传递函数执行后的结果为:";
cout << "姓名:" << s1.name << " ";
cout << "年龄:" << s1.age << " ";
cout << "学号:" << s1.id << " ";
cout << "所在省份:" << s1.province << endl;


// 地址传递
Student* p1 = &s1;
cout << endl;
coutStudent(p1);
cout << endl;
cout << "值传递函数执行后的结果为:";
cout << "姓名:" << s1.name << " ";
cout << "年龄:" << s1.age << " ";
cout << "学号:" << s1.id << " ";
cout << "所在省份:" << s1.province << endl;

return 0;
}

结构体中const使用场景

作用:用const来防止误操作

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string> // 引入string库,用于处理string数据类型
#include <typeinfo> // 引入typeinfo,用于判断数据类型

using namespace std;



struct Student
{
int id;
string name;
int age;
string province;
};

// 类型自动匹配函数
void coutStudent(const Student* s) {

//s->age = 1000; // 报错

cout << "姓名:" << s -> name << " ";
cout << "年龄:" << s -> age << " ";
cout << "学号:" << s -> id << " ";
cout << "所在省份:" << s -> province << endl;
}

int main() {
Student s1 = { 10001,"张三",14,"江苏" };


// 地址传递
Student* p1 = &s1;
coutStudent(p1);
cout << "值传递函数执行后的结果为:";
cout << "年龄:" << s1.age << " ";

return 0;
}

结构体案例练习

案例1:

共有两个结构体,分别是学生和老师,老师结构体中有姓名和学生数组(结构体嵌套,一共三个老师,每个老师共5名学生);

学生结构体中有姓名和分数;利用函数将老师和对应的学生进行赋值;最后将所有结构体打印出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <string> // 引入string库,用于处理string数据类型
#include <typeinfo> // 引入typeinfo,用于判断数据类型

using namespace std;

// 学生结构体
struct Student
{
string name;
int score;
};

// 老师结构体
struct Teacher
{
string name;
Student student[5];
};

// 对老师进行赋值的函数
void createTeacher(Teacher* t,string tname,Student s[]) {
t->name = tname;
for (int i = 0; i < size(t->student); i++)
{
t->student[i] = s[i];
}
}

// 对学生进行赋值的函数
void createStudent(Student* s,string name,int score) {
s->name = name;
s->score = score;
}



int main() {
Teacher t[3];
// 第一层循环表示的是对老师的赋值
for (int i = 0; i < size(t); i++)
{
string name;
cout << "请输入第" << i + 1 << "个老师的姓名:";
cin >> name;
cout << endl;
Student s[5];
// 第二层循环表示对学生数组进行赋值
for (int j = 0; j < size(s); j++)
{
string stuName;
int score;
cout << "请输入该老师带领的第" << j + 1 << "个学生的信息:" << endl;
cout << "学生姓名:";
cin >> stuName;
cout << endl;
cout << "学生分数:";
cin >> score;
Student* p = &s[j];
createStudent(p, stuName, score);
}
// 学生结构体数组创建完成后,进行老师结构体赋值
Teacher* p = &t[i];
createTeacher(p, name, s);
}

// 打印数据
for (int i = 0; i < size(t); i++)
{
cout << "第" << i+1 <<"名老师是:" << t[i].name << "老师" << endl;

for (int j = 0; j < size(t[i].student); j++)
{
cout << "他的第" << j + 1 << "名学生叫:" << t[i].student[j].name << ",他得分是:" << t[i].student[j].score << endl;
}
}

return 0;
}

案例2:

设计一个人物的结构体,结构体成员有:姓名、年龄、性别;创建结构体数组,数组中存放5名人物

通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果

五名人物的信息如下:

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <string> // 引入string库,用于处理string数据类型
#include <typeinfo> // 引入typeinfo,用于判断数据类型

using namespace std;

struct Person {
string name;
int age;
string gender;
};

int main() {
Person p[] = {
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"}
};

// 冒泡排序算法
for (int i = 0; i < size(p) - 1; i++)
{
for (int j = 0; j < size(p) - 1 - i; j++)
{
if (p[j].age > p[j + 1].age) {
Person tmp = p[j];
p[j] = p[j + 1];
p[j + 1] = tmp;
}
}
}

// 打印结果
for (int i = 0; i < size(p); i++)
{
cout << "第" << i + 1 << "位人物是:" << p[i].name << ",年龄是:" << p[i].age << ",性别是:" << p[i].gender << endl;
}



return 0;
}