C++入门编程学习笔记(二)
一、程序流程结构
- C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
- 顺序结构:程序安书序执行,不发生跳转
- 选择结构:依据条件是否满足,有选择的执行相应功能
- 循环结构:依据条件是否满足,循环多次执行某段代码
1.1 选择结构
1.1.1 if 语句
- if语句的作用是执行满足条件的语句
- if语句有三种形式:单行格式if语句、多行格式if语句、多条件的if语句
代码:
/*********************************************************************
程序名:选择结构
作者: Sweitena
日期: 2021-03-17 16:05
说明:if语句的三种结构
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//单行格式if语句
//如果成绩大于90,输出成绩优秀
cout << "①单行if语句" << endl;
int score1 = 0;
cout << "请输入一个分数:" << endl;
cin >> score1;
if (score1 > 90) {
cout << "成绩优秀" << endl;
}
//多行格式if语句
//如果成绩大于60,输出及格;反之,输出不及格
cout << "②if - else结构" << endl;
int score2 = 0;
cout << "请输入一个分数:" << endl;
cin >> score2;
if (score2 < 60) {
cout << "不及格" << endl;
} else {
cout << "及格" << endl;
}
//多条件的if语句
/*如果成绩小于60,输出成绩不及格;60~80,输出成绩一般;
80~90,成绩不错;大于90,成绩优秀*/
cout << "③if - else if - else结构" << endl;
int score3 = 0;
cout << "请输入一个分数:" << endl;
cin >> score3;
if (score3 > 90)
{
cout << "成绩优秀" << endl; //注意:if里面也是按顺序依次执行的
}
else if (score3 > 80)
{
cout << "成绩不错" << endl; //所以先把大的写前面
}
else if (score3 > 60)
{
cout << "成绩一般" << endl;
}
else
{
cout << "成绩不及格" << endl;
}
system("pause");
return 0;
}
运行结果图:
1.1.2 嵌套 if 语句
- 在 if 语句中,可以嵌套使用 if 语句,达到更精确的条件判断
案例描述:
- 提示用户输入一个高考考试分数,根据分数做出如下判断;
- 分数如果大于600视为考上一本,大于500分视为考上二本,大于400考上三本,其余视为未考上本科;
- 在一本分数中,如果大于700分,考上北大,大于650分,考上清华,大于600分,考入人大。
代码:
/*********************************************************************
程序名:选择结构
作者: Sweitena
日期: 2021-03-17 16:05
说明:嵌套if语句
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int score = 0;
cout << "请输入一个高考分数:" << endl;
cin >> score;
cout << "您输入的分数是:" << score << endl;
if (score > 600) //如果大于600 一本
{
cout << "恭喜您考入一本大学" << endl;
if (score > 700)
{ cout << "恭喜您考入北大" << endl;}
else if (score > 650)
{ cout << "恭喜您考入清华" << endl;}
cout << "恭喜您考入人大" << endl;
}
else if (score > 500) //如果大于500 二本
{
cout << "恭喜您考入二本大学" << endl;
}
else if (score > 400) //如果大于400 三本
{
cout << "恭喜您考入三本大学" << endl;
}
else //其余情况 未考上本科
{
cout << "很抱歉,您未考上本科" << endl;
}
system("pause");
return 0;
}
运行结果图:
❀案例练习:三只小猪称体重
案例描述:
- 有三只小猪ABC,请分别输入三只小猪的体重,并且判断那只小猪最重
代码:
/*********************************************************************
程序名:选择结构案例练习01
作者: Sweitena
日期: 2021-03-18 09:15
说明:三只小猪称重
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//1.创建三只小猪的体重变量
int a, b, c;
a = 0;
b = 0;
c = 0;
//2.让用户输入三只小猪的重量
cout <<"请输入小猪A的体重:"<< endl;
cin >> a;
cout <<"请输入小猪B的体重:"<< endl;
cin >> b;
cout <<"请输入小猪C的体重:"<< endl;
cin >> c;
//3.判断哪只最重
//先判断A和B
if(a > b) //a>b
{
if(a > c) //a>c
{cout << "小猪A最重" << a << endl;}
else //a<c
{cout << "小猪C最重" << c << endl;}
}
else //a<b
{
if(b > c) //b>c
{cout << "小猪B最重" << b << endl;}
else //b<c
{cout << "小猪c最重" << c << endl;}
}
system("pause");
return 0;
}
运行结果图:
- 引申:比较输入的三个数的大小,并按照降序排列
代码:
/*********************************************************************
程序名: 选择结构案例练习02
作者: Sweitena
日期: 2021-03-18 09:20
说明: 比较输入的三个数大小,并进行排序
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int a, b, c, t;
a = 0;
b = 0;
c = 0;
t = 0;
cout << "请分别输入三只小猪的重量:" << endl;
cin >> a;
cin >> b;
cin >> c;
if (a > b)
{
t = a;
if (c > t)
{
t = c;
cout << "③> ①> ②" << endl;
}
else
{
//已知a>c 且 a>b 不确定b和c的关系
if (b > c)
{cout << "①> ②> ③" << endl;}
else
{cout << "①> ③> ②" << endl;}
}
}
else
{ //已知a<b 不确定a与c的关系
t = b;
if (c > t)
{
t = c;
cout << "③> ②> ①" << endl;
}
else
{
//已知c<b 且 a<b 不确定a与c的关系
if (a > c)
{cout << "②> ①> ③" << endl;}
else
{cout << "②> ③> ①" << endl;}
}
}
system("pause");
return 0;
}
运行结果图:
1.1.3 三目运算符
- 作用:通过三目运算符实现简单判断
代码:
/*********************************************************************
程序名: 选择结构_三目运算符
作者: Sweitena
日期: 2021-03-18 09:30
说明: 【作用】通过三目运算符实现简单判断
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int a, b, c;
a = 10;
b = 20;
c = 0;
//使用三目运算符比较a和b,返回较大值
c = a > b ? a : b;
cout << "c = " << c << endl;
//C++中三目运算符返回的是变量,可以继续赋值
( a > b ? a : b ) = 100;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
运行结果图:
1.1.4 switch 结构
- 作用:switch结构可以执行多条件分支语句
案例描述:
- 给电影打分,分三个等级:
- A级:4.5~5.0分,电影非常好
- B级:3.0~4.5分,电影一般
- C级:3.0分一下,烂片
代码:
/*********************************************************************
程序名: 选择结构_switch结构
作者: Sweitena
日期: 2021-04-01 09:35
说明: 【作用】执行多条件分支语句
【案例需求】给电影打分,分三个等级,A级:4.5-5.0分;B级:3.0-4.5分;C级:3.0分以下
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//1.提示用户给电影打分
cout << "请给电影打分(0~5):" << endl;
//2.用户开始进行打分
float score;
char flag;
score = 0;
cin >> score;
cout << "您打的分数为:" << score << endl;
//3.根据用户输入的分数来提示用户最后的结果
flag = (score > 4.5 || score == 4.5) ? 'A' : (score > 3.0 || score == 3.0) ? 'B' : 'C';
switch (flag) {
case 'A':
cout << "A级-您认为电影非常好" << endl;
break;
case 'B':
cout << "B级-您认为电影一般" << endl;
break;
case 'C':
cout << "C级-您认为是个烂片" << endl;
break;
}
system("pause");
return 0;
}
运行结果图:
1.2 循环结构
1.2.1 while 语句
- while语句:只要循环条件的结果为真,就执行循环
- 语法:while (循环条件){ 循环语句 }
- 无限循环:while(1) { 循环语句 }
案例描述:
- 实现从0累加到n,求和并返回n个数的和
代码:
/*********************************************************************
程序名: 循环结构_while语句
作者: Sweitena
日期: 2021-04-01 11:07
说明: 【作用】满足循环条件,执行循环语句
【案例需求】实现从0累加到n,求和
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int i, n, S;
i = 0;
n = 0;
S = 0;
cout << "请输入一个n:" << endl;
cin >> n;
while (i < n) {
i = i + 1; // i++;
S = S + i;
}
cout << n << "个数做和为:" << S << endl;
system("pause");
return 0;
}
运行结果图
❀案例练习01:猜数字
- 注意:生成随机数时,可以引入< ctime >头文件,添加随机数种子
案例描述:
- 系统随机生成一个1到100之间的数字,玩家进行猜测;
- 如果猜错,提示玩家数字过大或过小;
- 如果猜对,恭喜玩家胜利,并且退出游戏。
代码:
/*********************************************************************
程序名: 循环结构案例练习01
作者: Sweitena
日期: 2021-04-01 11:26
说明: 猜数字
*********************************************************************/
#include <iostream>
using namespace std;
#include <ctime>//系统头文件
int main() {
//添加随机数种子,作用:利用当前系统时间生成随机数
srand((unsigned int)time(NULL));
int num;
int val;
val = 0;
num = rand() % 100 + 1; //生成0-100的随机数
//cout << num << endl;
while (1) {
cout << "请输入一个数" << endl;
cin >> val;
if (val == num)
{
cout << "恭喜您猜对了!" << endl;
break; //跳出循环,即退出游戏
}
else if (val > num)
{
cout << "大了" << endl;
}
else
{
cout << "小了" << endl;
}
}
system("pause");
return 0;
}
运行结果图:
1.2.2 do…while 语句
- 与 while 的区别在于do…while 会先执行一次循环语句,再判断循环条件
- 语法:do { 循环语句 } while (循环条件) ;
- 无限循环:do { 循环语句 } while (1) ;
案例描述:
- 实现从0累加到n,求和并返回n个数的和
代码:
/*********************************************************************
程序名: 循环结构_do...while
作者: Sweitena
日期: 2021-04-03 19:20
说明: 【作用】满足循环条件,执行循环语句
【案例需求】实现从0累加到n,求和
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int i, n, S;
i = 0;
n = 0;
S = 0;
cout << "请输入一个n:" << endl;
cin >> n;
do {
i = i + 1;// i++;
S = S + i;
} while (i < n);
cout << n << "个数做和为:" << S << endl;
system("pause");
return 0;
}
运行结果图:
❀案例练习02:水仙花数
案例描述:
- 水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身
- 例如:13+53+33=153
- 请利用 do…while 语句,求出所有3位数中的水仙花数
案例分析:
代码:
/*********************************************************************
程序名: 循环结构案例练习02
作者: Sweitena
日期: 2021-04-03 19:36
说明: 找到所有3位的水仙花数
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int bai, shi, ge, num;
bai = 0;
shi = 0;
ge = 0;
num = 100;
do
{
//cout << num <<endl;
ge = num % 10;
shi = (num / 10 ) % 10;
bai = num / 100;
if (ge * ge * ge + shi * shi * shi + bai * bai * bai == num)
{cout << num << endl;}
num++;
} while (num < 1000);
system("pause");
return 0;
}
运行结果图:
1.2.3 for 循环语句
- 语法:for (起始表达式; 条件表达式; 末尾循环体) { 循环语句;}
- 无限循环:for ( ; ; ) { 循环语句;}
代码:
/*********************************************************************
程序名: 循环结构-for
作者: Sweitena
日期: 2021-04-03 20:30
说明: 【作用】满足循环条件,执行循环语句
【案例需求】实现从0累加到n,求和
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//for(起始表达式; 条件表达式; 末尾循环体) {循环语句;}
int i, n, S;
i = 0;
n = 0;
S = 0;
cout << "请输入一个n:" << endl;
cin >> n;
for (; i < n + 1; i++)
{
//注意这里的判断条件变成n+1了
S = S + i;
}
cout << n << "个数做和为:" << S << endl;
system("pause");
return 0;
}
运行结果图:
❀案例练习03:敲桌子
案例描述:
- 从1开始数到数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余数字直接打印输出。
案例分析:
代码:
/*********************************************************************
程序名: 循环结构案例练习03
作者: Sweitena
日期: 2021-04-03 20:41
说明: 从1到100,个位数或者十位数含有7,或者是7的倍数就打印敲桌子,其余数字直接输出
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int num, b, c;
num = 1;
b = 0;
c = 0;
for ( ; num < 101; num++ )
{
//cout << num << endl;
b = num / 10; //十位的数字
c = num % 10; //个位的数字
if ((num % 7 == 0 ) || (b == 7 ) || (c == 7))
{cout << "敲桌子" << endl;}
else
{cout << num << endl;}
}
system("pause");
return 0;
}
运行结果图:
1.2.4 嵌套循环
- 作用:在循环体中再嵌套一层循环,解决一些实际问题
代码:
/*********************************************************************
程序名: 循环结构-嵌套循环
作者: Sweitena
日期: 2021-04-03 21:31
说明: 打印10*10的矩阵形式的星星
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
cout << "方法一:利用for循环,先打印一行星图,再嵌套" << endl;
int i, j;
//利用for循环,先打印一行星图
for (i = 0; i < 10; i++)
{ //外层循环
for (j = 0; j < 10; j++)
{ //内层循环
cout << "* " ; //打印出来一行
}
cout << endl;
} //然后再设置一个循环把“打印一行”的代码,循环10次
cout << "方法二:不用嵌套也可以实现星图" << endl;
int k;
for (k = 0; k < 5; k++)
{cout << "* * * * * * " << endl; } //打印出来一行
system("pause");
return 0;
}
运行结果图:
❀案例练习04:乘法口诀表
案例描述:
- 利用嵌套循环,实现九九乘法表
案例分析:
代码:
/*********************************************************************
程序名: 循环结构案例练习04
作者: Sweitena
日期: 2021-04-04 08:57
说明: 打印乘法口诀表
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int r, c, product;
product = 0;
for (r = 1; r <= 9; r++)
{
//cout << r;
for (c = 1; c <= r; c++)
{
//cout << c;
product = c * r;
cout << c << "x" << r << "=" << product << " ";
}
cout << endl; //换行
}
system("pause");
return 0;
}
运行结果图:
1.2.5 跳转语句:3种
- 作用:更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁。
1. break 语句
- 作用:用于跳出选择结构或者循环结构
- 出现在 switch 条件语句中,作用是终止 case 并跳出 switch
- 出现在循环语句中,作用是跳出当前的循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
2. continue 语句
- 作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环
3. goto 语句
- 作用:可以无条件跳转语句
- 语法:goto 标记;
- 如果标记的名称存在,执行到goto语句时,会跳转到标记的位置
【注意】在任何编程语言中,都不建议使用 goto 语句
二、数组
- 所谓数组,就是一个集合,里面存放了相同类型的数据元素
- 特点1:数组中的每个数组元素都是相同的数据类型
- 特点2:数组是由连续的内存位置组成的
2.1 一维数组
2.1.1 定义
一维数组定义的三种方式:
- 数据类型 数组名 [ 数组长度 ] ;
- 数据类型 数组名 [ 数组长度 ] = { 值1,值2,… };
- 数据类型 数组名 [ ] = { 值1,值2,…};
代码:
/*********************************************************************
程序名: 一维数组
作者: Sweitena
日期: 2021-04-04 14:33
说明: 数组的定义
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
/********** 三种定义形式:********************
1.数据类型 数组名[数组长度];
2.数据类型 数组名[数据长度] = {值1, 值2, ...};
3.数据类型 数组名[ ] = {值1, 值2, ...};
**********************************************/
//①第一种定义方式
cout << "第一种定义方式:" << endl;
int arr[5];
arr[0] = 10;// 给数组元素赋值
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
cout << arr[0] << " "; // 访问数组元素
cout << arr[1] << " ";
cout << arr[2] << " ";
cout << arr[3] << " ";
cout << arr[4] << " ";
cout << endl;
//②第二种定义方式
cout << "第二种定义方式:" << endl;
int arr2[5] = {10, 20, 30, 40};
int i;
for (i = 0; i < 5; i++)
{
cout << arr2[i] << " ";
}
cout << endl;
//③第三种定义方式
cout << "第三种定义方式:" << endl;
int arr3[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int j;
for (j = 0; j < 10; j++)
{
cout << arr3[j] << " ";
}
cout << endl;
system("pause");
return 0;
}
运行结果图:
2.1.2 数组名用途
一维数组名称的用途:
- 可以统计整个数组在内存中的长度
- 可以获取数组在内存中的首地址
代码:
/*********************************************************************
程序名: 一维数组
作者: Sweitena
日期: 2021-04-04 14:38
说明: 数组名的用途
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//数组名用途:
int arr3[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
//1.可以通过数组名统计整个数组或元素占用内存的大小
cout << "整个数组占用内存大小为:" << sizeof(arr3) << endl;
cout << "元素占用内存大小为:" << sizeof(arr3[0]) << endl;
cout << "数组中元素的个数:" << sizeof(arr3) / sizeof(arr3[0]) << endl;
//2.可以用过数组名查看数组首地址
cout << "数组首地址为:" << arr3 << endl;
cout << "数组首地址为:" << (int)arr3 << endl; //16进制转10进制
cout << "数组中第一个元素的地址为:" << &arr3[0] << endl;
cout << "数组中第一个元素的地址为:" << (int)&arr3[0] << endl; //16进制转10进制
cout << "数组中第二个元素的地址为:" << (int)&arr3[1] << endl;
system("pause");
return 0;
}
运行结果图:
❀案例练习01:五只小猪称体重
案例描述:
- 在一个数组中记录了五只小猪的体重
- 例如:int arr[5] = { 300 , 350 , 200 , 400 , 250 };
- 找出并打印最重的小猪体重
代码:
/*********************************************************************
程序名:一维数组案例练习01
作者: Sweitena
日期: 2021-04-04 15:30
说明: 五只小猪称体重,找出并打印最重的小猪的体重
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
int arr[] = {300, 350, 200, 400, 250};
int max = 0; //先设置一个最大值
int num = 0;
for (int i = 0; i < 5; i++)
{
if (arr[i] > max)
{
max = arr[i]; //更新最大值
num = i;
}
}
cout << "第" << num + 1 << "只小猪最重,体重为:" << max << endl;
system("pause");
return 0;
}
运行结果图:
❀案例练习02:元素逆置
案例描述:
- 请声明一个5个元素的数组,并且将元素逆置
- 例如:原数组元素为:1,3,2,5,4; 逆置后输出结果为:4,5,2,3,1;
案例分析:
代码:
/*********************************************************************
程序名: 一维数组案例02
作者: Sweitena
日期: 2021-04-04 16:11
说明: 数组元素逆置,首尾元素交换
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
/*****1.创建数组*****/
int arr[] = {1, 3, 2, 5, 4};
cout << "数组逆置前:" << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}
cout << endl;
/*****2.实现逆置******/
//2.1记录起始下标位置
//2.2记录末尾下标位置
//2.3起始下标与末尾下标的元素互换
//2.4起始位置++,末尾位置--
//循环执行2.1-2.4操作,直到起始位置>=末尾位置
int start = 0; //起始元素下标
int end = sizeof(arr) / sizeof(arr[0]) - 1; //末尾元素下标
//定义一个临时内存
int temp;
//交换起始元素和末尾元素
while (start < end)
{
temp = arr[start]; //实现元素互换
arr[start] = arr[end];
arr[end] = temp;
start++; //下标更新,往中间聚拢
end--;
}
/******3.打印逆置后的数组*******/
cout << "数组元素逆置后:" << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
运行结果图:
❀案例练习03:冒泡排序法
案例描述:
- 作用:最常用的排序算法,对数组内元素进行排序
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
- 重复以上的步骤,每次比较次数-1,直到不需要比较。
- 示例:将数组{ 4,2,8,0,5,7,1,3,9 }进行升序排序
案例分析:
代码:
/*********************************************************************
程序名: 一维数组案例03
作者: Sweitena
日期: 2021-04-04 19:14
说明: 冒泡排序法实现数组元素升序排列
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//1.创建数组
int arr[] = {4, 2, 8, 0, 5, 7, 1, 3, 9};
int num = sizeof(arr) / sizeof(arr[0]); //确定元素有几个
cout << "排序前:" << endl;
for (int i = 0; i < num; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//2.开始冒泡排序
//2.1 先对相邻的两个元素比较并交换位置:每轮对比次数 = 元素个数 - 排序轮数 - 1
//2.2 排序总轮数 = 元素个数 - 1
for (int j = 0; j < num - 1; j++) //外层循环 做几轮比较 9个元素 需要比较8轮
{
for (int i = 0; i < num - j - 1; i++) //内层循环 每轮需要比较几次
{
if (arr[i] > arr[i + 1])
{
//交换两个元素位置
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
//3.打印排序后的数组
cout << "排序后:" << endl;
for (int i = 0; i < num; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
运行结果图:
2.2 二维数组
2.2.1 定义
-
二维数组就是在一维数组上多加一个维度
-
二维数组定义的四种方式:
- 数据类型 数组名 [ 行数 ] [ 列数 ] ;
- 数据类型 数组名 [ 行数 ] [ 列数 ] = { {数据1,数据2},{数据3,数据4} };
- 数据类型 数组名 [ 行数 ] [ 列数 ] = {数据1,数据2,数据3,数据4};
- 数据类型 数组名 [ ] [ 列数 ] = {数据1,数据2,数据3,数据4};
(建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性)
代码:
/*********************************************************************
程序名: 二维数组
作者: Sweitena
日期: 2021-04-06 08:55
说明: 数组的定义
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//二维数组的定义
/****
1.数据类型 数组名[ 行数 ][ 列数 ];
2.数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2},{数据3,数据4} };
3.数据类型 数组名[ 行数 ][ 列数 ] ={ 数据1,数据2,数据3,数据4 };
4.数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4 };
****/
//第①种定义方式
cout << "第一种定义方式:" << endl;
int arr[2][3]; //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;
}
//第②种定义方式
cout << "第二种定义方式:" << endl;
int arr2[2][3] = {{1, 2, 3}, {4, 5, 6}};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr2[i][j] << " ";
}
cout << endl;
}
//第③种定义方式
cout << "第三种定义方式:" << endl;
int arr3[2][3] = {1, 2, 3, 4, 5, 6};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr3[i][j] << " ";
}
cout << endl;
}
//第④种定义方式
cout << "第四种定义方式:" << endl;
int arr4[ ][3] = {1, 2, 3, 4, 5, 6};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr4 [i][j] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
运行结果图:
2.2.2 数组名用途
二维数组名称的用途:
- 可以统计整个数组在内存中的长度
- 可以获取数组在内存中的首地址
代码:
/*********************************************************************
程序名: 二维数组
作者: Sweitena
日期: 2021-04-06 08:58
说明: 数组名的用途
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
//二维数组名称用途
int arr4[ ][3] = {1, 2, 3, 4, 5, 6};
//1.可以查看占用内存大小
cout << "二维数组占用内存空间为:" << sizeof(arr4) << endl;
cout << "二维数组第一行占用内存为:" << sizeof(arr4[0]) << endl;
cout << "二维数组第一个元素占用内存为:" << sizeof(arr4[0][0]) << endl;
cout << "二维数组行数:" << sizeof(arr4) / sizeof(arr4[0]) << endl;
cout << "二维数组列数:" << sizeof(arr4[0]) / sizeof(arr4[0][0]) << endl;
//可以查看二维数组的首地址
cout << "二维数组的首地址为:" << arr4 << endl;
cout << "二维数组的首地址为:" << (int)arr4 << endl;
cout << "二维数组第一行首地址为:" << arr4[0] << endl;
cout << "二维数组第一行首地址为:" << (int)arr4[0] << endl;
system("pause");
return 0;
}
运行结果图:
❀案例练习:考试成绩统计
案例描述:
- 有三名同学(张三、李四、王五),在一次考试中的成绩分别如下表
- 请分别输出三名同学的总成绩
代码:
/*********************************************************************
程序名: 二维数组案例
作者: Sweitena
日期: 2021-04-06 11:00
说明: 考试成绩统计,分别输出每名同学的总成绩
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
int main() {
//创建二维数组
int scores[3][3] = {{100, 100, 100}, {90, 50, 100}, {60, 70, 80}} ; //第二种定义方式
int sum = 0;
string names[3] = {"张三", "李四", "王五"}; //创建名字的一维数组
//让每一行的数据相加
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
sum = scores[i][j] + sum; //相当于sum += score[i][j];
}
cout << names[i] << "的总成绩为:" << sum << endl;
}
system("pause");
return 0;
}
运行结果图:
三、函数
- 作用:将一段经常使用的代码封装起来,减少重复代码。
- 一个较大的程序一般分为若干个程序块,每个模块实现特定的功能。
3.1 函数定义
-
函数的定义一般主要有5个步骤:
- 返回值类型
- 函数名
- 参数表列
- 函数体语句
- return表达式
-
语法:
返回值类型 函数名(参数列表)
{
函数体语句;
return 表达式;
}
- 举例分析:
3.2 函数声明
-
作用:告诉编译器函数名称及如何调用函数
-
函数的声明可以多次,但是函数的定义只能有一次。
-
举例分析:
针对上面的加法函数add()
,以下是函数声明:
int add(int num1, int num2);
在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int add(int, int);
3.3 调用函数
- 作用:使用定义好的函数。
- 语法:
函数名 ( 参数 )
代码:
/*********************************************************************
程序名: 函数定义、声明、调用
作者: Sweitena
日期: 2021-04-06 11:19
说明: 以加法函数为例
*********************************************************************/
#include <iostream>
using namespace std;
//函数声明
int add(int num1, int num2); //加法函数的声明
int main() {
int a, b, c;
a = 5;
b = 10;
//调用函数
c = add(a, b); //调用加法函数
cout << c << endl;
system("pause");
return 0;
}
//函数定义
/****************实现一个加法函数****************/
/***功能:传入两个整型数据,计算相加结果并返回***/
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
运行结果图:
3.4 函数参数
3.4.1 向函数传递参数的方式
-
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
-
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
-
当调用函数时,有三种向函数传递参数的方式:
- 传值调用
该方法把参数的实际值赋值给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 - 指针调用
该方法把参数的地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 - 引用调用
该方法把参数的引用赋值给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
- 传值调用
【注意】本章只介绍第一种值传递方式,后两种在指针和引用那两章里有详细解释。
3.4.1.1 传值调用
举例说明:修改函数内的形式参数对实际参数没有影响。
代码:
/*********************************************************************
程序名: 函数参数-值传递
作者: Sweitena
日期: 2021-04-09 19:54
说明: 定义一个实现两个数字进行交换的函数
*********************************************************************/
#include <iostream>
using namespace std;
//函数声明
void swap(int num1, int num2); //交换函数
int main()
{
int a, b;
a = 10;
b = 20;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
/***********************************************************
当我们做值传递时,函数的形参发生变化,并不影响实参
***********************************************************/
cout << "调用swap()函数" << endl;
swap(a, b); //调用函数
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
//函数定义
/******************交换函数*******************/
/***功能:传入两个整型数据,交换2个数并返回***/
void swap(int num1, int num2) //函数不需要返回值,所以写void
{
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;
}
运行结果图:
3.4.1.2 指针调用
见4.5.1节。
3.4.1.3 引用调用
见5.3.1节。
3.4.2 函数的常见样式
常见的函数样式有4种:
- 无参无返
- 有参无返
- 无参有返
- 有参有返
代码:
/*********************************************************************
程序名: 函数的常见样式
作者: Sweitena
日期: 2021-04-09 20:09
说明: 1无参无返 2有参无返 3无参有返 4有参有返
*********************************************************************/
#include <iostream>
using namespace std;
//1.无参无返
void test01()
{
cout << "this is test01 for 无参无返" << endl;
}
//2.有参无返
void test02(int a)
{
cout << "this is test02 for 有参无返 a =" << a << endl;
}
//3.无参有返
int test03()
{
cout << "this is test03 for 无参有返" << endl;
return 200;
}
//4.有参有返
int test04(int b)
{
cout << "this is test04 for 有参有返 b=" << b << endl;
return b;
}
int main()
{
test01(); //无参无返调用
test02(100); //有参无返调用
int num1 = test03(); //无参有返调用
int num2 = test04(3000); //有参有返调用
system("pause");
return 0;
}
运行结果图:
3.5 Lambda 函数
- C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。
- Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。
- Lambda 表达式本质上与函数声明非常类似。
- 在 lambda 函数的定义式中,参数列表和返回类型都是可选部分,而捕捉列表和函数体都可能为空,C++ 中最简单的 lambda 函数只需要声明为:
[]{};
- 语法:
[ capture ]( parameters ) mutable -> return-type{ statement }
其中:
- [capture]:捕捉列表。捕捉列表总是出现在 lambda 表达式的开始处。事实上,[] 是 lambda 引出符。编译器根据该引出符判断接下来的代码是否是 lambda 函数。捕捉列表能够捕捉上下文中的变量供 lambda 函数使用。
- (parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号 () 一起省略。
- mutable:mutable 修饰符。默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。
- ->return_type:返回类型。用追踪返回类型形式声明函数的返回类型。出于方便,不需要返回值的时候也可以连同符号 -> 一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。
- {statement}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
【注意】详细解释将在后面的笔记介绍,目前对于基础知识部分有点超纲了吧。
3.6 函数的分文件编写
- 作用:让代码结构更加清晰
- 函数分文件编写一般有4个步骤:
- 创建.h后缀名的头文件
- 创建.cpp后缀名的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
- 分文件编写的过程举例,依据3.4.1节提到的swap()代码:
step1: 创建项目。
- 步骤:文件 —— 新建… —— 项目… —— 基本 —— 控制台应用程序 —— C++项目 —— 名称(测试分文件编写swap) —— 确定。
- 观察到此时项目名称下已经包含main.cpp文件。
step2: 创建swap.h的头文件,包含函数声明
- 右键单击“测试分文件编写swap”(项目名称) —— 新建单元 —— 弹出的新文件重命名为swap.h
step3: 创建swap.cpp的源文件,包含函数定义
- 步骤同上:右键单击“测试分文件编写swap”(项目名称) —— 新建单元 —— 弹出的新文件重命名为swap.cpp
step4: 在main.cpp文件中,可以调用swap()函数
- 注意文件之间的关联关系。
- 源文件swap.cpp和main.cpp中都需要包含swap.h文件,即
#include "swap.h"
- 头文件swap.h和源文件main.cpp中都需要包含C++的原始框架,即
#include <iostream>
和using namespace std;
step5: 最后,编译运行main.cpp
四、指针
4.1 指针的基本概念
- 作用:可以通过指针间接访问内存。
- 指针是一个变量,其值为另一个变量的地址,即:内存位置的直接地址。
- 可以理解为:指针就是一个地址,可以通过指针来保存一个地址。
4.1.1 指针变量的定义和使用
- 指针变量定义语法:
数据类型 * 变量名;
代码:
/*********************************************************************
程序名: 指针的定义和使用
作者: Sweitena
日期: 2021-04-12 10:47
说明: 【作用】可以通过指针间接访问内存
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
/************************************************/
/************* 1.定义指针 *******************/
/************************************************/
int a = 10; //实际变量的声明:一个整型的变量
int *p; //指针变量的声明:一个整型的指针
p = &a; //在指针变量p中存储变量a的地址
cout << "a的地址 &a = " << &a << endl;
cout << "指针变量 p = " << p << endl;
/************************************************/
/************* 2.使用指针 *******************/
/************************************************/
cout << "访问指针中地址的值 *p = " << *p << endl; //通过解引用的方式找到指针指向的内存
*p = 1000; //指针前加*代表解引用,找到指针指向的内存中的数据
cout << "更改之后的 *p = " << *p << endl;
cout << "更改之后的 a = " << a << endl;
system("pause");
return 0;
}
运行结果图:
4.1.2 指针所占内存空间
- 指针也是一种数据类型。
- 所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。
代码:
/*********************************************************************
程序名: 指针所占的内存空间
作者: Sweitena
日期: 2021-04-12 14:08
说明: 根据指针所指向的变量的数据类型定义不同数据类型的指针;
在32位操作系统下,指针所占的内存空间都是4个字节。
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int *p;
p = &a;
cout << "指针p所占用的内存空间为:" << sizeof(p) << endl;
cout << "整型指针int *所占用的内存空间为:" << sizeof(int *) << endl;
cout << "浮点型指针float *所占用的内存空间为:" << sizeof(float *) << endl;
cout << "字符型指针char *所占用的内存空间为:" << sizeof(char *) << endl;
system("pause");
return 0;
}
运行结果图:
4.2 const 修饰指针
- const修饰指针有三种情况:
- const 修饰指针——常量指针(指针指向的值不可以改,指针指向可以改);
- const 修饰常量——指针常量(指针指向的值可以改,指针指向不可以改);
- const既修饰指针,又修饰常量(指针指向的值不可以改,指针指向不可以改)。
4.2.1 常量指针 const int *p = &a
//初始代码:
int a = 10; //a的地址:0x0011
int b = 10; //b的地址:0x0022
int *p = &a; //将a的地址存储到p中,让p指向a
4.2.2 指针常量 int *const p = &a
//初始代码:
int a = 10; //a的地址:0x0011
int b = 10; //b的地址:0x0022
int *p = &a; //将a的地址存储到p中,让p指向a
4.2.3 既修饰指针又修饰常量 const int *const p = &a;
//初始代码:
int a = 10; //a的地址:0x0011
int b = 10; //b的地址:0x0022
int *p = &a; //将a的地址存储到p中,让p指向a
4.3 空指针和野指针
4.3.1 空指针
- 定义:空指针指向内存中编号为0的空间
- 作用:空指针用于给指针向量初始化
- 【注意】空指针指向的内存是不可以访问的
在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。 - C++11标准后,用nullptr来表示空指针。
代码:
/*********************************************************************
程序名: 空指针
作者: Sweitena
日期: 2021-04-12 14:15
说明: NULL 指针是一个定义在标准库中的值为零的常量
*********************************************************************/
#include <iostream>
using namespace std;
int main() {
/**********定义一个整型指针**********/
int a = 10;
int *g = &a; //整型指针变量g指向a的地址
cout << "g的值为:" << g << endl;
/**********定义一个空指针**********/
int *p = NULL; //指针p是值为0的常量,空指针用于给指针变量进行初始化
cout << "p的值为:" << p << endl;
/*
//不能访问空指针,内存编号0-255为系统占用内存,不允许用户访问
*p = 100;
cout << *p << endl;
*/
system("pause");
return 0;
}
运行结果图:
- 如需检查一个空指针,可以使用 if 语句,如下所示:
if(p) /* 如果 p 非空,则完成... */
if(!p) /* 如果 p 为空,则完成... */
4.3.2 野指针
- 定义:指针变量指向非法的内存空间,野指针指向的位置是不可知的。
/*********************************************************************
程序名: 野指针
作者: Sweitena
日期: 2021-04-12 14:22
说明: 在程序中,尽量避免出现野指针
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
//指针变量p指向内存地址编号位0x1100的空间
int *p = (int *) 0x1100;
//访问野指针会报错,但是野指针不是我们申请的空间,因此不要访问
//cout << *p << endl; //没有输出,是空的
system("pause");
return 0;
}
4.4 指针的运算
4.4.1 指针的算术运算
- 指针是一个用数值表示的地址,可以对指针执行算术运算。可以对指针进行四种算术运算:++、–、+、-。
4.4.1.1 递增一个指针
- 假设 p 是一个指向地址1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算:
p++
。 - 在执行完上述的运算之后,p 将指向位置 1004,因为 p 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 个字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果 p 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。
代码:
/*********************************************************************
程序名: 指针递增运算
作者: Sweitena
日期: 2021-04-12 14:25
说明: 习惯使用指针代替数组,变量指针可以递增,而数组不能递增
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
int arr[3] = {1, 2, 3}; //定义一个名为arr的一维数组
int *p; //定义一个名为p的整型指针
p = &arr[0]; //令整型指针p指向数组首地址
/*** 【补充】数组名是数组的首地址,所以也可以写成 p = &arr ***/
for (int i = 0; i < 3; i++)
{
cout << "第" << i << "个元素的地址是:" << p << endl;
cout << "\t 值是:" << *p << endl;
p++; //移动到下一个元素的位置
}
system("pause");
return 0;
}
运行结果图:
4.4.1.2 递减一个指针
- 同样地,对指针进行递减运算,即把值减去其数据类型的字节数。
代码:
/*********************************************************************
程序名: 指针递减运算
作者: Sweitena
日期: 2021-04-12 14:28
说明: 与递增相反的去理解,指针往回走
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
int arr[3] = {1, 2, 3}; //定义一个名为arr的一维数组
int *p; //定义一个名为p的整型指针
p = &arr[3 - 1]; //令整型指针p指向数组最后一个元素的地址
/***【补充】一共有3个元素,用“元素个数-1”表示取到该数组的最后一个元素 ***/
for (int i = 0; i < 3; i++)
{
cout << "第" << i << "个元素的地址是:" << p << endl;
cout << "\t 值是:" << *p << endl;
p--; //移动到下一个元素的位置
}
system("pause");
return 0;
}
运行结果图:
4.4.2 指针的比较运算
- 指针可以用关系运算符进行比较,如 ==、< 和 >。
- 如果 p1 和 p2 指向两个相关的变量,比如:同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。
代码:
/*********************************************************************
程序名: 指针比较运算
作者: Sweitena
日期: 2021-04-12 14:29
说明: 可以比较指针中存储的地址的大小
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
int arr[3] = {1, 2, 3}; //定义一个名为arr的一维数组
int *p1, *p2, *p3; //定义三个名为p1、p2、p3的整型指针
p1 = &arr[0]; //令指针p1指向数组第一个元素的地址
p2 = &arr[1]; //令指针p2指向数组第二个元素的地址
p3 = &arr[2]; //令指针p2指向数组第三个元素的地址
if (p1 <= p3) //指针p1中的地址是否小于指针p3中的地址
{
p1++; //指针指向下一个位置,p1会指向第二个元素,相当于p2
cout << "此时p1的地址为:" << p1 << endl;
cout << "p1指向的元素为:" << *p1 << endl;
}
system("pause");
return 0;
}
运行结果图:
4.5 指针和数组
4.5.1 指针数组
- 当我们想要让数组存储指向 int 或其他数据类型的指针时,可以使用指针数组。
- 指针数组的语法:
数据类型 * 变量名 [ 数组长度 ];
代码片段:
//下面是一个指向整数的指针数组的声明:
int *p[max];
//在这里,把 p 声明为一个数组,由max个整数指针组成。因此,p中的每个元素,都是一个指向int值的指针。
//也就是说p[0]存放的是一个指针,这个指针指向数组的第一个元素,可以用解引用*p[0]得出元素的值。
代码:
/*********************************************************************
程序名: 指针数组
作者: Sweitena
日期: 2021-04-16 10:08
说明: 【举例】将三个整数存放在指针数组中
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
int arr[3] = {1, 2, 3}; //定义一个名为arr的一维数组,包含3个元素
int *p[3]; //定义一个名为p的指针数组,长度为3
for (int i = 0; i < 3; i++) //用for循环将数组中元素的地址存放在指针中
{
p[i] = &arr[i];
}
for (int j = 0; j < 3; j++) //用for循环打印数组
{
cout << "原数组:" << "arr[" << j << "]=" << arr[j] << endl;
cout << "地址:" << p[j] << endl;
cout << "通过指针数组显示原数组:" << "*p[" << j << "]=" << *p[j] << endl;
}
system("pause");
return 0;
}
运行结果图:
- 也可以用一个指向字符的指针数组来存储一个字符串列表,代码如下。
【 这是菜鸟教程里的笔记的内容:char *p[3]
是指针数组,它的本质是存储指针的数组,即存储char
类型的指针的数组,数组内的每个元素都是一个指针,指向一个存储char
类型的地址。】
代码:
#include <iostream>
using namespace std;
int main()
{
const char *p[3] = {"zara", "hina", "nuha"}; //用一个指向字符的指针数组来存储一个字符串列表
cout << "输出p[i]如下:" << endl;
cout << "p[0]=" << p[0] << " ";
cout << "p[1]=" << p[1] << " ";
cout << "p[2]=" << p[2] << " ";
cout << endl;
cout << endl;
cout << "输出&(p[i])如下:" << endl;
cout << "&(p[0])=" << &(p[0]) << " ";
cout << "&(p[1])=" << &(p[1]) << " ";
cout << "&(p[2])=" << &(p[2]) << " ";
cout << endl;
cout << endl;
cout << "输出*p[i]如下:" << endl;
cout << "*p[0]=" << *p[0] << " ";
cout << "*p[1]=" << *p[1] << " ";
cout << "*p[2]=" << *p[2] << " ";
cout << endl;
cout << endl;
cout << "输出&(*p[i])如下:" << endl;
cout << "&(*p[0])=" << &(*p[0]) << " ";
cout << "&(*p[1])=" << &(*p[1]) << " ";
cout << "&(*p[2])=" << &(*p[2]) << " ";
cout << endl;
cout << endl;
cout << "输出p[0][i]如下:" << endl;
cout << "p[0][0]=" << p[0][0] << " ";
cout << "p[0][1]=" << p[0][1] << " ";
cout << "p[0][2]=" << p[0][2] << " ";
cout << "p[0][3]=" << p[0][3] << " ";
cout << endl;
cout << endl;
cout << "输出&(p[0][i])如下:" << endl;
cout << "&(p[0][0])=" << &(p[0][0]) << " ";
cout << "&(p[0][1])=" << &(p[0][1]) << " ";
cout << "&(p[0][2])=" << &(p[0][2]) << " ";
cout << "&(p[0][3])=" << &(p[0][3]) << " ";
cout << endl;
cout << endl;
cout << "输出*p[0]+i如下:" << endl;
cout << "*p[0] + 1 =" << *p[0] + 1 << " ";
cout << "*p[0] + 2 =" << *p[0] + 2 << " ";
cout << "*p[0] + 3 =" << *p[0] + 3 << " ";
cout << endl;
cout << endl;
system("pause");
return 0;
}
运行结果图:
4.5.2 指向数组的指针
- 利用指针访问数组元素,下面给出了一个指向 int 型的指针,它可以存储一个 int 类型的变量。一旦我们有了 p 中的地址,*p 将给出存储在 p 中相应地址的值。
代码:
/*********************************************************************
程序名: 指向数组的指针
作者: Sweitena
日期: 2021-04-16 10:12
说明: 【作用】利用指针访问数组元素
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
//1.创建数组
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//2.正常输出数组元素
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//3.用指针访问数组元素
int *p = arr; //arr是数组的首地址
for (int j = 0; j < 10; j++)
{
cout << *p << " " ;
p++; //指针指向下一个位置
}
cout << endl;
system("pause");
return 0;
}
运行结果图:
- 使用数组名作为常量指针是合法的,因此,
*( arr + 4)
是一种访问arr[4]
数据的合法方式。一旦把第一个元素的地址存储在p中,可以使用*p 、 *(p+1) 、 *(p+2)
等来访问数组元素。
代码:
/*********************************************************************
程序名: 指向数组的指针
作者: Sweitena
日期: 2021-04-16 10:14
说明: 【举例】针对一个含有5个double型变量的数组,用指针指向该数组
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
//创建 数组 和 指向数组的指针
double arr[] = {0.1, 3.14, 17.3, 102.4, 5.8};
double *p; //定义一个名为p的双精度浮点型指针
p = arr;
// 两种方式输出数组中每个元素的值
for (int i = 0; i < 5; i++)
{
cout << "*(p + " << i << ")" << "=" << *(p + i) << endl;
cout << "*(arr +" << i << ") " << "=" << *(arr + i) << endl;
}
system("pause");
return 0;
}
运行结果图:
4.6 指针和函数
4.6.1 指针调用(地址传递)
- 指针调用:该方法把参数的地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
- 作用:利用指针作函数参数,可以修改实参的值。
代码:
/*********************************************************************
程序名: 值传递vs地址传递
作者: Sweitena
日期: 2021-04-16 10:25
说明: 如果是地址传递,可以修改实参
*********************************************************************/
#include <iostream>
using namespace std;
//函数声明
void swap01(int num1, int num2);//实现两个数字交换的函数:值传递
void swap02(int *p1, int *p2); //实现两个数字交换的函数:地址传递
int main()
{
int a, b;
a = 10;
b = 20;
//1.值传递
cout << "entering 值传递函数:" << endl;
swap01( a, b );
cout << "swap01中的a = " << a << endl;
cout << "swap01中的b = " << b << endl;
//2.地址传递
cout << "entering 地址传递函数:" << endl;
swap02( &a, &b );
cout << "swap02中的a = " << a << endl;
cout << "swap02中的b = " << b << endl;
system("pause");
return 0;
}
/********** 实现两个数字交换的函数:值传递 **********/
void swap01(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;
}
/********** 实现两个数字交换的函数:地址传递 **********/
void swap02(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
运行结果图:
4.7 指针配合数组和函数
4.7.1 从函数返回数组或指针
- C++ 不允许返回一个完整的数组作为函数的参数。(但是数组其实就是指针,所以可以让函数返回指针来实现~)
- 可以通过指定不带索引的数组名来返回一个指向数组的指针。
- 如果想要从函数返回一个一维数组,必须声明一个返回指针的函数,如下:
int * myFunction()
{
.
.
.
}
案例描述:
- 生成 10 个随机数,并使用数组来返回它们。
int *getRandom( )
{
static int arr[10];
srand( (unsigned)time( NULL ) ); //添加随机数种子,作用:利用当前系统时间生成随机数
for (int i = 0; i < 10; ++i)
{
arr[i] = rand(); //生成10个随机数,默认情况下生成的是一个五位数
cout << arr[i] << endl; //打印输出10个随机数
}
return arr; //返回数组名
}
代码:
/*********************************************************************
程序名: 从函数返回数组
作者: Sweitena
日期: 2021-07-25 17:57
说明: C++不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。
*********************************************************************/
#include <iostream>
#include <ctime> //系统头文件
using namespace std;
/************************************************/
/************* 函数名:getRandom( ) ************/
/************ 功能:生成和返回随机数 ************/
/************************************************/
int *getRandom( )
{
static int arr[10];
srand( (unsigned)time( NULL ) ); //添加随机数种子,作用:利用当前系统时间生成随机数
for (int i = 0; i < 10; ++i)
{
arr[i] = rand(); //生成10个随机数,默认情况下生成的是一个五位数
cout << arr[i] << endl; //打印输出10个随机数
}
return arr; //返回数组名
}
int main()
{
int *p; //定义一个指向整数的指针
p = getRandom(); //相当于 p = arr; 通过指针,让函数返回数组
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : " << *(p + i) << endl;
}
system("pause");
return 0;
}
运行结果图:
4.7.2 传递数组给函数
- C++ 中可以通过指定不带索引的数组名来传递一个指向数组的指针。
- 传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址。
- 如果想要在函数中传递一个一维数组作为参数,必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样地,也可以传递一个多维数组作为形式参数。
- 方式1: 形式参数是一个指针
void myFunction(int *parameter)
{
.
.
.
}
- 方式2: 形式参数是一个已定义大小的数组
void myFunction(int parameter[10])
{
.
.
.
}
- 方式3: 形式参数是一个未定义大小的数组
void myFunction(int parameter[])
{
.
.
.
}
案例描述:
- 函数功能:把数组作为参数,同时传递另一个参数,根据所传的参数,返回数组中各元素的平均值。
double getAverage(int arr[], int size) //形式参数是一个未定义大小的数组
{
int sum = 0;
double avg;
for (int i = 0; i < size; i++)
{
sum += arr[i]; //相当于sum = sum + arr[i];
}
avg = double(sum) / size;
return avg; //返回平均值
}
代码:
/*********************************************************************
程序名:传递数组给函数
作者: Sweitena
日期: 2021-07-23 07:45
说明: 返回数组中的平均值
*********************************************************************/
#include <iostream>
using namespace std;
/************************************************/
/************ 函数名:getAverage( ) ************/
/************ 功能:返回数组的平均值 ************/
/************************************************/
double getAverage(int arr[], int size)
{
int sum = 0;
double avg;
for (int i = 0; i < size; i++)
{
sum += arr[i]; //相当于sum = sum + arr[i];累加数组的元素
}
avg = double(sum) / size;
return avg; //返回平均值
}
int main ()
{
int balance[5] = {1000, 2, 3, 17, 50}; //定义一个带有5个元素的整型数组
double avg; //定义双精度的浮点型变量avg,作为数组的平均值
avg = getAverage( balance, 5 ) ; //传递一个指向数组的指针作为参数
cout << "平均值是:" << avg << endl; //输出返回值
system("pause");
return 0;
}
运行结果图:
❀案例练习:冒泡排序法
案例描述:
- 封装一个函数,利用冒泡排序,实现对整型数组的升序排列
- 例如数组:`int arr[] = {4, 3, 6, 9, 1, 2, 10, 8, 7, 5};
案例分析:
- 首先,创建数组
- 创建函数,实现冒泡排序
- 打印排序后的数组
代码:
/*********************************************************************
程序名: 指针、数组、函数
作者: Sweitena
日期: 2021-04-18 13:47
说明: 封装一个函数,利用冒泡排序,实现对整型数组的升序排列
*********************************************************************/
#include <iostream>
using namespace std;
//函数声明
void BubbleSort(int *arr, int num); //冒泡排序函数
void PrintArray(int *arr, int num); //打印数组函数
int main()
{
//1.先创建数组
int arr[] = {4, 3, 6, 9, 1, 2, 10, 8, 7, 5};
int num = sizeof(arr) / sizeof(arr[0]); //确定数组的长度
cout << "排序前:" << endl; //打印原始数组
PrintArray(arr, num);
//2.创建函数,实现冒泡排序
BubbleSort(arr, num); //调用冒泡排序函数
//3.打印排序后的数组
cout << "排序后:" << endl; //打印排序后的数组
PrintArray(arr, num);
system("pause");
return 0;
}
/************函数名:BubbleSort(int *arr, int num)*************/
/***********功能:冒泡排序,实现对整型数组的升序排列***********/
/*******形式参数:【参数1】数组首地址,【参数2】数组长度*******/
void BubbleSort(int *arr, int num)
{
for (int j = 0; j < num - 1; j++) //外层循环 做几轮比较 9个元素 需要比较8轮
{
for (int i = 0; i < num - j - 1; i++) //内层循环 每轮需要比较几次
{
if (arr[i] > arr[i + 1])
{
//交换两个元素位置
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
}
/************函数名:PrintArray(int *arr, int num)*************/
/***********************功能:打印数组*************************/
/*******形式参数:【参数1】数组首地址,【参数2】数组长度*******/
void PrintArray(int *arr, int num)
{
for (int i = 0; i < num; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
运行结果图:
五、引用
5.1 引用的基本概念
- 作用:引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。
- 一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
5.1.1 引用的定义和使用
- 引用变量定义语法:
数据类型 & 变量名;
代码:
/*********************************************************************
程序名:引用的定义和使用
作者: Sweitena
日期: 2021-08-01 20:56
说明: 引用在创建时就要被初始化
*********************************************************************/
#include <iostream>
using namespace std;
int main()
{
//声明简单的变量
int i = 5;
double d = 11.7;
//声明引用变量
int & r1 = i;
double & r2 = d;
//输出
cout << "i = " << i << endl;
cout << "& i = " << r1 << endl;
cout << "d = " << d << endl;
cout << "& d = " << r2 << endl;
system("pause");
return 0;
}
运行结果图:
5.2 引用vs指针
-
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 重新赋值问题:一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 初始化问题:引用必须在创建时被初始化,指针可以在任何时间被初始化。
代码片段1:
int a = 3;
int *p; //可以不被初始化
int &r = a; //必须在创建时被初始化
查看汇编代码:
代码片段2:
int a = 3, b = 6;
//指针
int *p = &a; //让指针指向a,p里面存放的是a的地址
p = &b; //让指针指向b,p里面存放的是b的地址
//引用
int &r = a; //r指向a,r是a的引用
r = b; //相当于a = b;是把b赋值给a,r始终是a的引用,一切对r的操作实际上是对a的操作
代码片段3:
//承接上面的代码2
p++; //在数组中,会指向下一个元素
r++; //相当于a++,此时a的值为4
代码片段4:
class A //定义一个类
{
int a;
int b;
int c;
int d;
}
A a;
A *ap = a; //定义一个指针
A &ar = a; //定义一个引用
printf(sizeof(ap)); //指针所占内存是4个字节
printf(sizeof(ar)); //引用是16个字节,因为类A中有4个int型的变量
5.3 引用和函数
5.3.1 引用调用(地址传递)
- 作用:使用引用来实现调用函数。
- 该方法把参数的引用赋值给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
代码:
/*********************************************************************
程序名:使用引用调用函数
作者: Sweitena
日期: 2021-08-03 18:27
说明: 对比之前学过的使用指针调用函数
*********************************************************************/
#include <iostream>
using namespace std;
//函数声明
void swap03(int &r1, int &r2); //实现两个数字交换的函数
int main()
{
int a, b;
a = 10;
b = 20;
//使用引用调用函数
swap03( a, b );
cout << "swap03中的a = " << a << endl;
cout << "swap03中的b = " << b << endl;
system("pause");
return 0;
}
/********** 实现两个数字交换的函数:地址传递 **********/
void swap03(int &r1, int &r2)
{
int temp = r1;
r1 = r2;
r2 = temp;
}
运行结果图:
5.4 引用配合数组和函数
5.4.1 从函数返回数组或引用
- 通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。C++ 函数可以返回一个引用,方式与返回一个指针类似。
- 当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。
代码:
/*********************************************************************
程序名:从函数返回数组或引用
作者: Sweitena
日期: 2021-08-03 19:06
说明: 与4.7.2节对应着去理解,和指针的用法类似
*********************************************************************/
#include <iostream>
using namespace std;
double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0}; //定义一个浮点型数组
/************************************************/
/************* 函数名:setValues( ) ************/
/********** 功能:改变数组中第i个元素 ***********/
/************************************************/
double &setValues(int i)
{
double &ref = vals[i]; //ref是一个引用变量,ref引用vals[i]
return ref;
}
int main()
{
//1、输出调用函数前的数组
cout << "改变前的值" << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "vals[" << i << "] = " << vals[i] << endl;
}
//2、调用函数改变元素的值
setValues(1) = 20.23; // 改变第 2 个元素
setValues(3) = 70.8; // 改变第 4 个元素
//3、输出改变后的数组
cout << "改变后的值" << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "vals[" << i << "] = " << vals[i] << endl;
}
system("pause");
return 0;
}
运行结果图:
六、结构体
6.1 结构体的基本概念
- 作用:结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
6.1.1 结构体的定义和使用
- 语法:
struct 结构体名 { 结构体成员列表 };
- 通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = { 成员1值,成员2值…}
- 定义结构体时顺便创建变量
代码:
/*********************************************************************
程序名: 结构体定义和使用
作者: Sweitena
日期: 2021-04-18 14:37
说明: [定义]结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
[注意]在使用时可以不写struct,直接写Student s1...
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//1. 创建学生数据类型,包括(姓名、年龄、分数)
struct Student
{
//成员列表
string name; //学生姓名
int age; //学生年龄
int score; //学生分数
} s3;
/******************结构体使用*******************************/
int main()
{
// 2.通过学生类型创建具体学生
// 2.1 第一种方式:struct Student s1
struct Student s1;
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 分数:" << s1.score << endl;
// 2.2 第二种方式:struct Student s2 = { ..., ..., ... }
struct Student s2 = {"李四", 19, 80};
cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 分数:" << s2.score << endl;
// 2.3 第三种方式:在定义结构体时顺便创建结构体变量
s3.name = "王五";
s3.age = 20;
s3.score = 70;
cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 分数:" << s3.score << endl;
system("pause");
return 0;
}
运行结果图:
6.2 结构体数组
- 作用:将自定义的结构体放入到数组中方便维护。
- 语法:
struct 结构体名 数组名 [ 元素个数 ] = { { } , { } , . . . { } }
代码:
/*********************************************************************
程序名: 结构体数组
作者: Sweitena
日期: 2021-05-09 15:56
说明: 先有结构体定义,再去创建结构体数组
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//1. 创建学生数据类型,包括(姓名、年龄、分数)
struct Student
{
//成员列表
string name;
int age ;
int score;
};
/******************结构体使用*******************************/
int main()
{
//2.创建结构体数组,包含三个学生
struct Student stuarr[3] =
{
{"张三", 18, 100},
{"李四", 19, 80},
{"王五", 20, 70}
};
//3.遍历结构体数组,实现信息输出
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuarr[i].name << " 年龄:" << stuarr[i].age << " 分数:" << stuarr[i].score << endl;
}
cout << endl;
//4.给结构体数组中的元素赋值
stuarr[2].name = "赵六";
cout << "修改某一元素后输出:" << endl;
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuarr[i].name << " 年龄:" << stuarr[i].age << " 分数:" << stuarr[i].score << endl;
}
cout << endl;
system("pause");
return 0;
}
运行结果图:
6.3 结构体指针
- 作用:通过指针访问结构体中的成员。
- 利用操作符
->
可以通过结构体指针访问结构体属性。
代码:
/*********************************************************************
程序名: 结构体指针
作者: Sweitena
日期: 2021-05-09 16:32
说明:利用操作符" -> "可以通过结构体指针访问结构体属性
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//1. 创建学生数据类型,包括(姓名、年龄、分数)
struct Student
{
//成员列表
string name;
int age ;
int score;
};
/******************结构体使用*******************************/
int main()
{
//2、创建学生结构体变量
Student s;
s = {"张三", 18, 100};
//3、直接输出结构体变量中的数据
cout << "常规输出方式:" << endl;
cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.score << endl;
//4、通过指针指向结构体变量
Student *p = &s;
//5、通过指针访问结构体变量中的数据
cout << "使用指针输出:" << endl;
cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
system("pause");
return 0;
}
运行结果图:
6.4 结构体嵌套结构体
- 作用:结构体的成员可以是另一个结构体。
- 例如:每个老师辅导一个学生,则一个老师的结构体中记录一个学生的结构体。
代码:
/*********************************************************************
程序名: 结构体嵌套结构体
作者: Sweitena
日期: 2021-05-09 16:45
说明:【作用】结构体中的成员可以是另一个结构体
【例子】每个老师辅导一个学生,一个老师的结构体中记录一个学生的结构体
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//学生结构体定义,包括(姓名、年龄、分数)
struct Student
{
//成员列表
string name;
int age ;
int score;
};
//老师结构体定义,包含(ID、姓名、年龄)以及学生结构体
struct Teacher
{
//成员列表
int id; //职工编号
string name; //教师姓名
int age ; //教师年龄
struct Student stu; //子结构体 学生
};
/******************结构体使用*******************************/
int main()
{
//1、创建老师结构体变量
Teacher t1;
t1.id = 200112;
t1.name = "老王";
t1.age = 75;
//2、子结构体赋值
t1.stu.name = "小付";
t1.stu.age = 23;
t1.stu.score = 100;
//3、输出老师结构体变量中的数据
cout << "老师姓名:" << t1.name << endl;
cout << "老师编号:" << t1.id << endl;
cout << "老师年龄:" << t1.age << endl;
cout << "老师辅导的学生姓名:" << t1.stu.name << endl;
cout << "学生年龄:" << t1.stu.age << endl;
cout << "学生分数:" << t1.stu.score << endl;
system("pause");
return 0;
}
运行结果图:
6.5 结构体做函数参数
- 作用:将结构体作为参数向函数中传递。
- 传递方式:
- 值传递
- 地址传递
代码:
/*********************************************************************
程序名: 结构体做函数参数
作者: Sweitena
日期: 2021-05-12 10:10
说明: ①值传递:形参改变,实参不变
②地址传递:形参改变,实参也变
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//学生结构体的定义,包括(姓名、年龄、分数)
struct student
{
//成员列表
string name;
int age;
int score;
};
/******************结构体使用*******************************/
/********* 函数名:Printstudent_1(struct student s) *********/
/************** 功能:值传递方式——打印学生信息 **************/
/************ 形式参数:【参数1】学生结构体变量 *************/
void Printstudent_1(struct student s)
{
cout << "值传递函数中:" << endl;
cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.score << endl;
}
/********* 函数名:Printstudent_2(struct student *p) **********/
/************** 功能:地址传递方式——打印学生信息 **************/
/******** 形式参数:【参数1】指向学生结构体变量的指针 *********/
void Printstudent_2(struct student *p)
{
//p->age = 90; //会改变实参
cout << "地址传递函数中:" << endl;
cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
}
int main()
{
//1、创建学生结构体变量,并赋值
student s = {"张三", 18, 100};
//2、在主函数中打印结构体变量中的数据
cout << "主函数中:" << endl;
cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.score << endl;
//3、通过值传递方式打印
Printstudent_1(s); //值传递
//4、通过地址传递方式打印
Printstudent_2(&s); //地址传递
system("pause");
return 0;
}
运行结果图:
6.6 结构体中const的使用
- 作用:用const来防止误操作
代码:
/*********************************************************************
程序名: 结构体中const使用场景
作者: Sweitena
日期: 2021-05-12 10:47
说明:【作用】在地址传递过程中,为防止误操作修改实参,可以加入const
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//学生结构体的定义,包括(姓名、年龄、分数)
struct student
{
//成员列表
string name;
int age;
int score;
};
/******************结构体使用*******************************/
/********* 函数名:Printstudent(const student *p) **********/
/*************** 功能:打印结构体中的数据 ******************/
/***** 形式参数:【参数1】指向学生结构体变量的常量指针 *****/
void Printstudent(const student *p)
{
//p->age = 90; //会改变实参,但是加入const之后,一旦有修改的操作就会报错,防止误操作
cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
}
int main()
{
//1、创建学生的结构体变量
struct student s = {"张三", 18, 100};
//2、调用函数打印结构体中的数据
Printstudent(&s);
system("pause");
return 0;
}
运行结果图:
❀案例练习01:嵌套结构体
案例描述:
- 学校正在做毕设项目,每名老师带领5个学生,总共有3名老师。
- 需求:设计学生和老师的结构体,其中在老师的结构体中,有2个成员:①姓名、②一个存放5名学生的数组。在学生的结构体中,有2个成员:①姓名、②考试分数。
- 创建数组存放3名老师,通过函数给每个老师及所带的学生赋值,最终打印出老师数据以及老师所带的学生数据。
案例分析:
代码:
/*********************************************************************
程序名: 结构体案例01
作者: Sweitena
日期: 2021-05-12 14:02
说明: 【案例描述】学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,
需求如下:设计学生和老师的结构体,其中在老师的结构体中,有老师姓名
和存放5个学生的数组作为成员,学生的成员有姓名、考试分数,创建数组
存放3名老师,通过函数给每个老师及所带的学生赋值,最终打印出老师数据
以及老师所带的学生数据。
*********************************************************************/
#include <iostream>
using namespace std;
#include <string> //字符串
#include <ctime> //系统时间
/******************结构体定义*******************************/
//学生结构体的定义,包括(姓名、考试分数)
struct student
{
//成员列表
string sname; //学生姓名
int score; //考试分数
};
//老师结构体的定义,包括(姓名、存放5名学生的数组)
struct teacher
{
//成员列表
string tname; //教师姓名
struct student sarr[5]; //学生数组
};
/******************结构体使用*******************************/
/****************** 函数名:allocateSpace( ) *******************/
/*************** 功能:给老师和学生赋值的函数 ******************/
/****** 形式参数:【参数1】老师的数组、【参数2】数组长度 *******/
void allocateSpace(struct teacher tarr[], int len) //传递数组给函数:这是4.7.2节提到的方式3
{
string nameSeed = "ABCDE";
for (int i = 0; i < len; i++) //外侧循环:给老师赋值
{
tarr[i].tname = "Teacher_";
tarr[i].tname += nameSeed[i]; //相当于在Teacher_后,追加了一个nameSeed
for (int j = 0; j < 5; j++) //内侧循环:给每名老师所带的学生赋值
{
tarr[i].sarr[j].sname = "Student_";
tarr[i].sarr[j].sname += nameSeed[j];
int randomnum = rand() % 61 + 40; //生成40~100的随机数
tarr[i].sarr[j].score = randomnum;
}
}
}
/******************** 函数名:printInfo( ) *********************/
/***************** 功能:打印所有信息的函数 ********************/
/****** 形式参数:【参数1】老师的数组、【参数2】数组长度 *******/
void printInfo(struct teacher tarr[], int len)
{
for (int i = 0; i < len; i++) //外侧循环:输出老师的信息
{
cout << "老师的姓名:" << tarr[i].tname << endl;
for (int j = 0; j < 5; j++) //内侧循环:输出老师所带学生的信息
{
cout << "\t学生的姓名:" << tarr[i].sarr[j].sname << " 分数:" << tarr[i].sarr[j].score << endl;
}
cout << endl;
}
}
int main()
{
srand((unsigned int)time(NULL)); //随机数种子
//1、创建3名老师的数组
struct teacher tarr[3];
//2、通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(tarr) / sizeof(tarr[0]); //求出老师的数组长度
allocateSpace(tarr, len);
//3、打印所有老师及所带学生的信息
printInfo(tarr, len);
system("pause");
return 0;
}
运行结果图:
❀案例练习02:冒泡排序法
案例描述:
- 设计一个英雄的结构体,成员包括:①姓名、②年龄、③性别;
- 创建结构体数组,数组中存放5名英雄;
- 通过冒泡排序法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
- 例如:5名英雄信息已给出
代码:
/*********************************************************************
程序名:结构体案例02
作者: Sweitena
日期: 2021-05-12 16:20
说明: 【案例描述】设计一个英雄的结构体,包括成员姓名,年龄,性别;
创建结构体数组,数组中存放5名英雄。通过冒泡排序的算法,将
数组中的英雄按照年龄进行升序排列,最终打印排序结果。
*********************************************************************/
#include <iostream>
using namespace std;
#include <string>
/******************结构体定义*******************************/
//英雄结构体的定义,包括(姓名、年龄、性别)
struct hero
{
//成员列表
string name;
int age;
string sex;
};
/******************结构体使用*******************************/
/******************** 函数名:bubbleSort( ) *********************/
/************** 功能:冒泡排序-实现年龄升序排列 *****************/
/******* 形式参数:【参数1】英雄的数组、【参数2】数组长度 *******/
void bubbleSort(struct hero arr[], int len) //冒泡排序法的应用
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j].age > arr[j + 1].age)
{
//交换位置
struct hero temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
/******************** 函数名:printHero( ) *********************/
/***************** 功能:打印数组信息的函数 ********************/
/****** 形式参数:【参数1】英雄的数组、【参数2】数组长度 *******/
void printHero(struct hero arr[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "\t姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 性别:" << arr[i].sex << endl;
}
}
int main()
{
//1、创建数组存放5名英雄
struct hero arr[5] =
{
{"刘备", 23, "男"},
{"关羽", 22, "男"},
{"张飞", 20, "男"},
{"赵云", 21, "男"},
{"貂蝉", 19, "女"}
};
int len = sizeof(arr) / sizeof(arr[0]); //求出英雄数组的长度
cout << "原来数组信息:" << endl;
printHero(arr, len);
//2、对数组进行排序,按照年龄进行升序排序
bubbleSort(arr, len);
//3、将排序后的结果打印输出
cout << "排序后数组信息:" << endl;
printHero(arr, len);
system("pause");
return 0;
}
运行结果图: