最近开始学C++了,很多企业对于算法工程师的要求中,“掌握C++、Python、Java编程语言中至少一种”是招聘条件之一,另外考虑到自己后期要学习算法与数据结构,而很多经典的算法与数据结构教材是C/C++语言描述的,因此很有必要学习一下C++。
除此之外,C++这门编程语言也很偏向于系统底层,在工作场景中实际上会经常用到,技多不压身,尽管自己从事的研究方向机器视觉主要使用Python,但学习C++对于未来成为一名算法工程师而言也是很有帮助的。
尽管之前有一些C基础,但还是有必要去听一下C++基础,自己编写一些代码,让大脑尽快熟悉编程的感觉,以便后续的课程能够更好地进行下去。
C++基础部分,我是跳着看黑马程序员的教程,有些编码部分没有看视频自己直接在VS上编程,从6.22看到7.1,通讯录的作业还没有做,后面打算单独发一篇博文。
目录
零、代码模板
在进行C++程序编写前,需要倒入一些标准库,下面是C++的模板,每次写C++程序之前都可以将这个模板粘贴进去,避免重复劳动。
#include<iostream>
using namespace std;
int main()
{
//此处编写核心程序部分
system("pause");
return 0;
}
一、if-else选择结构:三只小猪称体重
需求描述:有三只小猪A,B,C,现在由用户输入这三只小猪的体重,编写程序比较三只小猪的体重,并输出体重最终的小猪名称:
#include<iostream>
using namespace std;
int main()
{
//创建三只小猪体重变量
int w1, w2, w3;
//提示用户输入
cout << "请输入小猪A的体重:" << endl;
cin >> w1;
cout << "请输入小猪B的体重:" << endl;
cin >> w2;
cout << "请输入小猪C的体重:" << endl;
cin >> w3;
if (w1 > w2){
if (w1 > w3) {
cout << "小猪A最重";
}
else {
cout << "小猪B最重";
}
}
else {
if (w2 > w3) {
cout << "小猪B最重";
}
else {
cout << "小猪C最重";
}
}
system("pause");
return 0;
}
二、while/do...while循环与for循环的应用
2.1 猜数字(随机数种子、while循环并限制循环次数)
需求描述:系统随机生成一个1到100之间的数字,玩家进行猜测,如果猜错,提示玩家数字过大或者过小,如果猜错次数超过5次,那么退出游戏;如果猜对恭喜玩家胜利,也退出游戏。
代码如下所示:
#include<iostream>
using namespace std;
//time系统时间头文件包含
#include<ctime>
int main()
{
//添加随机数种子 作用:利用当前系统时间生成随机数,防止每次随机数都一样
srand((unsigned int)time(NULL));
//1、系统生成随机数
int num = rand() % 100 + 1; //表示生成0 + 1 ~ 99 + 1 的随机数
//cout << num << endl;
//2、玩家进行猜测
int user_input = 0 ;
//限制猜测次数
int limited_time = 5;
int user_time = 0;
while (1){
cout << "请你猜一下这个数是多少:" << endl;
cin >> user_input;
//3、判断结构
if (user_time < limited_time - 1) {
if (user_input > num) {
cout << "您猜大了,请输入一个小一些的数" << endl;
}
else if (user_input < num) {
cout << "您猜小了,请输入一个小一些的数" << endl;
}
else {
cout << "您猜对了,这个数就是:" << num << endl;
cout << "太棒了,您只用了" << user_time << "次就猜对了!" << endl;
break;
}
++user_time;
cout << "您已经猜测了" << user_time << "次,请再接再厉!" << endl;
}
else {
cout << "您猜错的次数已经超过5次,游戏结束!" << endl;
}
}
system("pause");
return 0;
}
猜对情况下程序的输出,玩这个游戏很简单,使用二分法即可,100以内的数最多猜测6次就可以猜出:
请你猜一下这个数是多少:
50
您猜大了,请输入一个小一些的数
您已经猜测了1次,请再接再厉!
请你猜一下这个数是多少:
25
您猜大了,请输入一个小一些的数
您已经猜测了2次,请再接再厉!
请你猜一下这个数是多少:
13
您猜对了,这个数就是:13
太棒了,您只用了2次就猜对了!
请按任意键继续. . .
猜错情况下程序的输出:
请你猜一下这个数是多少:
1
您猜小了,请输入一个小一些的数
您已经猜测了1次,请再接再厉!
请你猜一下这个数是多少:
2
您猜小了,请输入一个小一些的数
您已经猜测了2次,请再接再厉!
请你猜一下这个数是多少:
3
您猜小了,请输入一个小一些的数
您已经猜测了3次,请再接再厉!
请你猜一下这个数是多少:
4
您猜小了,请输入一个小一些的数
您已经猜测了4次,请再接再厉!
请你猜一下这个数是多少:
5
您猜小了,请输入一个小一些的数
您已经猜测了5次,请再接再厉!
请你猜一下这个数是多少:
6
您猜测的次数已经超过5次,游戏结束!
请按任意键继续. . .
2.2 水仙花数(do...while循环、for循环)
需求描述:水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身,例如:
请利用do..while语句,求出所有3位数中的水仙花数。
#include<iostream>
using namespace std;
int main()
{
int a = 100;
do {
int Digit, Decimal, Hundred;
Digit = a % 10; //取个位
Decimal = a / 10 % 10; //取十位
Hundred = a / 100 % 10; //取百位
if ((Hundred * Hundred * Hundred + Decimal * Decimal * Decimal + Digit * Digit * Digit) == a) {
cout << a<< endl;
}a++;
} while (a < 1000);
system("pause");
return 0;
}
也可使用for循环:
#include <iostream>
using namespace std;
int main()
{
for (int a = 100; a < 1000; a++)
{
int Digit, Decimal, Hundred;
Digit = a % 10; //取个位
Decimal = a / 10 % 10; //取十位
Hundred = a / 100 % 10; //取百位
if ((Hundred * Hundred * Hundred + Decimal * Decimal * Decimal + Digit * Digit * Digit) == a) {
cout << a << endl;
}
}
system("pause");
return 0;
}
输出结果如下:
153
370
371
407
2.3 输出10*10的星图(使用for嵌套循环)
外层执行一次,内层执行一周。
#include <iostream>
int main()
{
for (int j = 1; j < 11; j++) {
for (int i = 1; i < 11; i++)
{
printf("* ");
}
printf("\n");
}
system("pause");
return 0;
}
输出结果:
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
2.4 实现乘法口诀表(使用附加条件的for嵌套循环)
代码如下:
#include <iostream>
using namespace std;
int main()
{
for (int j = 1; j < 10; j++) {
for (int i = 1; i <= j ; i++)
{
cout << i << "×" << j << "=" << i * j << "\t";
}
cout << endl;
}
system("pause");
return 0;
}
输出结果如下:
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
1×4=4 2×4=8 3×4=12 4×4=16
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
三、break 和 continue 的区别
#include <iostream>
using namespace std;
int main()
{
for (int j = 1; j <= 100; j++) {
if (j % 2 == 0) {
break;
//continue;
}
cout << j << endl;
}
system("pause");
return 0;
}
如果是break,那么只会输出1;如果是continue,则会输出所有的奇数,在这里continue具有跳过的功能——continue并没有使整个循环终止,而break会跳出循环。
四、数组经典案例
4.1 数组表示及数组名的用途
#include <iostream>
using namespace std;
int main()
{
int arr[] = { 90,80,70,60 };
for (int i = 0; i < 4; i++) {
cout << arr[i] << endl;
}
//数组名用途
//1、可以通过数组名统计数组占用内存的大小
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;
}
输出结果如下:
90
80
70
60
整个数组占用的内存空间是:16
每个数组元素占用的内存空间是:4
数组中的元素个数是:4
数组首地址为:653260296
数组第一个元素地址为:653260296
数组第二个元素地址为:653260300
4.2 五只小猪称体重(找到数组中最大的值)
需求描述:在一个数组中记录了五只小猪的体重,如int arr[]={300,350,200,400,250},找出并打印最终的小猪体重。输出:400.
#include <iostream>
using namespace std;
int main()
{
int temp = 0;
int arr[] = { 300,350,200,400,250 };
for (int i = 0; i < 5; i++) {
if(arr[i]>temp){
temp = arr[i];
}
}
cout << temp << endl;
system("pause");
return 0;
}
4.3 数组逆序(数组交换位置,头尾交换法)
输入:{1,2,3,4,5}
输出:{5,4,3,2,1}
#include <iostream>
using namespace std;
int main()
{
int temp = 0;
int arr[] = { 1,2,3,4,5 };
//定义start 和end 是为了便于表示数组中的元素
int start = 0;
int end = sizeof(arr) / sizeof(arr[0]) - 1;
while (start < end)
{
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
for (int i = 0; i < 5; i++)
{
cout << arr[i] << endl;
}
system("pause");
return 0;
}
4.4 冒泡排序(重点算法)
- 比较相邻两个元素,如果第一个比第二个大就交换他们的位置
- 每一对相邻元素做同样的工作,整型完毕后,找到第一个最大值。
- 重复以上的步骤,每次比较次数-1,直到不需要比较
因此冒泡排序的核心思想是每一轮比较找出这次比较的最大值。
#include <iostream>
using namespace std;
int main()
{
//利用冒泡排序实现升序序列
//排序的总轮数=元素个数-1
//每轮对比的次数 = 元素个数 - 排序轮数
int temp = 0;
int arr[] = { 3,2,4,5,1,7,9,8,6 };
cout << "排序前:";
for (int i = 0; i < 9; i++)
{
cout << arr[i] << "\t";
}
cout << endl ;
for (int i = 0; i < 9 - 1; i++) {
for (int j = 0; j < 9 - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
cout << "排序后:";
for (int i = 0; i < 9; i++)
{
cout << arr[i] << "\t";
}
cout << endl;
system("pause");
return 0;
}
4.5 二维数组
实现二维数组的打印,以及各行、各列、各元素地址和占用内存的打印输出。
#include <iostream>
using namespace std;
int main()
{
int arr[2][3] =
{
{1,2,3},
{4,5,6}
};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
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 << "二维数组首地址为:" << int(arr) << endl;
cout << "二维数组第一行首地址为:" << (int)arr[0] << endl;
cout << "二维数组第二行首地址为:" << (int)arr[1] << endl;
cout << "二维数组第一行第一个元素首地址为:" << (int)&arr[0][0] << endl;
system("pause");
return 0;
}
输出结果如下:
1 2 3
4 5 6
二维数组占用内存为:24
二维数组第一行占用内存为:12
二维数组第一行第一个元素占用内存为:4
二维数组行数为:2
二维数组列数为:3
二维数组首地址为:1249376792
二维数组第一行首地址为:1249376792
二维数组第二行首地址为:1249376804
二维数组第一行第一个元素首地址为:1249376792
五、函数
5.1 函数的定义和调用
#include <iostream>
using namespace std;
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
int a = 10;
int b = 10;
//调用add函数
int sum = add(a, b);
cout << "sum=" << sum << endl;
a = 100;
b = 100;
sum = add(a, b);
cout << "sum=" << sum << endl;
system("pause");
return 0;
}
5.2 函数的值传递
- 所谓值传递,就是函数调用时实参将数值传入给形参
- 值传递时,如果形参发生任何改变,并不会影响形参
#include <iostream>
using namespace std;
//如果函数不需要返回值,声明的时候可以写void
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;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
//当我们做值传递的时候,函数的形参发生改变,并不会影响实参,经过函数,a的值会给num1,b的值会给num2.
swap(a, b);
//交换后a和b的实际值,发现a,b还是原来的a,b
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
输出结果:
a=10
b=20
交换前:
num1=10
num2=20
交换后:
num1=20
num2=10
a=10
b=20
5.3 函数的常见样式
一共四种常见样式:无参无返、有参无返、无参有返、有参有返
#include <iostream>
using namespace std;
//1、无参无返
void test01()
{
cout << "this is test 01 " << endl;
}
//2、有参无返
void test02(int a)
{
cout << "this is test 02 a=" << a << endl;
}
//3、无参有返
int test03()
{
cout << "this is test 03 " << endl;
return 1000;
}
//4、有参有返
int test04(int a)
{
cout << "this is test 04 " << endl;
return a;
}
int main()
{
//无参无返函数调用
test01();
//有参无返函数调用
test02(100);
//无参有返函数调用
int num1 = test03();
cout << "num1=" << num1 << endl;
//有参无返函数调用
int num2 = test04(10000);
cout << "num2=" << num2 << endl;
system("pause");
return 0;
}
输出结果如下:
this is test 01
this is test 02 a=100
this is test 03
num1=1000
this is test 04
num2=10000
5.4 函数的声明&函数的分文件编写
声明的作用:提前告诉编译器函数名称以及如何调用函数,知晓函数的存在,函数的实际主体可以单独定义。注意:函数的声明可以多次,但是函数的定义只能有一次。
分文件编写的作用:让代码的结构更清晰。
分文件编写的步骤:
1.创建后缀名为.h的头文件,在头文件中写函数声明。
//swap.h
#include <iostream>
using namespace std;
//函数的声明
void swap(int a, int b);
2.创建.cpp后缀名的源文件,在源文件中写函数定义。
//swap.cpp
#include <iostream>
#include "swap.h"
using namespace std;
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
}
3.在新文件中引用该函数
#include <iostream>
#include "swap.h"
using namespace std;
int main()
{
int a = 10;
int b = 20;
swap(a, b);
system("pause");
return 0;
}
六、指针
指针就是一个地址/指针就是记录地址的一个特殊变量/可以通过指针来保存一个地址。
指针的妙用:
- &a是一个常量值,不能进行++或--,但是用p就可以指向多个地址。
- 例如数字,用p++就可以遍历数组中的多个元素,因为数组元素的地址是连续的。
6.1 指针定义及使用、占用内存空间、空指针与野指针
#include <iostream>
using namespace std;
int main()
{
//1、定义指针:数据类型 * 指针变量名
int a = 10;
int* p;
//让指针记录变量a的地址
p = &a;
//等价于int *p = &a;
cout << "a的地址为: " << &a << endl;
cout << "指针p为: " << p << endl;
//2、使用指针
//可以通过解引用的方式找到指针指向的内存,指针前加 * 代表解引用,找到指针指向的内存的数据
//通过*p 找到a这段内存,并且通过*p修改内存,找到a的地址,执行读和写的操作,可修改可访问
*p = 1000;
cout << "a= " << a << endl;
cout << "*p= " << *p << endl;
//3、指针所占内存空间:32位x86占用4个字节空间,64位x64占用8个字节空间
cout << "sizeof(int*)=" << sizeof(int*) << endl;
cout << "sizeof(float*)=" << sizeof(float*) << endl;
cout << "sizeof(double*)=" << sizeof(double*) << endl;
cout << "sizeof(char*)=" << sizeof(char*) << endl;
//4、空指针:用于给变量指针进行初始化
int* p1 = NULL;
//空指针是不可以进行访问的,0~255之间的内存编号是系统占用的,因此不可以访问
//*p1 = 100;
//5、野指针:指针变量指向非法的内存空间(出现读取访问权限冲突错误),在程序中,尽量避免出现
//int* p2 = (int*)0x1100;
//cout << *p2 << endl;
//空指针和野指针都不是我们申请的空间,因此不要访问
system("pause");
return 0;
}
6.2 const修饰指针
6.2.1 常量指针
特点:指针的指向可以修改,但是指向的值不可修改。
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int b = 10;
const int * p = &a;
//*p = 20; 错误,指针指向的值不可以修改。
p = &b; //正确,指针指向可以修改
system("pause");
return 0;
}
6.2.2 指针常量
特点:指针的指向不可以改,指针指向的值可以改。
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int b = 10;
int * const p = &a;
*p = 20; //正确,指向的值可以修改
//p = &b; 错误,指针指向不可以修改
system("pause");
return 0;
}
6.2.3 const既修饰指针,又修饰常量
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int b = 10;
const int * const p = &a;
//*p = 20;
//p = &b; 错误,指针指向和指向的值都不可以修改
system("pause");
return 0;
}
6.3 利用指针实现访问数组元素
#include <iostream>
using namespace std;
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int * p = arr;
cout << "第一个元素:" << arr[0] << endl;
cout << "指针访问第一个元素:" <<*p << endl;
for (int i = 0; i < 9; i++) {
cout << *p << endl;
p++; //让指针向后偏移四个字节
}
system("pause");
return 0;
}
6.4 指针与函数
使用指针表示函数的特点:变量是地址时可以间接改变实参,因为参数的传递方法可以传递地址。
#include <iostream>
using namespace std;
//值传递
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);//值传递不会改变实参,a=10 b=20
cout << "a=" << a << endl;
cout << "b=" << b << endl;
swap2(&a, &b);//地址传递会改变实参,a=20 b=10
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
6.5 指针、数组、函数的综合应用
需求描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序。
#include <iostream>
using namespace std;
//值传递
void BubbleSort(int *arr, int len)
{
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++)
{
int temp = 0;
if (arr[j] > arr[j + 1])
{
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(arr[0]);
//创建函数
BubbleSort(arr, len);
//打印排序后数组
printArray(arr, len);
system("pause");
return 0;
}
七、结构体
结构体属于用户自定义的数据类型,允许永和存储不同的数据类型。
7.1 结构体的定义和使用
创建结构体的语法:
struct 结构体名{结构体成员列表}
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = {成员1值,成员2值...}
- 定义结构体时顺便创建变量
#include <iostream>
using namespace std;
//1、创建学生数据类型,自定义数据类型就是一些类型的集合组成的一个类型
struct Student
{
//成员列表
string name;
int age;
int score;
}s3;
int main()
{
//2、通过学生类型创建具体学生
//2.1 struct Student s1
Student s1; //C++中结构体创建时struct可省略
s1.name = "张三"; //结构体用.访问成员
s1.age = 18;
s1.score = 100;
cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 分数:" << s1.score << endl;
//2.2 struct Student s2 = {成员1值,成员2值...}
struct Student s2 = { "李四",19,80 };
cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 分数:" << s2.score << endl;
//2.3 定义结构体时顺便创建结构体变量(12行创建了s3)
s3.name = "王五";
s3.age = 20;
s3.score = 90;
cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 分数:" << s3.score << endl;
system("pause");
return 0;
}
7.2 结构体数组
作用:将自定义的结构体放到数组中便于维护
语法:struct 结构体名 数组名[元素个数] = {{},{}...{}}
#include <iostream>
using namespace std;
//1、创建学生数据类型,自定义数据类型就是一些类型的集合组成的一个类型
struct Student
{
//成员列表
string name;
int age;
int score;
};
int main()
{
//2、创建结构体数组
struct Student stuArray[3] =
{
{"张三", 18, 80},
{"李四", 19, 90},
{"王五", 20, 100},
};
//3、给结构体数组中的元素赋值
stuArray[2].name = "赵六";
//4、遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuArray[i].name << " 年龄:" << stuArray[i].age << " 分数:" << stuArray[i].score << endl;
}
system("pause");
return 0;
}
7.3 结构体指针
结构体指针可以通过->操作符来访问结构体成员
#include <iostream>
using namespace std;
//1、创建学生数据类型,自定义数据类型就是一些类型的集合组成的一个类型
struct Student
{
//成员列表
string name;
int age;
int score;
};
int main()
{
struct Student stu = { "张三", 18, 80 };
struct Student * p = & stu;
p->score = 90; //指针通过->操作符可以访问成员
cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;
system("pause");
return 0;
}
7.4 结构体嵌套结构体
#include <iostream>
using namespace std;
//学生结构体定义
struct student
{
//成员列表
string name;
int age;
int score;
};
//老师结构体定义
struct teacher
{
int id; //教师编号
string name; //教师姓名
int age; //教师年龄
struct student stu;
};
int main()
{
struct teacher t1;
t1.id = 10000;
t1.name = "Mr.Wang";
t1.age = 40;
t1.stu.name = "Zhang San";
t1.stu.age = 18;
t1.stu.score = 100;
cout << "教师 职工编号: " << t1.id << " 姓名:" << t1.name << " 年龄:" << t1.age << endl;
cout << "辅导学员 姓名: " << t1.stu.name << " 年龄:" << t1.stu.age << " 考试分数:" << t1.stu.score << endl;
system("pause");
return 0;
}
7.5 结构体做函数参数
需求描述:将学生信息传入到一个参数中,打印学生身上所有信息。
#include <iostream>
using namespace std;
//学生结构体定义
struct student
{
//成员列表
string name;
int age;
int score;
};
//值传递
void printStudent1(struct student s)
{
cout << "子函数中打印 姓名:" << s.name << " 年龄:" << s.age << " 考试分数:" << s.score << endl;
}
//地址传递
void printStudent2(struct student *p)
{
cout << "子函数2中打印 姓名:" << p->name << " 年龄:" << p->age << " 考试分数:" << p->score << endl;
}
int main()
{
struct student s = { "张三",20,85 };
cout << "main函数中打印 姓名:" <<s.name << " 年龄:" << s.age << " 考试分数:" << s.score << endl;
printStudent1(s); //值传递
printStudent2(&s);//地址传递
system("pause");
return 0;
}
7.6 结构体做函数参数及结构体const使用场景
一共有两种方式:值传递和地址传递,如果不想修改主函数中的数据,用值传递;反之用地址传递。以下程序输出结果分别为:20,100,200,200.
加入const之后,一旦有修改的操作就会报错,可以防止误操作。
#include <iostream>
using namespace std;
//学生结构体定义
struct student
{
//成员列表
string name;
int age;
int score;
};
//值传递,修饰形参,实参不会发生改变,值传递拷贝的数据量太大了
void printStudent1(struct student s)
{
s.age = 100;
cout << "子函数中打印 姓名:" << s.name << " 年龄:" << s.age << " 考试分数:" << s.score << endl;
}
//地址传递,修饰形参,实参会发生改变,将函数中的形参改为指针可以减少内存空间,而且不会复制新的副本
void printStudent2(const struct student *p)
{
p->age = 200; //加入const之后不可修改
cout << "子函数2中打印 姓名:" << p->name << " 年龄:" << p->age << " 考试分数:" << p->score << endl;
}
int main()
{
struct student s = { "张三",20,85 };
cout << "实参传递前main函数中打印 姓名:" <<s.name << " 年龄:" << s.age << " 考试分数:" << s.score << endl;
printStudent1(s); //值传递
printStudent2(&s);//地址传递
cout << "子函数2实参传递后main函数中打印 姓名:" << s.name << " 年龄:" << s.age << " 考试分数:" << s.score << endl;
system("pause");
return 0;
}
7.7 结构体案例
7.7.1 毕设项目学生和老师(有些难度,可重复复习)
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员。
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值。
最终打印出老师数据以及老师所带学生的数据。
解决方案代码如下:
#include <iostream>
using namespace std;
//学生结构体定义
struct Student
{
string sName;
int score;
};
//教师结构体定义
struct Teacher
{
string tName;
Student sArray[5];
};
//给老师和学生赋值的函数
void allocateSpace(struct Teacher tArray[], int len)
{
string nameSeed = "ABCDE";
//给老师开始赋值
for (int i = 0; i < len; i++)
{
tArray[i].tName = "Teacher_";
tArray[i].tName = nameSeed[i];
//通过循环给每名老师所带学生赋值
for (int j = 0; j < 5; j++)
{
tArray[i].sArray[j].sName = "Student_";
tArray[i].sArray[j].sName += nameSeed[j];
int random = rand() % 61 + 40; // 40 ~100
tArray[i].sArray[j].score = random;
}
}
}
//打印所有老师及所带的学生信息的函数
void printInfo(struct Teacher tArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "老师姓名: " << tArray[i].tName << endl;
for (int j = 0; j < 5; j++)
{
cout << "\t学生姓名: " << tArray[i].sArray[j].sName <<
" 考试分数 " << tArray[i].sArray[j].score<<endl;
}
}
}
int main()
{
//随机数种子
srand((unsigned int)time(NULL));
//创建3名老师的数组
struct Teacher tArray[3];
//通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);
allocateSpace(tArray, len);
//打印所有老师及所带的学生信息
printInfo(tArray, len);
system("pause");
return 0;
}
小结:在创建函数之前,可以先在主函数中考虑实现什么样的功能,再考虑写什么样的子函数。
7.7.2 数组中的英雄按年龄进行升序排序
设计一个英雄的结构体,包括成员姓名、年龄、性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
五名英雄信息如下:
{"欣南",20,"火"},
{"东杉",24,"木"},
{"北淼",23,"水"},
{"坤中",18,"土"},
{"西昭",22,"金"},
代码如下:
#include <iostream>
using namespace std;
//学生结构体定义
struct Hero
{
string name;
int age;
string sex;
};
void BubbleSort(Hero Array[],int len)
{
for (int i = 0 ; i < len - 1 ; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
Hero temp;
if (Array[j].age > Array[j + 1].age)
{
temp = Array[j];
Array[j] = Array[j+1];
Array[j+1] = temp;
}
}
}
}
void printHero(Hero Array[], int len)
{
for (int i = 0; i < len; i++)
{
cout << Array[i].name<< Array[i].age<< Array[i].sex << endl;
}
}
int main()
{
Hero Array[5] =
{
{"欣南",20,"火"},
{"东杉",24,"木"},
{"北淼",23,"水"},
{"坤中",18,"土"},
{"西昭",22,"金"},
};
int len = sizeof(Array) / sizeof(Array[0]);
BubbleSort(Array, len);
printHero(Array, len);
system("pause");
return 0;
}
耶,最终实现了冒泡排序功能!!!