教学视频:
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1et411b73Z
目录
C++初识
注释
变量
变量存在的意义:方便我们管理内存空间
变量创建的语法:数据类型 变量名 = 变量初始值;
常量
用于记录程序中不可更改的数据
1、#define 宏常量:#define 常量名 常量值(通常在文件上方定义)
2、const修饰的变量:const 数据类型 常量名 = 常量值
(通常在变量定义前加关键字const,修饰该变量为常量,不可修改)
关键字(标识符)
在定义变量或常量时,不要用关键字
标识符命名规则
- 标识符不能是关键字
- 标识符只能由字母、数字、下划线组成
- 第一个字符必须为字母或下划线
- 标识符中字母区分大小写
数据类型
存在意义:给变量分配合适的内存空间
整型
sizeof关键字
统计数据类型所占内存大小
sizeof(数据类型/变量)
//整型:short(2) int(4) long(4) long long(8)
//可以利用sizeof求出数据类型占用内存大小
//语法:sizeof(数据类型/变量)
short num1 = 10;
cout << "short占用内存空间为: " << sizeof(num1/*short */) << endl;
int num2 = 10;
cout << "int占用内存空间为: " << sizeof(num2/*int */) << endl;
long num3 = 10;
cout << "long占用内存空间为: " << sizeof(num3/*long */) << endl;
long long num4 = 10;
cout << "long long占用内存空间为: " << sizeof(num4/*long long */) << endl;
//整型大小比较
//short < int <= long <= long long
实型(浮点型)
1.单精度float**(不加f默认双精度)**
2.双精度double
默认情况下 输出一个小数,会显示6位有效数字
两者区别在于表示的有效数字范围不同
//科学计数法
float f2 = 3e2; //3 * 10 ^ 2
cout << "f2 = " << f2 << endl;
float f3 = 3e-2; //3 * 0.1 ^2
cout << "f3 = " << f3 << endl;
字符型
表示单个字母
char ch = ‘a’;
- C和C++字符型变量只占用1个字节
- 字符型变量不是把字符本身放到内存中存储,而是将对应的ASCII编码放入存储单元
//1、字符型变量创建方式
char ch = 'a';
cout << ch << endl;
//2、字符型变量所占内存大小
cout << "char字符型变量所占内存: " << sizeof(char) <<endl;
//3、字符型变量常见错误
//char ch2 = "b";//创建字符型变量要用单引号
//char ch2 = 'abcdef';//创建字符型变量单引号内只能有一个字符
//4、字符型变量对应ASCII编码
//a -- 97(ASCII值)
//A -- 65
//...
cout << (int)ch << endl;
ASCII
转义字符
//转义字符
//换行符 \n
cout << "hello world\n";
//反斜杠 \\
cout << "\\" <<endl;
//水平制表符 \t 可以整齐地输出数据
cout << "aaaa\thelloworld" << endl;
cout << "aa\thelloworld" << endl;
cout << "aaaaaa\thelloworld" << endl;
字符串型
1、C风格字符串: char 变量名[] = “字符串值”
2、C++风格字符串: string 变量名 = “字符串值”
//1、C风格字符串
//注意事项 char 字符串名[]
//注意事项2 等号后面要用双引号 包含起来字符串
char str[] = "hello world";
cout << str << endl;
//2、C++风格字符串
//包含一个头文件 #include<string>(为了可移植性和良好的编码风格,记得包含)
string str2 = "hello world";
cout << str2 << endl;
布尔类型
代表真或假的值
- true ----真(本质是1)
- false ----假(本质是0)
占1个字节
数据的输入
ctrl+k+c 注释
cin >>
运算符
算术运算符
两个数字相除时,除数不能为0
两个整数相除,结果依然是整数,将小数部分去除
两个小数可以相除 运算结果也可以是小数
//取模运算本质 就是求余数
int a1 = 10;
int b1 = 3;
cout << a1 % b1 << endl;
int a2 = 10;
int b2 = 20;
cout << a2 % b2 << endl;
int a3 = 10;
int b3 = 0;
//两个数相除除数不可以为0,所以也做不了取模运算
/*cout << a3 % b3 << endl;*/
//两个小数是不可以做取模运算的
double d1 = 3.14;
double d2 = 1.1;
//cout << d1 % d2 << endl;
赋值运算符
比较运算符
逻辑运算符
真变假,假变真
同真为真,其余为假
同假为假,其余为真
程序流程结构
顺序结构
选择结构
if语句
执行满足条件的语句
-
单行
if(条件){条件满足执行的语句}
-
多行
if(条件){条件满足执行的语句}else{条件不满足执行的语句}
-
嵌套if语句
三目运算符
实现简单判断
表达式1 ? 表达式2 : 表达式3
1为真,执行2;1为假,执行3
//三目运算符
//创建三个变量 a b c
//将a和b作比较,将变量大的值赋值给变量c
int a = 10;
int b = 20;
int c = 0;
c = (a > b ? a : b);
cout << "c = " << c << endl;
//在C++中三目运算符返回的是变量,可以继续赋值
(a < b ? a : b) = 100;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
switch语句
执行多条件分支语句
//if和switch区别
//switch缺点 判断时只能是整型或字符型,不可以是一个区间
//switch优点 结构清晰,执行效率高
循环结构
while循环结构
while(循环条件){循环语句}
只要循环条件为真,就执行循环语句
//while循环
//在屏幕中打印0~9这10个数字
int num = 0;
//while()写入循环条件
//注意在写循环时一定要避免死循环
while (num < 10)
{
cout << "num = " << num << endl;
num++;
}
C语言随机数生成教程,C语言rand和srand用法详解 (biancheng.net)
dowhile语句
do{循环语句}while{循环条件};
do…while会先执行一次循环语句
//do...while语句
//在屏幕中输出0~9这10个数字
int num = 0;
do
{
cout << "num = " << num << endl;
num ++;
} while (num < 10);
//do while和while循环区别在于dowhile先执行一次循环语句
//while中num为0,dowhile中num为1
/*do
{
cout << "num = " << num << endl;
num++;
} while (num);
while (num)
{
cout << "num = " << num << endl;
num++;
}*/
//水仙花数是指一个三位数,它的每个位上的数字的3次幂之和等于它本身
//1^3 + 5^3 + 3^3 = 153
//请利用do...while语句,求出所有3位数中的水仙花数
//1、将所有的三位数进行输出(100~999)
int num = 100;
do
{
int a = 0;//个位
int b = 0;//十位
int c = 0;//百位
a = num % 10;
b = num / 10 % 10;
c = num / 100;
//2、从所有三位数中找到水仙花数
//如果是水仙花数才打印
if (a*a*a + b*b*b + c*c*c == num)
{
cout << num << endl;
}
num ++;
} while (num < 1000);
for循环语句
for(起始表达式 ; 条件表达式 ; 末尾循环体){循环语句;}
嵌套循环
在循环中再嵌套一层循环,解决实际问题
列数 * 行数 = 运算结果
列数 <= 当前行数
跳转语句
break语句
用于跳出选择结构或循环结构
- 出现在switch语句中,作用是跳出case语句
- 出现在循环语句中,作用是跳出当前的循环语句
- 出现在嵌套循环中,跳出最近的内层循环语句
continue语句
在循环语句中,跳过本次循环中未执行的语句,继续执行下一次循环
//continue可以筛选条件,执行到此就不再向下执行,执行下一次循环循环
//break会退出循环,continue不会
goto语句
goto 标记;
如果标记的名称存在,执行到goto语句时,会跳转到标记的位置
//goto跳转语句
cout << "1、xxxx" << endl;
cout << "2、xxxx" << endl;
goto FLAG;
cout << "3、xxxx" << endl;
cout << "4、xxxx" << endl;
FLAG:
cout << "5、xxxx" << endl;
最好不要使用,以免破环程序稳定性
输出结果
数组
数组就是一个集合,里面存放了相同类型的数据类型
- 数组的每个数据元素都是相同的数据类型
- 数组是由连续的内存位置组成的
一维数组
一维数组定义方式
- 数组类型 数组名[数组长度];
- 数组类型 数组名[数组长度] = {值1,值2 …};
- 数组类型 数组名[] = {值1、值2 …};
一维数组数组名用途
1、可以统计整个数组在内存中的长度 sizeof(arr)
2、可以获取数组在内存中的首地址 cout << arr << endl;
①sizeof(arr) 整个数组所占内存空间
②sizeof(arr[0]) 某个元素所占内存空间
①除以②就可以拿到整个数组的长度
//数组名的用途
//1、可以通过数组名统计整个数组占用内存大小
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "整个数组占用内存空间: " << sizeof(arr) << endl;
cout << "每个元素占用内存空间:" << sizeof(arr[0]) << endl;
cout << "数组中元素个数为: " << sizeof(arr) / sizeof(arr[0]) << endl;
//2、可以通过数组名查看数组首地址
cout << "数组的首地址为: " << (int)arr << endl;
cout << "数组中第一个元素的地址: " << (int)&arr[0] << endl;
cout << "数组中第二个元素的地址: " << (int)&arr[1] << endl;
//数组名是常量,不可以进行赋值操作
//arr = 100;//错误
一维数组案例
//数组元素逆置
//请声明一个5个元素的数组,并且将元素逆置
冒泡排序
最常用的排序算法,对数组内元素进行排序
1、比较相邻的元素。如果第一个比第二个大,就交换他们两个
2、对每一对相邻元素做同样工作,执行完毕后,找到第一个最大值
3、重复以上步骤,每次比较次数-1,直到不需要比较
//利用冒泡排序实现升序序列
int arr[9] = { 4,2,8,0,5,7,1,3,9 };
cout << "排序前: " << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//开始冒泡排序
//总共排序轮数为 元素个数 - 1
for (int i = 0; i < 9 - 1; i++)
{
//内层循环 对比次数 = 元素个数 - 当前轮数 - 1
for (int j = 0; j < 9 - i - 1; j++)
{
//如果第一个数字比第二个数字大,交换两个数字
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
cout << "排序后: " << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
二维数组
在一维数组上 多加一个维度
二维数组定义方式
-
数据类型 数组名[行数][列数]
-
数据类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}};
-
数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
-
数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4};
//二维数组定义方式
//数据类型 数组名[行数][列数]
int arr[2][3];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;
/*cout << arr[0][0] << endl;
cout << arr[0][1] << endl;
cout << arr[0][2] << endl;
cout << arr[1][0] << endl;
cout << arr[1][1] << endl;
cout << arr[1][2] << endl;*/
//外层循环打印行数,内层循环打印列数
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j] << endl;
}
}
//数据类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}};
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;
}
//数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
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;
}
//数据类型 数组名[][列数] = {数据1,数据2,数据3,数据4};
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;
}
二维数组数组名
- 查看二维数组所占内存空间
- 获取二维数组首地址
//二维数组名称用途
//1、查看二维数组所占内存空间大小
int arr[2][3] =
{
{1,2,3},
{4,5,6}
};
cout << "二维数组占用空间大小: " << sizeof(arr) << endl;
cout << "二维数组第一行占用内存: " << sizeof(arr[0]) << endl;
cout << "二维数组第一个元素占用内存: " << sizeof(arr[0][0]) << endl;
cout << "二维数组行数:" << sizeof(arr) / sizeof(arr[0]) << endl;
cout << "二维数组列数:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;
//2、查看二维数组首地址
cout << "二维数组首地址: " << (int)arr << endl;
cout << "二维数组第一行首地址: " << (int)arr[0] << endl;
cout << "二维数组第二行首地址: " << (int)arr[1] << endl;
cout << "二维数组第一个元素首地址: " << (int)&arr[0][0] << endl;
cout << "二维数组第二个元素首地址: " << (int)&arr[0][1] << endl;
二维数组应用案例
//二维数组案例
//有三名同学(张三、李四、王五)在一次考试中成绩如下
//请分别输入三名同学的总成绩
// 语文 数学 英语
//张三 100 100 100
//李四 90 50 100
//王五 60 70 80
//1、创建二维数组,3*3
int scores[3][3] =
{
{100,100,100},
{90,50,100},
{60,70,80}
};
string names[3] = { "张三","李四","王五" };
//2、统计考试成绩,让每行3列相加,统计出总和
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += scores[i][j];
}
cout << names[i] << "的总分为: " << sum << endl;
}
函数
将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能
函数定义
5个步骤
1、返回值类型
2、函数名
3、参数列表
4、函数体语句
5、return表达式
返回值类型 函数名(参数列表)
{
函数体语句
return表达式
}
system(“pause”);//按任意键继续
函数的调用
使用定义好的函数
语法:函数名(参数)
//实现一个加法函数,功能是传入两个整型数据,计算相加的结果,并且返回
//定义加法函数
//函数定义时num1和num2并没有真的数据,只是形式上的参数(形参)
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
//函数调用
//a和b称为实际参数(实参)
//当调用函数时,实参的值会传递给形参
int a = 10;
int b = 20;
int c = add(a, b);
cout << c << endl;
a = 100;
b = 500;
c = add(a, b);
cout << c << endl;
值传递
函数调用时实参将数值传入给形参
值传递时,形参发生改变不会影响实参
函数的常见样式
1、无参无返
2、有参无返
3、无参有返
4、有参有返
函数声明
//函数声明
//比较函数 实现两个整型数字进行比较 返回较大的值
//提前告诉编译器 函数存在 利用函数声明
//函数声明
//声明可以写多次,但是定义只能有一次
int max(int a, int b);
int main()
{
int a = 10;
int b = 20;
cout << max(a, b) << endl;
system("pause");
return 0;
}
int max(int a, int b)
{
return a > b ? a : b;
}
函数的分文件编写
使代码结构更加清晰
1、创建后坠为.h的头文件
2、创建后缀为.cpp的源文件
3、在头文件中写函数的声明
4、在源文件中写函数的定义
#include "swap.h"
双引号表示自定义头文件
指针
指针的基本概念
可以通过指针间接访问内存
- 内存编号是从0开始记录的,一般用十六进制数字表示
- 可以利用指针变量保存地址
指针变量的定义和使用
//定义指针
int a = 10;
//指针定义的语法 数据类型 *指针变量名;
int * p;
//让指针记录变量a的地址
p = &a;
cout << "a的地址: " << &a << endl;
cout << "指针p为: " << p << endl;
//2、使用指针
//可以通过解引用的方式找到指针指向的内存
//指针前加*号代表解引用,找到指针指向的内存中的数据
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
指针所占内存空间
指针也是种数据类型
x86编译出来的可执行文件是32位的
//指针所占内存空间
int a = 10;
int* p = &a;
//在32位操作系统下,指针占4个字节空间大小,不管是什么数据类型
//在64位操作系统下,指针占8个字节空间大小,不管是什么数据类型
cout << "sizeof(int *) = " << sizeof(int */*或者写p*/) << endl;
cout << "sizeof(int *) = " << sizeof(double *) << endl;
cout << "sizeof(int *) = " << sizeof(float *) << endl;
cout << "sizeof(int *) = " << sizeof(char *) << endl;
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
0-255内存是系统占用的
//空指针
//1、用于给指针变量初始化
int* p = NULL;
//2、空指针是不可以进行访问的
//0~255之间的内存编号是系统占用的,因此不能访问
*p = 100;//错误
野指针:指针变量指向非法内存空间
//野指针
//在程序中避免出现野指针
//指针变量p指向内存编号为0x1100的空间
int* p = (int *)0x1100;
//访问野指针报错
cout << *p << endl;
const修饰指针
1、const修饰指针 ———常量指针
2、const修饰常量 ———指针常量
3、cons既修饰指针,又修饰常量
指针和数组
利用指针访问数组中元素
//指针和数组
//利用指针访问数组中元素
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "第一个元素为: " << arr[0] << endl;
int* p = arr;//arr就是数组首地址
cout << "利用指针访问第一个元素: " << *p << endl;
p++;//让指针向后偏移4个字节
cout << "利用指针访问第二个元素: " << *p << endl;
cout << "利用指针遍历数组: " << endl;
int* p2 = arr;
for (int i = 0; i < 10; i++)
{
cout << *p2 << endl;
p2++;
}
指针和函数
利用指针作函数参数,可以修改实参的值
//实现两个数字进行交换
void swap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "swap01 a = " << a << endl;
cout << "swap01 b = " << b << endl;
}
void swap02(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
cout << "swap02 a = " << *p1 << endl;
cout << "swap02 b = " << *p2 << endl;
}
int main()
{
//指针和函数
//1、值传递
int a = 10;
int b = 20;
swap01(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//2、地址传递
//如果是地址传递,可以修饰实参
swap02(&a, &b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
指针、数组、函数
封装一个函数,利用冒泡排序,实现对整型数组的升序排序
//封装一个函数,利用冒泡排序,实现对整型数组的升序排序
//冒泡排序函数 参数1 数组的首地址 参数2 数组长度
void bubbleSort(int* arr, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j > j+1的值,交换数字
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
//打印数组
void printArray(int * arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
int main()
{
//1、创建数组
int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
//数组长度
int len = sizeof(arr) / sizeof(arr[0]);
//2、创建函数,实现冒泡排序
bubbleSort(arr, len);
//3、打印排序后的数组
printArray(arr, len);
system("pause");
return 0;
}
结构体
结构体基本概念
属于用户自定义数据类型,允许用户存储不同的数据类型
struct 结构体名{结构体成员列表}
- struct 结构体名 变量名
- struct结构体名 变量名 = {成员1值,成员2值…}
- 在定义结构体时顺便创建结构体变量
#include<iostream>
using namespace std;
#include<string.h>
//1、创建学生的数据类型 : 学生包括(姓名,年龄, 分数)
//自定义数据类型,一些类型集合组成的一个类型
//语法 struct 类型名称 {成员列表}
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3;//顺便创建结构体变量
int main()
{
//2、通过学生类型创建具体学生
//创建结构体时struct关键字可以省略
//2.1 struct Student s1
struct Student s1;
//给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 = 60;
cout << "姓名: " << s3.name << " 年龄: " << s3.age << " 分数: " << s3.score << endl;
system("pause");
return 0;
}
结构体数组
将自定义的结构体放入到数组中方便维护
struct 结构体名 数组名{元素个数} = {{}, {}, … {}}
#include<iostream>
using namespace std;
#include<string.h>
//结构体数组
//1、定义结构体
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main()
{
//2、创建结构体数组
struct Student stuArray[3] =
{
{"张三", 18, 100},
{"李四", 28, 99},
{"王五", 38, 66}
};
//3、给结构体数组中的元素赋值
stuArray[2].name = "赵六";
stuArray[2].age = 80;
stuArray[2].score = 60;
//4、遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名: " << stuArray[i].name
<< " 年龄: " << stuArray[i].age
<< " 分数: " << stuArray[i].score << endl;
}
system("pause");
return 0;
}
结构体指针
作用:通过指针访问结构体中的成员
利用操作符 -> 可以通过结构体指针访问结构体属性
#include<iostream>
using namespace std;
#include<string.h>
//结构体数组
//1、定义结构体
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main()
{
//1、创建学生的结构体变量
Student s = { "张三", 18, 100 };
//2、通过指针指向结构体变量
Student * p = &s;
//3、通过指针访问结构体变量中的数据
//通过结构体指针 访问结构体中的属性,需要利用“->”
cout << "姓名: " << p->name
<< " 年龄: " << p->age
<< " 成绩: " << p->score << endl;
system("pause");
return 0;
}
结构体嵌套结构体
结构体中的成员可以是另一个结构体
例:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
#include<iostream>
using namespace std;
#include<string.h>
//结构体嵌套结构体
//每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
//定义学生结构体
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
//定义老师结构体
struct Teacher
{
int id; //教师编号
string name; //教师姓名
int age; //年龄
struct Student stu; //辅导的学生
};
int main()
{
//创建老师
Teacher t;
t.id = 10000;
t.name = "老王";
t.age = 50;
t.stu.name = "小王";
t.stu.age = 20;
t.stu.score = 60;
cout << "老师姓名: " << t.name
<< " 老师编号: " <<t.id
<< " 老师年龄: " << t.age
<< " 老师辅导的学生姓名: " << t.stu.name
<< " 学生年龄: " << t.stu.age
<< " 学生成绩: " << t.stu.score << endl;
system("pause");
return 0;
}
结构体做函数参数
将结构体作为参数向函数中传递
传递方式:
- 值传递
- 地址传递
#include<iostream>
using namespace std;
#include<string.h>
//定义学生结构体
struct Student
{
string name;
int age;
int score;
};
//1、值传递
void printStudent1(struct Student s)
{
s.age = 100;
cout << "子函数中打印 姓名: " << s.name
<< " 年龄: " << s.age
<< " 成绩: " << s.score << endl;
}
//2、地址传递
void printStudent2(struct Student * p)
{
p->age = 200;
cout << "子函数2中打印 姓名: " << p->name
<< " 年龄: " << p->age
<< " 成绩: " << p->score << endl;
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
struct Student s;
s.name = "张三";
s.age = 20;
s.score = 85;
//printStudent1(s);
printStudent2(&s);
cout << "main函数中打印 姓名: " << s.name << " 年龄: " << s.age << " 成绩: " << s.score << endl;
system("pause");
return 0;
}
结构体中const使用场景
用const来防止误操作
#include<iostream>
using namespace std;
#include<string.h>
//const使用场景
const struct Student
{
string name;
int age;
int score;
};
//将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudents(const Student *s)
{
//s->age = 150;//加入const之后,一旦有修改的操作就会报错,可以防止我们的误操作
cout << "姓名: " << s->name
<< " 年龄: " << s->age
<< " 得分: " << s->score << endl;
}
int main()
{
//创建结构体变量
struct Student s = { "张三", 15, 70 };
//通过函数打印结构体变量信息
printStudents(&s);
cout << "姓名: " << s.name
<< " 年龄: " << s.age
<< " 得分: " << s.score << endl;
system("pause");
return 0;
}
结构体案例
案例1
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数、创建数组存放3名老师,通过函数给每个老师及所带学生赋值
最终打印出老师数据及老师所带学生数据
#include<iostream>
using namespace std;
#include<string>
#include<Ctime>
//学校正在做毕设项目,
//每名老师带领5个学生,总共有3名老师,需求如下:
//设计学生和老师的结构体
//其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
//学生的成员有姓名、考试分数、创建数组存放3名老师,通过函数给每个老师及所带学生赋值
//最终打印出老师数据及老师所带学生数据
//定义学生结构体
struct Student
{
//姓名
string sName;
//分数
int score;
};
struct Teacher
{
//姓名
string tName;
//学生数组
Student sArray[5];
};
//给老师和学生赋值的函数
void allocateSpace(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; //0~60 + 40 = 40~100
tArray[i].sArray[j].score = random;
}
}
}
//打印所有信息
void printInfo(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));
//1、创建3名老师的数组
struct Teacher tArray[3];
//2、通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);
allocateSpace(tArray, len);
//3、打印所有老师及所带学生信息
printInfo(tArray, len);
//cout << "main函数中打印 姓名: " << s.name << " 年龄: " << s.age << " 成绩: " << s.score << endl;
system("pause");
return 0;
}
案例2
设计一个英雄的结构体,包括成员姓名、年龄、性别;创建结构体数组,数组中存放5名英雄。通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果
#include<iostream>
using namespace std;
#include<string>
//1、设计英雄结构体
struct Hero
{
string name;
int age;
string sex;
};
//3、对数组进行排序,按照年龄进行升序排序
void bubbleSort(Hero heroArray[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (heroArray[j].age < heroArray[j + 1].age)
{
//如果j下标元素年龄 大于 j+1下标的元素的年龄,交换两个元素
struct Hero temp = heroArray[j];
heroArray[j] = heroArray[j + 1];
heroArray[j + 1] = temp;
}
}
}
}
//4、对排序结果打印输出
void printHero(Hero heroArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "英雄姓名: " << heroArray[i].name
<< " 英雄年龄: " << heroArray[i].age
<< " 英雄性别: " << heroArray[i].sex << endl;
}
}
int main()
{
//2、创建结构体数组存放5名英雄
struct Hero heroArray[5] =
{
{"刘备", 23, "男"},
{"关羽", 22, "男"},
{"张飞", 20, "男"},
{"赵云", 21, "男"},
{"貂蝉", 19, "女"}
};
int len = sizeof(heroArray) / sizeof(heroArray[0]);
//必要的阶段性测试不能少!!!
//排序前打印
/*for (int i = 0; i < len; i++)
{
cout << "姓名: " << heroArray[i].name
<< " 年龄: " << heroArray[i].age
<< " 性别: " << heroArray[i].sex << endl;
}*/
bubbleSort(heroArray,len);
//排序后打印
printHero(heroArray, len);
system("pause");
return 0;
}