c++基于过程

 前言:

笔记基于C++黑马程序员网课视频:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili
在此发布笔记,只是为方便学习,不做其他用途,原作者为黑马程序员。

1. C++基础

1.1 用Visual Studio写C++程序输出Hello World

1.1.1 下载并配置Visual Studio环境

1.官网www.microsoft.com 2.下载Visual Studio安装包 安装Visual Studio 1.工作负荷:选C++桌面开发

2. 单个组件:默认 (电脑是Window11系统要勾选Window11系统)

3.选择安装位置

4.第一次安装可以改安装位置,否则要改注册表编辑器的设置

 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\Setup 

1.1.2 用Visual Studio写C++程序

代码:

//在屏幕中输出 Hello World#include<iostream>
using namespace std;int main() {cout << "Hello World" << endl;  //屏幕显示“Hello World”system("pause");              //按任意键继续,退出程序return 0;
}/*
Hello World
请按任意键继续. . .
*/

1. main函数

① main函数是一个程序的入口

② 每个程序都必须有这么一个函数,并且有且只有一个。

2. 打印

① cout << "XXXX" << endl; 会使得屏幕打印双引号里面的字符串。

② system("pause"); 会使得屏幕的打印界面暂停到该语句这里,按任意键后才会继续运行。

1.2 注释、变量、常量、标识符、关键字

1.2.1 注释

① 在代码中的加一些说明和解释,这些说明和解释就叫注释。

② 注释能方便自己和其他程序员阅读代码。

③ C++的注释,有两种格式:

1.单行注释: // 描述信息

通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明。

2.多行注释: /* 描述信息 */

编译器在编译代码时,会忽略注释的内容,即不会执行。

1.2.2 变量

① 变量的作用就是就是给一段指定的内存空间起名,方便操作这段内存。

② 语法:数据类型 变量名 = 初始值;

③ 变量存在的意义:方便我们管理内存空间。

④ 每一段内存都有一个地址编号。

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

#include <iostream>
using namespace std;int main()
{//变量创建的语法:数据类型 变量名 = 变量初始值int a = 10;  cout << "a = " << a << endl;   // 输出语句 cout << "提示语" << 变量 << endl; system("pause");return 0;}/*
a = 10
请按任意键继续. . .
*/

1.2.3 常量

① 常量,用于记录程序中不可更改的数据。

② C++定义常量两种方式:

1.define 宏常量:#define 常量名 常量值

通常在文件上方定义,表示一个常量。

2.const修饰的变量:const 数据类型 常量名 = 常量值

通常在变量定义前加关键字const,修饰该变量为常量,不可修改。

#define 常量名 常量值

#include <iostream>
using namespace std;#define Day 7 int main()
{/*Day = 14;  //错误,Day是常量,一旦修改就会报错cout << "一周总共有:" << Day << "天" << endl;*/cout << "一周总共有:" << Day << "天" << endl;// 输出语句:cout << "提示语" << 变量 << endl; system("pause");return 0;}/*
一周总共有:7天
请按任意键继续. . .
*/

 const 数据类型 常量名 = 常量值

#include <iostream>
using namespace std;int main()
{/*const int month = 12;month = 24;  //错误,const修饰的变量也称为常量*/int month = 12;month = 24;  //正确,这样可以修改变量的值cout << "一年总共有:" << month << "个月" << endl;system("pause");return 0;}/*
一年总共有:24个月
请按任意键继续. . .
*/

 1.2.4 关键字

① 关键字是C++中预先保留的单词(标识符)。

② 在定义变量或者常量的时候,不要用关键字。

关键字表:

1. int关键字

#include <iostream>
using namespace std;int main()
{// int int = 10;  // 错误,第二个int是关键字,不可以作为变量的名称system("pause");return 0;}/*
请按任意键继续. . .
*/

2. sizeof关键字

① sizeof关键字可以统计数据类型所占内存大小。

② sizeof关键字,书写语法:sizeof ( 数据类型 / 变量 )

#include <iostream>
using namespace std;int main()
{cout << "short 类型所占内存空间为:" << sizeof(short) << endl;system("pause");return 0;}/*
short 类型所占内存空间为:2
请按任意键继续. . .
*/

1.2.5 标识符

① 标识符就是 C++ 给变量、常量的命名。

② 标识符有一套自己的命名规则:

  1. 标识符不能使关键字。
  2. 标识符只能由字母、数字、下划线组成。
  3. 第一个字符不能为数字。
  4. 标识符中字母区分大小写。

③ 建议:给标识符命名时,争取做到见名知意,方便自己和他人的阅读。

#include <iostream>
using namespace std;int main()
{//1、标识符不可以是关键字//int int = 10;  //报错//2、标识符由字母、数字、下划线构成int abc       =   10;int _abc      =   20;int _123abc   =   40;//3、标识符第一个字符只能是字母或下划线//int 123abc = 50; //报错//4、标识符区分大小写int aaa = 100;//cout << AAA << endl; //报错,AAA和aaa不是同一个名称//建议:给变量起名的时候,最好能够做到见名知意int num1 = 10;int num2 = 20;int sum = num1 + num2; //建议用num1、num2、sum表示加法,而不是用a、b、c来表示cout << sum << endl;system("pause");return 0;}/*
30
请按任意键继续. . .
*/

2. C++的数据类型

2.1.1 整形

① 作用:整型变量表示的是整数类型的数据。

② C++中能够表示整形的类型有以下几种方式,区别在于所占内存空间不同。

③ 数据类型 占用空间 取值范围

  1. short(短整型) 2字节 -2^15-2^15-1
  2. int(整型) 4字节 -2^31-2^31-1
  3. long(长整型) Windows为4字节,Linux为4字节(32位),8字节(64位) -2^31-2^31-1
  4. long long(长长整型) 8字节 -2^63-2^63-1

#include <iostream>
using namespace std;int main()
{//1、短整型(-32768~32767)short num1 = 10;short num5 = 32768; //溢出了,打印出来是-23768short num6 = 32770; //溢出了,打印出来是-32766//2、整型int num2 = 10;//3、长整型long num3 = 10;//4、长长整型long long num4 = 10;cout << "num1 = " << num1 << endl;cout << "num2 = " << num2 << endl;cout << "num3 = " << num3 << endl;cout << "num4 = " << num4 << endl;cout << "num5 = " << num5 << endl;cout << "num6 = " << num6 << endl;system("pause");return 0;}/*
num1 = 10
num2 = 10
num3 = 10
num4 = 10
num5 = -32768
num6 = -32766
请按任意键继续. . .
*/

2.1.2 实型(浮点型)

① 作用:用于表示小数。

② 浮点型变量分为下面两种,两个的区别在于表示有效数字范围不同。

  1. 单精度float
  2. 双精度double

③ 数据类型 占用字节 有效数字范围

  1. float 4字节 7位有效数字
  2. double 8字节 15-16位有效数字

2.1.2.1 单精度、双精度

#include <iostream>
using namespace std;int main()
{//1、单精度  float//2、双精度  double//默认情况下,无论单精度还是双精度,都只会显示6位有效数字float f1 = 3.1415926;  //默认为双精度,前面加float相当于把双精度转换为单精度float f2 = 3.1415926f;  //后面加一个f,直接创建的是单精度cout << "f1 = :" << f1 << endl;double d1 = 3.1415926;cout << "d1 = :" << d1 << endl;cout << "float  占用内存空间为" << sizeof(float) << endl;cout << "double 占用内层空间为" << sizeof(double) << endl;system("pause");return 0;}/*
f1 = :3.14159
d1 = :3.14159
float 占用内存空间为4
double 占用内层空间为8
请按任意键继续. . .
*/

2.1.2.2 科学计数法

#include <iostream>
using namespace std;int main()
{//科学计数法float f3 = 3e2;  // 3 * (10 ^ 2)cout << "f3 = :" << f3 << endl;float f4 = 3e-2; // 3 * (0.1 ^ 2)cout << "f4 = :" << f4 << endl;system("pause");return 0;
}/*
f3 = :300
f4 = :0.03
请按任意键继续. . .
*/

2.1.3 字符型

① 字符型变量用于显示单个字符。

② 语法:char ch = 'a';

③ 在显示字符型变量时,用单引号字符括起来,不要用双引号。

④ 单引号内只能有一个字符,不可以是字符串。

⑤ C和C++中字符型变量只占用1个字节。

⑥ 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元。

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

  1. ASCII非打印控制字符:ASCII表上的数字0-31分配给了控制字符,用于控制像打印机等一些外围设备。
  2. ASCII打印字符:数字21-126分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。
#include <iostream>
using namespace std;int main()
{//1、字符型变量创建方式char ch = 'a';cout << ch << endl;//2、字符型变量所占内存大小cout << "char字符型变量所占内存:" << sizeof(char) << endl;//3、字符型变量常见错误char ch2 = 'b';  //创建字符型变量时候,要用单引号//char ch3 = "b";  //错误,创建字符型变量时候,不能用双引号//char ch4 = 'abcdef'; //错误,创建字符型变量时候,单引号内只能有一个字符//4、字符型变量对应ASCII编码cout << (int)ch << endl;   // (int)ch 为字符'a'的ASCIII码值system("pause");return 0;}/*
a
char字符型变量所占内存:1
97
请按任意键继续. . .
*/

2.1.4 字符串型

① 用于表示一串字符。

② 字符串型有两种风格

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

④ C++风格字符串:string 变量名 = "字符串值"

#include <iostream>
using namespace std;
#include <string> //用C++风格字符串时候,要包含这个头文件int main()
{//1、C风格字符串//char 字符   =    这是一个字符//char 字符[] =    这是一个字符串//表示字符串时,等号后面,要用双引号char str[] = "hello world";cout << str << endl;//2、C++风格字符串string str2 = "hello world";cout << str2 << endl;system("pause");return 0;}/*
hello world
hello world
请按任意键继续. . .
*/

2.1.5 布尔类型 bool

① 布尔数据类型代表真或假的值。

② bool类型只有两个值:

  1. true -- 真 (本质是1)
  2. false -- 假(本质是0)

③ bool类型占1个字节大小

#include <iostream>
using namespace std;int main()
{//1、创建bool数据类型bool flag1 = true; //true代表真cout << flag1 << endl;bool flag2 = false; //flag 代表假cout << flag2 << endl;//本质上 1代表真 0代表假//2、查看bool类型所占空间cout << "bool所占内存空间:" << sizeof(flag1) << endl;cout << "bool所占内存空间:" << sizeof(flag2) << endl;system("pause");return 0;}/*
1
0
bool所占内存空间:1
bool所占内存空间:1
请按任意键继续. . .
*/
 

2.1.6 转义字符

① 用于表示一些不能显示出来的ASCII字符。

② 我们常用的转义字符有:\n、\、\t。

#include <iostream>
using namespace std;int main()
{//换行符 \ncout << "hello world\n";//反斜杠 \\    要输出反斜杠\时,要在前面加上一个反斜杠cout << "\\" << endl;//水平制表符\t  可以整齐的输出数据cout << "aaaa\thellowworld" << endl;cout << "aa\thellowworld" << endl;cout << "aaaaaa\thellowworld" << endl;system("pause");return 0;}/*
hello world
\
aaaa hellowworld
aa hellowworld
aaaaaa hellowworld
请按任意键继续. . .
*/

2.1.7 数据输入

① 数据的输入,作用:用于从键盘获取数据。

② 数据的输入,关键字:cin

③ 数据饿输入,语法:cin >> 变量

#include <iostream>
using namespace std;
#include <string>  //包含string的头文件
int main()
{//1、创建bool数据类型int a = 0;cout << "请给整型变量 a 赋值:" << endl;cin >> a;cout << "整型变量a = " << a << endl;//2、浮点型float f = 3.14f;cout << "请给浮点型变量 f 赋值:" << endl;cin >> f;cout << "浮点型变量 f = " << f << endl;//3、字符型char ch ;  //仅仅声明了,没有初始化cout << "请给字符型变量 ch 赋值:" << endl;cin >> ch;cout << "字符型变量 ch = " << ch << endl;//4、字符型string str = "hello";cout << "请给字符串 str 赋值:" << endl;cin >> str;cout << "字符型变量 str = " << str << endl;//4、布尔型bool flag = false;cout << "请给布尔类型 flag 赋值:" << endl;cin >> flag;   //布尔类型  只要是非0的值都代表真cout << "布尔类型 flag = " << flag << endl;system("pause");return 0;}/*
请给整型变量 a 赋值:
23
整型变量a = 23
请给浮点型变量 f 赋值:
23.4
浮点型变量 f = 23.4
请给字符型变量 ch 赋值:
w
字符型变量 ch = w
请给字符串 str 赋值:
asfg
字符型变量 str = asfg
请给布尔类型 flag 赋值:
4562
布尔类型 flag = 1
请按任意键继续. . .
*/
 

3. C++的运算符

① 运算符作用:用于执行代码的运算。

② 运算符类型主要有四种:

  1. 算术运算符:用于处理四则运算。
  2. 赋值运算符:用于将表达式的值赋给变量
  3. 比较运算符:用于表达式的比较,并返回一个真值或假值。
  4. 逻辑运算法:用于表达式的值返回真值或假值。

3.1 算术运算符

3.1.1 加减乘除运算

#include <iostream>
using namespace std;int main()
{int a1 = 10;int b1 = 3;cout << a1 + b1 << endl;cout << a1 - b1 << endl;cout << a1 * b1 << endl;cout << a1 / b1 << endl;  //两个整数相除,结果依然是整数,将小数部分去除int a2 = 10;int b2 = 20;cout << a2 / b2 << endl;int a3 = 10;int b3 = 0;//cout << a3 / b3 << endl;  //两个数相除,除数不可以为0//两个小数可以相除double d1 = 0.51;        //如果d1为0.5,运算结果为整数2double d2 = 0.25;cout << d1 / d2 << endl; //运算结果也可以是小数system("pause");return 0;}/*
13
7
30
3
0
2.04
请按任意键继续. . .
*/
 

3.1.2 取模运算

#include <iostream>
using namespace std;int main()
{//取摸运算本质  就是求余数int a1 = 10;int b1 = 3;cout << a1 % b1 << endl;/*两个数相除,除数不可以为0,所以也做不了取模运算int a2 = 10;int b2 = 0;cout << a2 % b2 << endl;  //*//*两个小数是不可以做取模运算的double d1 = 3.14;double d2 = 1.1;cout << d1 % d2 << endl;*/system("pause");return 0;}/*
1
请按任意键继续. . .
*/

3.1.3 递增递减运算

#include <iostream>
using namespace std;int main()
{//1、前置递增int a = 10;++a;cout << "a=" << a << endl;//2、后置递增int b = 15;b++;cout << "b=" << b << endl;//3、前置和后置的区别//前置递增,先让变量+1 然后进行表达式运算int a2 = 10;int b2 = ++a2 * 10;cout << "a2= " << a2 << endl;cout << "b2= " << b2 << endl;//后置递增,先进行表达式运算,后让变量+1int a3 = 10;int b3 = a3++ * 10;cout << "a3= " << a3 << endl;cout << "b3= " << b3 << endl;system("pause");return 0;}/*
a=11
b=16
a2= 11
b2= 110
a3= 11
b3= 100
请按任意键继续. . .
*/
 

3.2 赋值运算符

#include <iostream>
using namespace std;int main()
{// = 赋值int a = 10;a = 100;cout << "a= " << a << endl;// += 加等于int b = 10;b = 10;b += 2;cout << "b= " << b << endl;// -= 减等于int c = 10;c = 10;c -= 2;cout << "c= " << c << endl;// *= 乘等于int d = 10;d = 10;d *= 2;cout << "d= " << d << endl;// /= 除等于int e = 10;e = 10;e /= 2;cout << "e= " << e << endl;// %= 模等于int f = 10;f = 10;f %= 2;cout << "f= " << f << endl;system("pause");return 0;}/*
a= 100
b= 12
c= 8
d= 20
e= 5
f= 0
请按任意键继续. . .
*/
 

3.3 比较运算符

① 作用:用于表达式的比较,并返回一个真值或假值。

#include <iostream>
using namespace std;int main()
{//比较运算符// ==int a = 10;int b = 20;cout << (a == b) << endl;// !=cout << (a != b) << endl;// >cout << (a > b) << endl;// <cout << (a < b) << endl;// >=cout << (a >= b) << endl;// <=cout << (a <= b) << endl;system("pause");return 0;}/*
0
1
0
1
0
1
请按任意键继续. . .
*/
 

3.4 逻辑运算符

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

  1. !a 表示非,如果a为假,则!a为真;如果a为真,则!a为假。
  2. a&&b 表示与,如果a和b都为真,则结果为真,否则为假。
  3. a||b 表示或,如果a和b有一个为真,则结果为真,二者都为假时,结果为假。
#include <iostream>
using namespace std;int main()
{//逻辑运算符// !=int a = 10;int b = 30;cout << (!a) << endl;  //在C++中除了0,都为真cout << (!!a) << endl;// &&a = 10;b = 30;cout << (a && b) << endl;a = 0;b = 10;cout << (a && b) << endl;// ||a = 10;b = 30;cout << (a || b) << endl;a = 0;b = 10;cout << (a || b) << endl;a = 0;b = 0;cout << (a || b) << endl;system("pause");return 0;}/*
0
1
1
0
1
1
0
请按任意键继续. . .
*/
 

4. C++的程序流程结构

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

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

4.1 选择结构

4.1.1 单行 if 语句

① 单行if语句,格式:if(条件){条件满足执行的语句}

#include <iostream>
using namespace std;int main()
{// 选择结构 单行if语句// 用户输入分数,如果分数大于600,视为考上一本大学,在屏幕上输出//1、用户输入分数int score = 0;cout << "请输入一个分数:" << endl;  //在C++中除了0,都为真cin >> score;//2、打印用户输入的分数cout << "您输入的分数为 :" << score << endl;//3、判断分数是否大于600,如果大于,那么输出//注意事项,if条件后面不要加分号。加了分号条件不管满足还是不满足,后面的都会运行if (score > 600){cout << "恭喜您考上了一本大学" << endl;}system("pause");return 0;}/*
请输入一个分数:
611
您输入的分数为 :611
恭喜您考上了一本大学
请按任意键继续. . .
*/
 

4.1.2 单行 else 语句

① 单行else语句,格式:if(条件){条件满足执行的语句} else{条件不满足执行的语句}

#include <iostream>
using namespace std;int main()
{// 选择结构 多行if语句// 输入考试分数,如果分数大于600,视为考上一本大学,在屏幕上输出// 如果没考上一本大学,打印未考上一本大学//1、输入考试分数int score = 0;cout << "请输入一个考试分数" << endl;cin >> score;//2、提示用户输入的分数cout << "您输入的分数为:" << score << endl;//3、判断 如果大于600,打印考上一本,否则打印未考上一本大学if (score > 600) //大于600分,执行下面大括号中内容{cout << "恭喜您考上了一本大学" << endl;}else //不大于600分,执行else后大括号中内容{cout << "未考上一本大学" << endl;}system("pause");return 0;}/*
请输入一个考试分数
490
您输入的分数为:490
未考上一本大学
请按任意键继续. . .
*/
 

4.1.3 多条件的 if 语句

① 多条件的if语句,格式:if(条件1){条件1满足执行的语句}else if(条件){条件2满足执行的语句}....else{都不满足时执行的语句}

#include <iostream>
using namespace std;int main()
{// 选择结构 多条件if语句// 输入一个考试分数,// 如果分数大于600,视为考上一本大学,在屏幕上输出// 如果分数大于500,视为考上二本大学,在屏幕上输出// 如果分数大于400,视为考上三本大学,在屏幕上输出// 如果小于等于400,视为未考上本科,屏幕上输出//1、输入考试分数int score = 0;cout << "请输入一个考试分数" << endl;cin >> score;//2、提示用户输入的分数cout << "您输入的分数为:" << score << endl;//3、判断 // 如果大于600,考上一本// 如果大于500,考上二本// 如果大于400,考上三本// 如果小于等于400,未考上本科if (score > 600) {cout << "恭喜您考上了一本大学" << endl;}else if (score > 500) {cout << "恭喜您考上了二本大学" << endl;}else if (score > 400) {cout << "恭喜您考上了三本大学" << endl;}else {cout << "未考上本科大学" << endl;}system("pause");return 0;}/*
请输入一个考试分数
430
您输入的分数为:430
恭喜您考上了三本大学
请按任意键继续. . .
*/
 

4.1.4 嵌套 if 语句

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

#include <iostream>
using namespace std;int main()
{// 选择结构 嵌套if语句//1、提示高考分数int score = 0;cout << "请输入一个考试分数" << endl;cin >> score;//2、提示用户输入的分数cout << "您输入的分数为:" << score << endl;//3、判断 if (score > 600) {cout << "恭喜您考上了一本大学" << endl;if (score > 700){cout << "您能考上了北京大学" << endl;}else if (score > 650){cout << "您能考上了清华大学" << endl;}else{cout << "您能考上了人名大学" << endl;}}else if (score > 500){cout << "恭喜您考上了二本大学" << endl;}else if (score > 400){cout << "恭喜您考上了三本大学" << endl;}else{cout << "未考上本科大学" << endl;}system("pause");return 0;}/*
请输入一个考试分数
670
您输入的分数为:670
恭喜您考上了一本大学
您能考上了清华大学
请按任意键继续. . .
*/
 

4.1.5 三目运算符

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

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

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

③ 三目运算符可以用在显示语句中,cout << "c = " << c == 1 ? "男" : "女" << endl。

#include <iostream>
using namespace std;int main()
{// 创建三个变量 a b c// 将a和b做比较,将变量大的值赋值给变量cint 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;system("pause");return 0;}/*
c = 20
a = 10
b = 100
请按任意键继续. . .
*/
 

4.1.6 switch 语句

① switch语句用于执行多条件分支语句。

② switch语句中表达式类型只能是整型或者字符型。

③ case里如果没有break,那么程序会一直向下执行。

④ 与if语句比,对于多条件判断时,switch的结构清晰,执行效率高,缺点是switch不可以判断区间。

#include <iostream>
using namespace std;int main()
{//1、提示用户给电影评分cout << "请给电影进行评分" << endl;//2、用户开始进行打分int score = 0;cin >> score;cout << "您打的分数为:" << score << endl;//3、根据用户输入的分数来提示用户最后的结果switch (score){case 10:cout << "您认为是经典的电影" << endl; break;case 9:cout << "您认为是经典的电影" << endl;break;case 8:cout << "您认为电影非常好" << endl;break;case 7:cout << "您认为电影还行" << endl;break;case 6:cout << "您认为电影一般" << endl;break;default:  //前面都不满足,就会执行default语句cout << "您认为电影是烂片" << endl;break;}//if 和 switch 区别://switch 缺点,判断的时候只能是整型或者字符型,不可以是一个区间。//switch 优点,结构清晰,执行效率高。system("pause");return 0;}/*
请给电影进行评分
8
您打的分数为:8
您认为电影非常好
请按任意键继续. . .
*/
 

4.1.7 三只小猪称体重

题目:现有三只小猪ABC,请分别输入三只小猪的体重,并且判断哪只小猪最重。

#include <iostream>
using namespace std;int main()
{//三只小猪称体重,判断哪只最重//1、创建三只小猪的体重变量int num1 = 0;int num2 = 0;int num3 = 0;//2、让用户输入三只小猪的重量cout << "请输入小猪A的体重" << endl;cin >> num1;cout << "请输入小猪B的体重" << endl;cin >> num2;cout << "请输入小猪C的体重" << endl;cin >> num3;cout << "小猪A的体重为:" << num1 << endl;cout << "小猪B的体重为:" << num2 << endl;cout << "小猪C的体重为:" << num3 << endl;//3、判断哪只最重//先判断A和B重量if (num1 > num2)  //A比B重{if (num1 > num3)  //A比C重{cout << "小猪A最重" << endl;}else{cout << "小猪C最重" << endl;}}else  //B比A重{if (num2 > num3)  //B比C重{cout << "小猪B最重" << endl;}else //C比B重{cout << "小猪C最重" << endl;}}system("pause");return 0;}/*
请输入小猪A的体重
100
请输入小猪B的体重
230
请输入小猪C的体重
300
小猪A的体重为:100
小猪B的体重为:230
小猪C的体重为:300
小猪C最重
请按任意键继续. . .
*/
 

4.2 循环结构

4.2.1 while 语句

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

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

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

#include <iostream>
using namespace std;int main()
{//while循环//在屏幕中打印 0~9 这10个数字int num = 0;//while()中填入循环条件//在写循环的时候,一定要避免死循环的出现while (num < 10)  //如果循环条件写1,为表示死循环,一直循环下去{cout << num << endl;num++;}// 在执行循环语句时候,程序必须提供跳出循环的出口,否则出现死循环。system("pause");return 0;}/*
0
1
2
3
4
5
6
7
8
9
请按任意键继续. . .
*/
 

4.2.2 do while 语句

① 满足循环条件,执行循环语句。

② 语法:

do{

循环语句

} while(循环条件);

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

#include <iostream>
using namespace std;int main()
{//do...while语句//在屏幕中输出 0 到 9 这10个数字int num = 0;do{cout << num << endl;num++;} while (num < 10);//do...while和while循环区别在于 do...while会先执行一次循环语句system("pause");return 0;
}/*
0
1
2
3
4
5
6
7
8
9
请按任意键继续. . .
*/
 

4.2.3 for 语句

① for循环,满足循环条件,执行循环语句。

② for(起始表达式(①);条件表达式②;末尾表达式③) { 循环语句④ }

  1. 先执行①,初始化
  2. 再执行②,进行判断
  3. 再执行④,进行一次循环
  4. 再执行③,执行一次末尾表达式

③ for循环中的表达式,要用分号进行分隔。

④ while、for...while、for都是开发中常用的循环语句,for循环结构比较清晰,比较常用。

#include <iostream>
using namespace std;int main()
{//for循环//从数字0 打印到 数字9for (int i = 0; i < 10; i++){cout << i << endl;}/*第二种方式int i = 0for (; i < 10; i++){cout << i << endl;}*//*第三种方式int i = 0for (; ; i++){if(i >= 10){break;}cout << i << endl;}*//*第四种方式int i = 0for (; ; ){if(i >= 10){break;}cout << i << endl;i++;}*/system("pause");return 0;}/*
0
1
2
3
4
5
6
7
8
9
请按任意键继续. . .
*/
 

4.2.4 for 嵌套

① 在循环体中再嵌套一层循环,可以解决一些实际问题,例如我们想在屏幕中打印十行十列的星图,就需要利用嵌套循环。

#include <iostream>
using namespace std;int main()
{//利用嵌套循环实现星图//外层执行一次,内层执行一周//外层循环for (int i = 0; i < 10; i++){//内层循环for (int j = 0; j < 10; j++){cout << "*";}cout << endl;}system("pause");return 0;}/*
**********
**********
**********
**********
**********
**********
**********
**********
**********
**********
请按任意键继续. . .
*/
 

4.2.5 猜数字

① 案例描述:系统随机生成一个1到100之间的数字,玩家进行猜测,如果猜错,提示玩家数字过大或过小,如果猜对恭喜玩家胜利,并且退出游戏。

#include <iostream>
using namespace std;
#include<ctime> //time系统时间头文件int main()
{//添加随机数种子,作用利用当前系统时间生成随机数,防止每次随机数都一样srand((unsigned int)time(NULL));//1、系统生成随机数int num = rand() % 100 + 1; //rand()%100 生成 0+1 ~ 99+1 随机数//cout << num << endl;      //不显示生成的随机数是多少//2、玩家进行猜测int val = 0;  //玩家输入的数据while (1){cin >> val;//3、判断玩家的判断if (val > num){cout << "猜测过大" << endl;}else if (val < num){cout << "猜测过小" << endl;}else{cout << "猜测您猜对了" << endl;break;  //break在循环中,可以利用该关键字来退出当前循环}}system("pause");return 0;
}/*
32
猜测过小
60
猜测过大
54
猜测过大
40
猜测过大
38
猜测过大
35
猜测过大
33
猜测您猜对了
请按任意键继续. . .
*/
 

4.2.6 水仙花数

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

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

题目:请利用 do...while语句,求出所有3位数中的水仙花数

#include <iostream>
using namespace std;int main()
{int num = 100;do{//2、从所有三位数中找到水仙花数int a;  //个位int b;  //十位int c;  //百位a = num % 10; //获取数字的个位b = num / 10 % 10; //获取数字的十位c = num / 100; //获取数字的百位if (a * a * a + b * b * b + c * c * c == num) //如果是水仙花数,才打印{cout << num << endl;}num++;} while (num < 1000);system("pause");return 0;
}/*
153
370
371
407
请按任意键继续. . .
*/
 

4.2.7 敲桌子(逢7过)

案例分析:从1开始数到数字100,如果数字个位含有7,或者数字十位含有7,或者该数字是7的倍数,我们打印敲桌子,其余数字直接打印输出。

#include <iostream>
using namespace std;int main()
{//敲桌子案例for (int i = 1; i <= 100; i++){//从100个数字中找到特殊数字,打印“敲桌子”//如果是7的倍数、个位有7、或者十位有7,打印“敲桌子”if (i % 7 == 0 || i % 10 == 7 || i/10 == 7) {cout << "敲桌子" << endl;}else //如果不是特殊数字,才打印数字{cout << i << endl;}}system("pause");return 0;
}/*
1
2
3
4
5
6
敲桌子
8
9
10
11
12
13
敲桌子
15
16
敲桌子
18
19
20
敲桌子
22
23
24
25
26
敲桌子
敲桌子
29
30
31
32
33
34
敲桌子
36
敲桌子
38
39
40
41
敲桌子
43
44
45
46
敲桌子
48
敲桌子
50
51
52
53
54
55
敲桌子
敲桌子
58
59
60
61
62
敲桌子
64
65
66
敲桌子
68
69
敲桌子
敲桌子
敲桌子
敲桌子
敲桌子
敲桌子
敲桌子
敲桌子
敲桌子
敲桌子
80
81
82
83
敲桌子
85
86
敲桌子
88
89
90
敲桌子
92
93
94
95
96
敲桌子
敲桌子
99
100
请按任意键继续. . .
*/
 

4.2.8 乘法口诀

案例描述:利用嵌套循环,实现九九乘法表。

#include <iostream>
using namespace std;int main()
{//乘法口诀表for (int i = 1; i <= 9; i++){for (int j = 1; j <= i; j++){cout << j << "*" << i << "=" << j * i << " ";}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
请按任意键继续. . .
*/
 

4.3 跳转语句

4.3.1 break 语句

① 用于跳出选择结构或者循环结构。

② break使用时机:

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

③ break如果使用在switch-case中,并且case前面有一大段代码,就会报错,把前面一大堆代码用括号括起来{},编译器认为是一段代码,就不会报错了。

#include <iostream>
using namespace std;int main()
{//break的使用时机//1、出现在switch语句中cout << "请选择副本难度" << endl;cout << "1、普通" << endl;cout << "2、中等" << endl;cout << "3、困难" << endl;int select = 0; cin >> select; //等待用户输入switch (select){case 1:cout << "您选择的是普通难度" << endl;break; //退出switch语句case 2:cout << "您选择的是中等难度" << endl;break;case 3:cout << "您选择的是困难难度" << endl;break;}//2、出现在循环语句中for (int i=0; i < 10; i++){//如果i等于5,退出循环,不再打印if (i == 5){break; //退出循环}cout << i << endl;}//3、出现在嵌套循环语句中for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){if (j == 5){break; //退出内存循环}cout << "*";}cout << endl;}system("pause");return 0;
}/*
请选择副本难度
1、普通
2、中等
3、困难
2
您选择的是中等难度
0
1
2
3
4
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
∗∗∗∗∗
请按任意键继续. . .
*/
 

4.3.2 continue 语句

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

#include <iostream>
using namespace std;int main()
{//continue的使用时机for (int i = 0; i <= 100; i++){// 如果是奇数就输出,如果是偶数就不输出if (i % 2 == 0) {continue; //continue可以筛选条件,执行到此就不再向下执行了,直接执行下一次循环}cout << i << endl;}system("pause");return 0;
}/*
1
3
5
7
9
11
13
15
17
19
21
23
25
27
29
31
33
35
37
39
41
43
45
47
49
51
53
55
57
59
61
63
65
67
69
71
73
75
77
79
81
83
85
87
89
91
93
95
97
99
请按任意键继续. . .
*/
 

4.3.3 goto 语句

① 可以无条件跳转语句。

② 语法:

goto 标记;

标记:

③ 在程序中不建议使用goto语句,以免造成程序流程混乱。

#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;system("pause");return 0;
}/*
1
5
6
请按任意键继续. . .
*/
 

5. C++的数组

5.1 数组特点

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

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

5.2 一维数组

5.2.1 定义方式

① 一维数组定义:

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

② 数组名的命名规范与变量名命名规范一致,不要和变量重名。

③ 数组中下标是从0开始索引。

#include <iostream>
using namespace std;int main()
{//1、数组类型 数组名 [ 数组长度 ]int arr[5];//数组元素的下标是从0开始索引的//给数组中的元素进行赋值arr[0] = 10;arr[1] = 20;arr[2] = 30;arr[3] = 40;arr[4] = 50;//访问数据元素cout << arr[0] << endl;cout << arr[1] << endl;cout << arr[2] << endl;cout << arr[3] << endl;cout << arr[4] << endl;//2、数据类型 数组名 [ 数组长度 ] = { 值1,值2,... }//如果在初始化数据的时候,没有完全填写完,会用0来填补剩余数据int arr2[5] = { 10,20,30 };/*方式一:cout << arr2[0] << endl;cout << arr2[1] << endl;cout << arr2[2] << endl;cout << arr2[3] << endl;cout << arr2[4] << endl;*/// 方式二:利用循环输出数组中的元素for (int i = 0; i < 5; i++){cout << arr2[i] << endl;}//3、数据类型 数组名 [ ] = { 值1,值2,.... }int arr3[] = { 90,80,70,60,50,40,30,20,10 };  //以后自定义变量,不要 int arr3 = 100,这样避免以后调用arr3到底是调用变量还是数组产生模糊。for (int i = 0; i < 9; i++){cout << arr3[i] << endl;}system("pause");return 0;
}/*
10
20
30
40
50
10
20
30
0
0
90
80
70
60
50
40
30
20
10
请按任意键继续. . .
*/
 

5.2.2 数组名

① 一维数组名的用途:

  1. 可以统计整个数组在内存中的长度。
  2. 可以获取数组在内存中的首地址。
#include <iostream>
using namespace std;int main()
{//数组名用途//1、可以通过数组名统计整个数组占用内存大小int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };cout << "整个数组占用内存空间为:" << sizeof(arr) << endl;cout << "每个元素占用内存空间为:" << sizeof(arr[0]) << endl;cout << "数组中元素的个数为:"     << sizeof(arr)/sizeof(arr[0]) << endl;//2、可以通过数组名查看数组首地址cout << "数组首地址为:" << (int)arr << endl;cout << "数组中第一个元素地址为:" << (int)&arr[0] << endl;  //int使得将十六位地址通过int转换为10位地址,&表示取址符号,取一个元素的首地址cout << "数组中第二个元素地址为:" << (int)&arr[1] << endl;  //第二个元素和第一个元素差四个字节//数组名是常量,值为数组首地址,不可以进行赋值操作//arr = 100;  不可以这样赋值修改system("pause");return 0;}/*
整个数组占用内存空间为:40
每个元素占用内存空间为:4
数组中元素的个数为:10
数组首地址为:12582108
数组中第一个元素地址为:12582108
数组中第二个元素地址为:12582112
请按任意键继续. . .
*/
 

5.2.3 五只小猪称体重

案例描述:在一个数组中记录了五只小猪的体重,如:int arr[5]={300,350,200,400,250},找出并打印最重的小猪体重。

#include <iostream>
using namespace std;int main()
{//1、创建5只小猪体重的数组int arr[5] = { 300,350,200,400,250 };//2、从数组中找到最大值int max = 0; //先认定一个最大值为0for (int i = 0; i < 5; i++){//cout << arr[i] << endl;if (arr[i] > max){max = arr[i];}}//3、打印最大值cout << max << endl;system("pause");return 0;}/*
400
请按任意键继续. . .
*/
 

5.2.4 数组元素逆置

案例描述:请声明一个5个元素的数组,并且将元素逆置。(如原数组元素为:1,3,2,5,4;逆置后输出的结果为:4,5,2,3,1)。

#include <iostream>
using namespace std;int main()
{//实现数组元素逆置//1、创建数组int arr[5] = { 1,3,2,5,4 };cout << "数组逆置前" << endl;for (int i = 0; i < 5; i++){cout << arr[i] << endl;}//2、实现逆置//2.1 记录起始下标位置//2.2 记录结束下标位置//2.3 起始下标与结束下标的元素互换//2.4 起始位置++ 结束位置--//2.5 循环执行2.1操作,直到起始位置 >= 结束位置int start = 0; //起始下标int end = sizeof(arr) / sizeof(arr[0]) - 1; //结束下标,先计算除法  while (start < end){int 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] << endl;}system("pause");return 0;
}/*
数组逆置前
1
3
2
5
4
数组逆置后
4
5
2
3
1
请按任意键继续. . .
*/
 

5.2.5 冒泡排序

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

  1. 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的go牛牛公主,执行完毕后,找到第一个最大值。
  3. 重复以上的步骤,每次比较次数-1.直到不需要比较。

② 示例:将数组(4,2,8,0,5,7,1,3,9)进行排序。

#include <iostream>
using namespace std;int main()
{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;//开始冒泡排序for (int i = 0; i < 9 - 1; i++){//内层循环对比  次数=元素个数=当前轮数-1for (int j = 0; j < 9 - 1 - i; 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] << " ";}cout << endl;system("pause");return 0;
}/*
排序前
4 2 8 0 5 7 1 3 9
排序后
0 1 2 3 4 5 7 8 9
请按任意键继续. . .
*/

5.3 二维数组

5.3.1 定义方式

① 二维数组就是在一维数组上,多加一个维度。

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

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

③ 以上4种定义方式,利用第二种更加直观,提高代码的可读性。

④ 定义二维数组的时候,如果初始化了数据,可以省略行数。

#include <iostream>
using namespace std;int main()
{//1、数据类型 数组名 [ 行数 ][ 列数 ];int arr[2][3];arr[0][0] = 1;arr[0][1] = 2;arr[0][2] = 3;arr[1][0] = 4;arr[1][1] = 5;arr[1][2] = 6;//外层循环打印行数,内层循环打印列数for (int i = 0; i < 2; i++){for (int j = 0; j < 3; j++){cout << arr[i][j] << endl;}}//2、数据类型 数组名 [ 行数 ][ 列数 ] = { { 数据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;  //换行语句}//3、数据类型 数组名 [ 行数 ][ 列数 ] = { 数据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 << arr2[i][j] << " ";}cout << endl;}//4、数据类型 数组名 [  ][ 列数 ] = { 数据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 << arr2[i][j] << " ";}cout << endl;}system("pause");return 0;}/*
1
2
3
4
5
6
1 2 3
4 5 6
1 2 3
4 5 6
1 2 3
4 5 6
请按任意键继续. . .
*/
 

5.3.2 数组名

① 查看二维数组所占内存空间。

② 获取二维数组首地址。

#include <iostream>
using namespace std;int main()
{//二维数组名称用途//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 << endl;cout << "二维数组第一行首地址为:" << (int)arr[0] << endl;cout << "二维数组第二行首地址为:" << (int)arr[1] << endl;cout << "二维数组第一个元素首地址为:" << (int)&arr[0][0] << endl;cout << "二维数组第二个元素首地址为:" << (int)&arr[0][1] << endl;  //每个元素地址相差4个字节system("pause");return 0;}/*
二维数组占用内存空间为: 24
二维数组第一行占用内存为:12
二维数组第一个元素占用内存为:4
二维数组行数为:2
二维数组列数为:3
二维数组首地址为:3733652
二维数组第一行首地址为:3733652
二维数组第一行首地址为:3733652
二维数组第二行首地址为:3733664
二维数组第一个元素首地址为:3733652
二维数组第二个元素首地址为:3733656
请按任意键继续. . .
*/
 

5.3.3 考试成绩

案例描述:有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的成绩。

姓名语文数学英语
张三100100100
李四9050100
王五607080
#include <iostream>
using namespace std;int main()
{//二维数组案例-考试成绩统计//1、创建二维数组int scores[3][3] ={{100,100,100},{90,50,100},{60,70,80}};//2、统计每个人的总和分数for (int i = 0; i < 3; i++){int sum = 0; //统计分数总和不变for (int j = 0; j < 3; j++){sum += scores[i][j];//cout << scores[i][j] << " ";}cout << "第" << i + 1 << "个人的总分为:" << sum << endl;}system("pause");return 0;
}/*
第1个人的总分为:300
第2个人的总分为:240
第3个人的总分为:210
请按任意键继续. . .
*/
 

6. C++的函数

6.1 函数概述

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

② 一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。

6.2 函数定义

① 函数的定义主要有5个部分:

  1. 返回值类型:一个函数可以返回一个值。
  2. 函数名:给函数起个名称。
  3. 参数列表:使用该函数时,传入的数据。
  4. 函数体语句:花括号内的代码,函数内需要执行的语句。
  5. return表达式:和返回值类型挂钩,函数执行完后,返回相应的数据。

② 语法格式如下所示:

返回值类型 函数名 (参数列表)
{函数体语句return 表达式
}
#include <iostream>
using namespace std;//函数的定义
//语法:返回值类型 函数名 (参数列表) { 函数体语句 return表达式 }//加法函数,实现两个整型相加,并且将相加的结果进行返回
int add(int num1, int num2)
{int sum = num1 + num2;return sum;
}int main()
{system("pause");   //按任意键继续return 0;}
 

6.3 函数调用

① 功能:使用定义好的函数

② 语法:函数名(参数)

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

#include <iostream>
using namespace std;//函数的定义
//语法:
//返回值类型 函数名 (参数列表) { 函数体语句 return表达式 }//定义加法函数
//函数定义的时候,num1和num2并不是真实数据
//它们只是一个形式上的参数,简称形参
int add(int num1, int num2)
{int sum = num1 + num2;return sum;
}int main()
{//main函数中调用add函数int a = 10;int b = 20;//函数调用语法:函数名称:(参数)//a和b称为 实际参数,简称实参//当调用函数的时候,实参的值会传递给形参int c = add(a, b);cout << "c = " << c << endl;system("pause");   //按任意键继续return 0;}/*
c = 30
请按任意键继续. . .
*/
 

6.4 函数值传递

① 所谓值传递,就是函数调用时实参将数值传入给形参。

② 值传递时,如果形参发生改变,并不影响实参。

③ 在下面代码例子中,实参传进去时,新参会产生新的内存空间赋值,对num1、num2的操作并不会改变实参a、b的值。

#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;  //前面写了void,所以不需要返回值。返回值不需要的时候,也可以不写return。
}int main()
{//main函数中调用add函数int a = 10;int b = 20;cout << "a = " << a << endl;cout << "b = " << b << endl;//当我们把值传递的时候,函数的形参发生发生改变,并不会影响实参swap(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
*/
 

6.5 函数常见样式

① 常见的函数样式有四种

  1. 无参无返
  2. 有参无返
  3. 无参有返
  4. 有参有返
#include <iostream>
using namespace std;//函数常见样式
//1、无参无返
void test01()
{cout << "this is test01" << 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 a = " << a << 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 test01
this is test 02 a = 100
this is test 03
num1 = 1000
this is test 04 a = 10000
num2 = 10000
*/
 

6.6 函数声明

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

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

#include <iostream>
using namespace std;//函数的声明
//比较函数,实现两个整型数字进行比较,返回较大的值。//提前告诉编译器函数的存在,可以利用函数的声明
//函数的声明
//声明可以写多次,但是定义只能有一次
int max(int a, int b);
int max(int a, int b);
int max(int a, int b);int main()
{int a = 10;int b = 20;cout << max(a, b) << endl;system("pause");   //按任意键继续return 0;}//函数定义在main函数之后,必须要在main函数之前写函数的声明
int max(int a, int b)
{return a > b ? a : b;
}/*
20
按任意键继续...
*/
 

6.7 函数分文件编写

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

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

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

6.7.1 swap.h头文件

创建swap.h头文件

//这个是swap.h头文件
#include <iostream>
using namespace std;//函数的声明
void swap(int a, int b);
 

6.7.2 swap.cpp源文件

//这个是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;
}
 

6.7.3 主文件

//主文件,调用函数分文件
#include <iostream>
using namespace std;
#include "swap.h"  //包含要调用的函数的头文件,双引号表示我们自己写的头文件int main()
{int a = 10;int b = 20;cout << max(a, b) << endl;system("pause");   //按任意键继续return 0;
}/*
20
*/
 

7. C++的指针

7.1 指针概念

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

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

7.2 指针变量定义和使用

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

#include <iostream>
using namespace std;int main()
{//1、定义指针int a = 10;//指针定义的语法:数据类型 * 指针变量int * p; //创建p为指针变量//让指针记录变量a的地址p = &a;  // &为取址符号cout << "a的地址为:" << &a << endl;cout << "指针p为:" << p << endl;  // 指针p存储的值 和变量a的地址是一样的//2、使用指针//可以通过解引用的方式来找到指针指向的内存//指针前加 * 代表解引用,找到指针指向的内存中的数据*p = 1000;  //通过*p访问内存,并修改内存的值cout << "a= " << a << endl;cout << "*p:" << *p << endl;system("pause");   //按任意键继续return 0;}/*
a的地址为:00FBFC78
指针p为:00FBFC78
a= 1000
*p:1000
请按任意键继续. . .
*/
 

7.3 指针所占内存空间

① 在32位操作系统下,不管什么类型的指针都占4个字节的内存。

② 在64位操作系统下,不管什么类型的指针都占8个字节的内存,但是实际开发环境一般都是32位操作系统下。

#include <iostream>
using namespace std;int main()
{//指针所占内存空间int a = 10;/*int * p; //p变量是 int * 数据类p = &a;等价于:int * p = &a;*/int * p = &a; cout << "sizeof(int * )= " << sizeof(p) << endl;cout << "sizeof(int * )= " << sizeof(int(*)) << endl;  cout << "sizeof(float * )= " << sizeof(float(*)) << endl;cout << "sizeof(double * )= " << sizeof(double(*)) << endl;cout << "sizeof(char * )= " << sizeof(char(*)) << endl;system("pause");   //按任意键继续return 0;}/*
sizeof(int * )= 4
sizeof(int * )= 4
sizeof(float * )= 4
sizeof(double * )= 4
sizeof(char * )= 4
请按任意键继续. . .
*/
 

7.4 空指针

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

② 用途:初始化指针变量。

③ 空指针指向的内存是不可以访问的。

#include <iostream>
using namespace std;int main()
{//空指针//1、空指针用于给指针变量进行初始化int* p = NULL;//2、空指针是不可以进行访问的//0~255之间的内存编号是系统占用的,因此不可以访问。*p = 100;  //对空指针解引用,然后操作它,这样是报错的system("pause");   //按任意键继续return 0;}
 

7.5 野指针

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

② 野指针和空指针都不是我们申请的空间,所以不要访问。

③ 例如,创建了一个整型变量a,是申请了一个整型变量的空间,由于是申请的空间,所以可以通过指针访问它。

#include <iostream>
using namespace std;int main()
{//野指针int* p = (int*)0x1100; // 0x1100是一个十六进制数,int*使得十六进制数强行转换为地址。// 拿指针随便指向并没有申请这个内存的访问权限的内存。cout << *p << endl; // 报错,地址并没有申请,你还要去访问它,就会报错system("pause");   return 0;}
 

7.6 const修饰指针

① 看const紧跟着的是指针就是常量指针,是常量就是指针常量

② 如果const后面跟的是指针(*),就不能做 *p=20 操作,即不能修改指针指向的值。

③ 如果const 后面跟的常量(p),就不能做 p = &b 操作,即不能修改指针的指向。

const在 * 前,修饰整个指针指向的地址,值不可以修改

const在 * 后,修饰特定的指针名字,指向不可以修改

#include <iostream>
using namespace std;int main()
{int a = 10;int b = 10;//1、const修饰指针 常量指针const int * p = &a;  // const(常量)   *(指针) → 常量指针 // *p = 20;  错误,常量指针 → 指针指向的值不可以改,指针的指向可以改p = &b; // 正确//2、const修饰指针 指针常量int * const p2 = &a; // *(指针)   const(常量) → 指针常量*p2 = 100; //正确的p2 = &b;  //错误,指针的指向不可以改,指针指向的 值可以改//3、const修饰指针和常量const int * const p3 = &a;*p3 = 100;  //错误p3 = &b;  //错误system("pause");   return 0;
}

7.7 指针和数组

① 利用指针访问数组中元素。

#include <iostream>
using namespace std;int main()
{//指针和数组//利用指针访问数组中的元素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++;cout << "利用指针访问第二个元素:" << *p << endl;cout << "利用指针遍历数组:" << endl;int* p2 = arr;for (int i = 0; i < 10; i++) {//cout << arr[i] << endl;cout << *p2 << endl;p2++;}system("pause");   return 0;
}/*
第一个元素为:1
利用指针访问第一个元素:1
利用指针访问第二个元素:2
利用指针遍历数组:
1
2
3
4
5
6
7
8
9
10
请按任意键继续. . .
*/
 

7.8 指针和函数

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

② 地址传递可以改变实参的数据,值传递不可以改变实参的值。

③ 如果不想修改实参,就用值传递,如果想修改实参,就用地址传递。

④ 代码例子中,temp的值会传递给 *p2 地址中的值,所以a、b实参的值改变了。

#include <iostream>
using namespace std;void swap(int* p1, int* p2)
{int temp = *p1;*p1 = *p2;*p2 = temp;
}int main()
{//指针和函数int a = 10;int b = 20;swap(&a, &b);//如果是地址传递,可以修改实参,原来 a = 10;b = 20,地址传递后 a = 20,b = 10.cout << "a =" << a << endl;cout << "b =" << b << endl;//如果是值传递,不可以修改实参,原来 a = 10;b = 20,值传递后 a = 10,b = 20.system("pause");return 0;}/*
a =20
b =10
请按任意键继续. . .
*/
 

7.9 指针配合数组和函数案例

案例描述:封装一个函数,利用冒泡排序,实现对整型数字的升序排列。

例如: int arr[10] = {4,3,6,9,1,2,10,8,7,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++){//如果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,1,2,9,10,8,7,5 };//数组长度int len = sizeof(arr) / sizeof(arr[0]);//2、创建函数,实现冒泡排序bubbleSort(arr, len);//3、打印排序后的数组printArray(arr, len);system("pause");return 0;}/*
1
2
3
4
5
6
7
8
9
10
请按任意键继续. . .
*/
 

8. C++的结构体

8.1 结构体定义和使用

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

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

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

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

④ 结构体变量利用点.访问成员

#include <iostream>
using namespace std;
#include <string>
//自定义数据类型,一些类型的集合组成一个类型
//语法 struct 类型名称 { 成员列表 }
//结构体定义的时候,struct关键字不能省略
//1、创建学生数据类型:学生包括(姓名,年龄,分数)
struct Student
{//成员列表//姓名string name;//年龄int age;//分数int score;
}s3;   //2.3 创建结构体的时候,顺便创建个结构体变量int main()
{//2.1 struct Student s1  s1类似结构体的实例值,类似变量赋值:int a = 10 → 属性 变量 变量值//结构体创建的时候,struct 关键字可以省略;上面结构体定义的时候 struct 可以省略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;
}/*
姓名:张三年龄:18分数:100
姓名:李四年龄:19分数:80
姓名:王五年龄:20分数:60
请按任意键继续. . .
*/
 

8.2 结构体数组

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

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

#include <iostream>
using namespace std;
#include <string>
//自定义数据类型,一些类型的集合组成一个类型
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;
}/*
姓名:张三年龄:18分数:100
姓名:李四年龄:28分数:99
姓名:赵六年龄:80分数:60
请按任意键继续. . .
*/
 

8.3 结构体指针

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

② 利用操作符 · > 可以通过结构体指针访问结构体属性。

#include <iostream>
using namespace std;
#include <string>//结构体指针//定义学生结构体
struct Student
{string name; //姓名int age; //年龄int score; //分数
};int main()
{// 1、创建学生结构体变量,这里的 struct 可以省略struct Student s = { "张三",18,100 };//2、通过指针指向结构体变量struct Student* p = &s;  //对s取地址, tudent * p 类似 int * p,这里的 struct 可以省略//3、通过指针访问结构体变量中的数据//通过结构体指针 访问结构体中的属性,需要利用'->'cout << "姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << endl;system("pause");return 0;}/*
姓名:张三年龄:18分数:100
请按任意键继续. . .
*/
 

8.4 结构体嵌套结构体

① 结构体中的成员可以是另一个结构体。

#include <iostream>
using namespace std;
#include <string>//因为老师的结构体里有学生的结构体,所以学生结构体要在老师结构体前面先定义
//定义学生结构体
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;}/*
老师姓名:老王 老师编号:10000 老师年龄:50 老师辅导的学生姓名:小王 学生年龄:20 学生考试分数:60
请按任意键继续. . .
*/
 

8.5 结构体做函数参数

① 作用:将结构体作为参数向函数中传递,传递方式有两种。

② 传递方式有两种:

  1. 值传递
  2. 地址传递
#include <iostream>
using namespace std;
#include <string>//定义学生结构体
struct student
{string name; //姓名int age; //年龄int score; //分数
};//定义老师结构体
struct teacher
{int id; //教师编号string name; //教师姓名int age; //年龄struct student stu; //学生结构体
};//打印学生信息的函数
//1、值传递
void printStudent1(struct student s)
{cout << "子函数 值传递前 姓名:" << s.name << "年龄:" << s.age << "分数:" << s.score << endl;s.age = 100;
}//2、地址传递
void printStudent2(struct student* p)
{cout << "子函数 地址传递前 姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << endl;p->score = 90;
}int main()
{//结构体做函数参数//将学生传入到一个参数中,打印学生身上的所有信息//创建结构体变量struct student s;s.name = "张三";s.age = 20;s.score = 85;cout << "main函数 传递前 姓名:" << s.name << "年龄:" << s.age << "分数:" << s.score << endl;printStudent1(s);cout << "子函数  值传递后 姓名:" << s.name << "年龄:" << s.age << "分数:" << s.score << endl;printStudent2(&s);cout << "子函数 地址传递后 姓名:" << s.name << "年龄:" << s.age << "分数:" << s.score << endl;cout << "main函数 传递后 姓名:" << s.name << "年龄:" << s.age << "分数:" << s.score << endl;system("pause");return 0;}/*
main函数 传递前 姓名:张三年龄:20分数:85
子函数 值传递前 姓名:张三年龄:20分数:85
子函数 值传递后 姓名:张三年龄:20分数:85
子函数 地址传递前 姓名:张三年龄:20分数:85
子函数 地址传递后 姓名:张三年龄:20分数:90
main函数 传递后 姓名:张三年龄:20分数:90
请按任意键继续. . .
*/
 

8.6 结构体中const使用

① 作用:const来防止误操作。

#include <iostream>
using namespace std;
#include <string>//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 << "main中张三年龄为:" << s.age << endl;system("pause");return 0;}
 

8.7 结构体案例(一)

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

#include <iostream>
using namespace std;
#include <string>
#include <Ctime>//学生结构体定义
struct Student
{//姓名string sName;//学生数组int score;
};//老师结构体
struct Teacher
{//姓名string tName;//学生数组struct Student sArray[5];
};//给老师和学生赋值的函数
void allocateSpace(struct Teacher tArray[], int len) //接收数组的两种方式:一用指针,二用数组名 struct Teacher tArray[]
{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 ~ 100tArray[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));//1、创建3名老师的数组struct Teacher tArray[3];//2、通过函数给3名老师的信息赋值,并给老师带的学生信息赋值int len = sizeof(tArray) / sizeof(tArray[0]);allocateSpace(tArray, len);//3、打印所有老师及所带的学生信息printInfo(tArray, len);system("pause");return 0;}/*
老师姓名:Teacher_A学生姓名:Student_A 考试分数:57学生姓名:Student_B 考试分数:84学生姓名:Student_C 考试分数:85学生姓名:Student_D 考试分数:43学生姓名:Student_E 考试分数:62
老师姓名:Teacher_B学生姓名:Student_A 考试分数:88学生姓名:Student_B 考试分数:44学生姓名:Student_C 考试分数:68学生姓名:Student_D 考试分数:100学生姓名:Student_E 考试分数:67
老师姓名:Teacher_C学生姓名:Student_A 考试分数:88学生姓名:Student_B 考试分数:73学生姓名:Student_C 考试分数:71学生姓名:Student_D 考试分数:48学生姓名:Student_E 考试分数:55
请按任意键继续. . .
*/
 

8.8 结构体案例(二)

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

五名英雄信息如下:

  • {"刘备",23,"男"}
  • {"关羽",22,"男"}
  • {"张飞",20,"男"}
  • {"赵云",21,"女"}
  • {"貂蝉",19,"女"}
#include <iostream>
using namespace std;//1、设计英雄结构体
struct Hero
{//姓名string name;//年龄int age;//性别string sex;
};//冒泡排序,实现年龄升序排列
void bubbleSort(struct Hero heroArray[], int len)
{for (int i = 0; i < len - 1; i++){for (int j = 0; j < len - i - 1; j++){//如果j下标的年龄大于j+1下标的元素的年龄,交换两个元素if (heroArray[j].age > heroArray[j + 1].age){struct Hero temp = heroArray[j];  //创建一个临时结构体变量heroArray[j] = heroArray[j + 1];heroArray[j + 1] = temp;}}}
}void printHero(struct 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]);cout << "排序前的打印结果" << endl;for (int i = 0; i < len; i++){cout << "姓名:" << heroArray[i].name << " 年龄:" << heroArray[i].age<< " 性别:" << heroArray[i].sex << endl;}//3、对数组进行排序,按照年龄进行升序排序bubbleSort(heroArray, len);//4、将排序后结果打印输出cout << "排序后的打印结果" << endl;printHero(heroArray,len);system("pause");return 0;}/*
排序前的打印结果
姓名:刘备 年龄:23 性别:男
姓名:关羽 年龄:22 性别:男
姓名:张飞 年龄:20 性别:男
姓名:赵云 年龄:21 性别:女
姓名:貂蝉 年龄:19 性别:女
排序后的打印结果
姓名:貂蝉 年龄:19 性别:女
姓名:张飞 年龄:20 性别:男
姓名:赵云 年龄:21 性别:女
姓名:关羽 年龄:22 性别:男
姓名:刘备 年龄:23 性别:男
请按任意键继续. . .
*/
 

9. 通讯录管理系统

#include<iostream>
using namespace std;
#include<string>//string头文件
#define MAX 1000//联系人结构体
struct Person
{//姓名string m_Name;//性别 1 男 2 女int m_Sex;//年龄int m_Age;//电话string m_Phone;//住址string m_Addr;
};
//通讯录结构体
struct Addressbooks
{//通讯录中保存的联系人数组struct Person personArray[MAX];//通讯录中当前记录联系人个数int m_Size;};//1、添加联系人
void addPerson(Addressbooks* abs)
{//判断通讯录是否已满,如果满了就不再添加if (abs->m_Size == MAX){cout << "通讯录已满,无法添加!" << endl;return;}else{//添加联系人//姓名string name;cout << "请输入姓名:"<<endl;cin >> name;abs->personArray[abs->m_Size].m_Name = name;//性别cout << "请输入性别:" << endl;cout << "1 --- 男" << endl;cout << "2 --- 女" << endl;int sex = 0;while (true){//输入正确,退出循环//输入错误,重新输入cin >> sex;if (sex == 1 || sex == 2){abs->personArray[abs->m_Size].m_Sex = sex;break;}cout << "输入有误,请重新输入" << endl;}//年龄cout << "请输入年龄:" << endl;int age = 0;cin >> age;abs->personArray[abs->m_Size].m_Age = age;//电话cout << "请输入电话:" << endl;string phone;cin >> phone;abs->personArray[abs->m_Size].m_Phone = phone;//住址cout << "请输入住址:" << endl;string address;cin >> address;abs->personArray[abs->m_Size].m_Addr = address;//更新通讯录人数abs->m_Size++;cout << "添加成功" << endl;system("pause");//按任意键继续system("cls");//清屏}  
}//2、显示所有联系人
void showPerson(Addressbooks* abs)
{////if (abs->m_Size == 0){cout << "当前记录为空" << endl;}else{for (int i = 0;i < abs->m_Size;i++){cout << "姓名:" << abs->personArray[i].m_Name << "\t";cout << "性别:" <<(abs->personArray[i].m_Sex == 1 ?"男":"女") << "\t";cout << "年龄:" << abs->personArray[i].m_Age << "\t";cout << "电话:" << abs->personArray[i].m_Phone << "\t";cout << "住址:" << abs->personArray[i].m_Addr << endl;}}system("pause");//按任意键继续system("cls");//清屏
}//3、删除指定联系人
//检测联系人是否存在,如果存在,返回联系人所在数组中的具体位置,不存在返回-1
//参数1  通讯录  参数2  对比姓名
int isExist(Addressbooks* abs, string name)
{for (int i = 0;i < abs->m_Size;i++){//找到用户输入的名字if (abs->personArray[i].m_Name == name){return i;  //找到了,返回这个人在数组中的下标编号}}return -1;//没找到,返回-1
}
void deletePerson(Addressbooks* abs)
{cout << "请输入您要删除的联系人" << endl;string name;cin >> name;//ret == -1 未查到,ret!= -1 查到了int ret = isExist(abs, name);if (ret != -1){//查到此人,要进行删除操作for (int i = ret;i < abs->m_Size;i++){//数据前移abs->personArray[i] = abs->personArray[i + 1];}abs->m_Size--;//更新通讯录中的人员数cout << "删除成功" << endl;}else{cout << "查无此人" << endl;}system("pause");system("cls");
}//4、查找指定联系人
void findPerson(Addressbooks* abs)
{cout << "请输入您要查找的联系人" << endl;string name;cin >> name;//判断指定联系人是否存在通讯录中int ret = isExist(abs, name);if (ret != -1)//找到联系人{cout << "姓名:" << abs->personArray[ret].m_Name << "\t";cout << "性别:" << abs->personArray[ret].m_Sex << "\t";cout << "年龄:" << abs->personArray[ret].m_Age << "\t";cout << "电话:" << abs->personArray[ret].m_Phone << "\t";cout << "住址:" << abs->personArray[ret].m_Addr << endl;}else//未找到联系人{cout << "查无此人" << endl;}system("pause");system("cls");
}//5、修改指定联系人信息
void modifyPerson(Addressbooks* abs)
{cout << "请输入您要修改的联系人" << endl;string name;cin >> name;int ret = isExist(abs, name);if (ret != -1){//姓名string name;cout << "请输入名字:" << endl;cin >> name;abs->personArray[ret].m_Name = name;//性别cout << "请输入性别:" << endl;cout << "1 --- 男" << endl;cout << "2 --- 女" << endl;int sex = 0;while (true){cin >> sex;if (sex == 1 || sex == 2){//输入正确,退出循环输入abs->personArray[ret].m_Sex = sex;break;}cout << "输入有误,请重新输入" << endl;}//年龄cout << "请输入年龄" << endl;int age = 0;cin >> age;abs->personArray[ret].m_Age = age;//电话cout << "请输入电话" << endl;string phone;cin >> phone;abs->personArray[ret].m_Phone = phone;//住址cout << "请输入住址" << endl;string address;cin >> address;abs->personArray[ret].m_Addr = address;cout << "修改成功" << endl;}else{cout << "查无此人" << endl;}system("pause");system("cls");
}//6、清空所以联系人
void cleanPerson(Addressbooks* abs)
{abs->m_Size = 0;cout << "通讯录已清空" << endl;system("pause");system("cls");
}
//菜单页面void showMenu()
{cout << "*************************" << endl;cout << "***** 1、添加联系人 *****" << endl;cout << "***** 2、显示联系人 *****" << endl;cout << "***** 3、删除联系人 *****" << endl;cout << "***** 4、查找联系人 *****" << endl;cout << "***** 5、修改联系人 *****" << endl;cout << "***** 6、清空联系人 *****" << endl;cout << "***** 0、退出联系人 *****" << endl;cout << "*************************" << endl;
}int main()
{//创建通讯录结构体变量Addressbooks abs;//初始化通讯录中当前人员个数abs.m_Size = 0;int select = 0; while (true){//菜单调用showMenu();cin >> select;switch (select){case 1:addPerson(&abs);//利用地址传递,可以修饰实参break;case 2:showPerson(&abs); break;case 3:deletePerson(&abs);break;case 4:findPerson(&abs);break;case 5:modifyPerson(&abs);break;case 6:cleanPerson(&abs);break;case 0:cout << "欢迎下次使用" << endl;system("pause");return 0;break;}}system("pause");return 0;
}

10. 内存分区模型

C++程序在执行时,将内存大方向划分为4个区域

  • 代码区:存放函数体的二进制代码,由操作系统进行管理的
  • 全局区:存放全局变量和静态变量以及常量
  • 栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等
  • 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收

内存四区意义:

不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程

10.1 程序运行前

​ 在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域

​ 代码区:

​ 存放 CPU 执行的机器指令

​ 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可

​ 代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

​ 全局区:

​ 全局变量和静态变量存放在此.

​ 全局区还包含了常量区, 字符串常量和其他常量也存放在此.

​ 该区域的数据在程序结束后由操作系统释放.

示例:

#include <iostream>
using namespace std;//全局变量
int g_a = 10;
int g_b = 10;//全局常量
const int c_g_a = 10;
const int c_g_b = 10;int main() {//局部变量int a = 10;int b = 10;//打印地址cout << "局部变量a地址为: " << (int)&a << endl;cout << "局部变量b地址为: " << (int)&b << endl;cout << "全局变量g_a地址为: " << (int)&g_a << endl;cout << "全局变量g_b地址为: " << (int)&g_b << endl;//静态变量static int s_a = 10;static int s_b = 10;cout << "静态变量s_a地址为: " << (int)&s_a << endl;cout << "静态变量s_b地址为: " << (int)&s_b << endl;cout << "字符串常量地址为: " << (int)&"hello world" << endl;cout << "字符串常量地址为: " << (int)&"hello world1" << endl;cout << "全局常量c_g_a地址为: " << (int)&c_g_a << endl;cout << "全局常量c_g_b地址为: " << (int)&c_g_b << endl;const int c_l_a = 10;const int c_l_b = 10;cout << "局部常量c_l_a地址为: " << (int)&c_l_a << endl;cout << "局部常量c_l_b地址为: " << (int)&c_l_b << endl;system("pause");return 0;
}/*
局部变量a地址为: 6945460
局部变量b地址为: 6945448
全局变量g_a地址为: 7323648
全局变量g_b地址为: 7323652
静态变量s_a地址为: 7323656
静态变量s_b地址为: 7323660
字符串常量地址为: 7314420
字符串常量地址为: 7314436
全局常量c_g_a地址为: 7314224
全局常量c_g_b地址为: 7314228
局部常量c_l_a地址为: 6945436
局部常量c_l_b地址为: 6945424
请按任意键继续. . .
*/

总结:

  • C++中在程序运行前分为全局区和代码区
  • 代码区特点是共享和只读
  • 全局区中存放全局变量、静态变量、常量
  • 常量区中存放 const修饰的全局常量 和 字符串常量

10.2 程序运行后

​ 栈区:

​ 由编译器自动分配释放, 存放函数的参数值,局部变量等

​ 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

代码:

#include <iostream>
using namespace std;int* func()
{int a = 10;return &a;
}int main() {int* p = func();cout << *p << endl;cout << *p << endl;system("pause");return 0;
}/*
10
1478068336
请按任意键继续. . .
*/

​ 堆区:

​ 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收

​ 在C++中主要利用new在堆区开辟内存

代码:

#include <iostream>
using namespace std;int* func()
{int* a = new int(10);return a;
}int main() {int *p = func();cout << *p << endl;cout << *p << endl;system("pause");return 0;
}

总结:

堆区数据由程序员管理开辟和释放

堆区数据利用new关键字进行开辟内存

10.3 new操作符

​ C++中利用new操作符在堆区开辟数据

​ 堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 delete

​ 语法:new 数据类型

​ 利用new创建的数据,会返回该数据对应的类型的指针

示例1: 基本语法

#include <iostream>
using namespace std;
//1、new的基本语法
int* func()
{//在堆区创建整型//new返回的是 该数据类型的指针int* a = new int(10);return a;
}int main() {int* p = func();cout << *p << endl;cout << *p << endl;cout << *p << endl;cout << *p << endl;//堆区的数据 由程序员管理开辟、释放//利用delete释放堆区数据delete p;//cout << *p << endl; //报错,释放的空间不可访问system("pause");return 0;
}/*
10
10
10
10
请按任意键继续. . .
*/

示例2:开辟数组

#include <iostream>
using namespace std;//堆区开辟数组
int main() {int* arr = new int[10];for (int i = 0; i < 10; i++){arr[i] = i + 100;}for (int i = 0; i < 10; i++){cout << arr[i] << endl;}//释放数组 delete 后加 []delete[] arr;system("pause");return 0;
}

 代码:

#include <iostream>
using namespace std;
//1、new的基本语法
int* func()
{//在堆区创建整型//new返回的是 该数据类型的指针int* a = new int(10);return a;
}//2、在堆区利用new开辟数组
void test02()
{//在堆区创建10个元素的整型数据的数组int* arr = new int[10];for (int i = 0; i < 10; i++){arr[i] = i + 100;//给10个元素赋值100~109}for (int i = 0; i < 10; i++){cout << arr[i] << endl;}//释放数组 delete 后加 []delete[] arr;}int main() {int* p = func();cout << *p << endl;cout << *p << endl;cout << *p << endl;//堆区的数据 由程序员管理开辟、释放//利用delete释放堆区数据delete p;//cout << *p << endl; //报错,释放的空间不可访问//int* p = func();  错误“p” : 重定义;多次初始化test02();test02();system("pause");return 0;
}/*
10
10
10
100
101
102
103
104
105
106
107
108
109
100
101
102
103
104
105
106
107
108
109
请按任意键继续. . .
*/

11. 引用

11.1 引用的基本使用

作用: 给变量起别名

语法: 数据类型 &别名 = 原名

示例:

#include <iostream>
using namespace std;int main() {int a = 10;int &b = a;cout << "a = " << a << endl;cout << "b = " << b << endl;b = 100;cout << "a = " << a << endl;cout << "b = " << b << endl;system("pause");return 0;
}

11.2 引用注意事项

  • 引用必须初始化
  • 引用在初始化后,不可以改变

示例:

#include <iostream>
using namespace std;int main() {int a = 10;int b = 20;//int &c; //错误,引用必须初始化int &c = a; //一旦初始化后,就不可以更改c = b; //这是赋值操作,不是更改引用cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;system("pause");return 0;
}

11.3 引用做函数参数

作用:函数传参时,可以利用引用的技术让形参修饰实参

优点:可以简化指针修改实参

示例:

#include <iostream>
using namespace std;//1. 值传递
void mySwap01(int a, int b) {int temp = a;a = b;b = temp;
}//2. 地址传递
void mySwap02(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}//3. 引用传递
void mySwap03(int& a, int& b) {int temp = a;a = b;b = temp;
}int main() {int a = 10;int b = 20;mySwap01(a, b);cout << "a:" << a << " b:" << b << endl;mySwap02(&a, &b);cout << "a:" << a << " b:" << b << endl;mySwap03(a, b);cout << "a:" << a << " b:" << b << endl;system("pause");return 0;
}

总结:通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单

11.4 引用做函数返回值

作用:引用是可以作为函数的返回值存在的

注意:不要返回局部变量引用

用法:函数调用作为左值

示例:

#include <iostream>
using namespace std;//返回局部变量引用
int& test01() {int a = 10; //局部变量return a;
}//返回静态变量引用
int& test02() {static int a = 20;return a;
}int main() {//不能返回局部变量的引用int& ref = test01();cout << "ref = " << ref << endl;cout << "ref = " << ref << endl;//如果函数做左值,那么必须返回引用int& ref2 = test02();cout << "ref2 = " << ref2 << endl;cout << "ref2 = " << ref2 << endl;test02() = 1000;cout << "ref2 = " << ref2 << endl;cout << "ref2 = " << ref2 << endl;system("pause");return 0;
}

11.5 引用的本质

本质:引用的本质在c++内部实现是一个指针常量.

讲解示例:

#include <iostream>
using namespace std;//发现是引用,转换为 int* const ref = &a;
void func(int& ref){ref = 100; // ref是引用,转换为*ref = 100
}
int main(){int a = 10;//自动转换为 int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改int& ref = a; ref = 20; //内部发现ref是引用,自动帮我们转换为: *ref = 20;cout << "a:" << a << endl;cout << "ref:" << ref << endl;func(a);return 0;
}

结论:C++推荐用引用技术,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了

11.6 常量引用

作用:常量引用主要用来修饰形参,防止误操作

在函数形参列表中,可以加const修饰形参,防止形参改变实参

示例:

#include <iostream>
using namespace std;//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {//v += 10;cout << v << endl;
}int main() {//int& ref = 10;  引用本身需要一个合法的内存空间,因此这行错误//加入const就可以了,编译器优化代码,int temp = 10; const int& ref = temp;const int& ref = 10;//ref = 100;  //加入const后不可以修改变量cout << ref << endl;//函数中利用常量引用防止误操作修改实参int a = 10;showValue(a);system("pause");return 0;
}

12. 函数提高

12.1 函数默认参数

在C++中,函数的形参列表中的形参是可以有默认值的。 

语法:返回值类型 函数名 (参数= 默认值){}

示例:

#include<iostream>
using namespace std;//1. 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值
int func1(int a, int b = 10, int c = 10) {return a + b + c;
}//2. 如果函数声明有默认值,函数实现的时候就不能有默认参数
int func2(int a = 10, int b = 10);
int func2(int a, int b) {return a + b;
}//3. 如果函数实现有默认值,函数声明的时候就不能有默认参数
int func3(int a, int b);
int func3(int a = 10, int b = 10) {return a + b;
}int main() {//cout << "ret = " << func1() << endl;错误cout << "ret = " << func1(20) << endl;cout << "ret = " << func1(20, 20) << endl;cout << "ret = " << func1(20,20,20) << endl;cout << "ret = " << func2() << endl;cout << "ret = " << func3() << endl;system("pause");return 0;
}/*
ret = 40
ret = 50
ret = 60
ret = 20
ret = 20
请按任意键继续. . .
*/

12.2 函数占位参数

C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置

语法: 返回值类型 函数名 (数据类型){}

在现阶段函数的占位参数存在意义不大,但是后面的课程中会用到该技术

示例:

#include<iostream>
using namespace std;void func1(int a) {cout << "this is func1" << endl;
}
//函数占位参数 
void func2(int a, int) {cout << "this is func2" << endl;
}
//占位参数也可以有默认参数
void func3(int a, int = 10) {cout << "this is func3" << endl;
}int main() {func1(10);func2(10, 10); //占位参数必须填补//func2();错误//func2(10);错误func3(10);func3(10,20);system("pause");return 0;
}/*
this is func1
this is func2
this is func3
this is func3
请按任意键继续. . .
*/

12.3 函数重载

12.3.1 函数重载概述

作用:函数名可以相同,提高复用性

函数重载满足条件:

  • 同一个作用域下
  • 函数名称相同
  • 函数参数类型不同 或者 个数不同 或者 顺序不同

注意: 函数的返回值不可以作为函数重载的条件

示例:

#include<iostream>
using namespace std;//函数重载需要函数都在同一个作用域下
void func()
{cout << "func 的调用!" << endl;
}
void func(int a)
{cout << "func (int a) 的调用!" << endl;
}
void func(double a)
{cout << "func (double a)的调用!" << endl;
}
void func(int a, double b)
{cout << "func (int a ,double b) 的调用!" << endl;
}
void func(double a, int b)
{cout << "func (double a ,int b)的调用!" << endl;
}
/*
函数返回值不可以作为函数重载条件
int func(double a, int b)
{cout << "func (double a ,int b)的调用!" << endl;
}
*/int main() {func();func(10);func(3.14);func(10, 3.14);func(3.14, 10);system("pause");return 0;
}/*
func 的调用!
func (int a) 的调用!
func (double a)的调用!
func (int a ,double b) 的调用!
func (double a ,int b)的调用!
请按任意键继续. . .
*/

12.3.2 函数重载注意事项

  • 引用作为重载条件
  • 函数重载碰到函数默认参数

示例:

#include<iostream>
using namespace std;//函数重载注意事项
//1、引用作为重载条件
void func(int& a)
{cout << "func (int &a) 调用 " << endl;
}void func(const int& a)
{cout << "func (const int &a) 调用 " << endl;
}//2、函数重载碰到函数默认参数
void func2(int a, int b = 10)
{cout << "func2(int a, int b = 10) 调用" << endl;
}void func2(int a)
{cout << "func2(int a) 调用" << endl;
}int main() {int a = 10;func(a); //调用无constfunc(10);//调用有const//func2(10); //碰到默认参数产生歧义,需要避免system("pause");return 0;
}/*
func (int &a) 调用
func (const int &a) 调用
请按任意键继续. . .
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/496906.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows配置cuda,并安装配置Pytorch-GPU版本

文章目录 1. CUDA Toolkit安装2. 安装cuDNN3. 添加环境变量配置Pytorch GPU版本 博主的电脑是Windows11&#xff0c;在安装cuda之前&#xff0c;请先查看pytorch支持的版本&#xff0c;cuda可以向下兼容&#xff0c;但是pytorch不行&#xff0c;请先进入&#xff1a;https://py…

【202】仓库管理系统

-- 基于springboot仓库管理系统设计与实现 开发技术栈: 开发语言 : Java 开发软件 : Eclipse/MyEclipse/IDEA JDK版本 : JDK8 后端技术 : SpringBoot 前端技术 : Vue、Element、HTML、JS、CsS、JQuery 服务器 : Tomcat8/9 管理包 : Maven 数据库 : MySQL5.x/8 数据库工具 : …

Debian安装配置RocketMQ

安装配置 本次安装在/tools/rocket目录下 下载 wget https://dist.apache.org/repos/dist/release/rocketmq/5.3.1/rocketmq-all-5.3.1-bin-release.zip 解压缩 unzip rocketmq-all-5.3.1-bin-release.zip 如果出现以下报错 -bash: unzip: command not found可安装unzip工具后执…

php的zip扩展 先装libzip

【宝塔面板】php7.4 安装 zip 扩展 - PHP笔记网 在CentOS 7系统中&#xff0c;通过【宝塔Linux】安装了PHP7.4&#xff0c;运行业务系统时&#xff0c;报错&#xff1a; 1 it is missing from your system. Install or enable PHPs zip extension. 提示需要php的zip扩展&…

【Java-tesseract】OCR图片文本识别

文章目录 一、需求二、概述三、部署安装四、技术细节五、总结 一、需求 场景需求:是对识别常见的PNG,JPEG,TIFF,GIF图片识别&#xff0c;环境为离线内网。组件要求开源免费&#xff0c;并且可以集成Java生成接口服务。 二、概述 我不做选型对比了,我筛选测试了下Tesseract(v…

【RabbitMQ的死信队列】

死信队列 什么是死信队列死信队列的配置方式死信消息结构 什么是死信队列 消息被消费者确认拒绝。消费者把requeue参数设置为true(false)&#xff0c;并且在消费后&#xff0c;向RabbitMQ返回拒绝。channel.basicReject或者channel.basicNack。消息达到预设的TTL时限还一直没有…

使用 Three.js 创建一个 3D 人形机器人仿真系统

引言 在这篇文章中&#xff0c;我们将探讨如何使用 Three.js 创建一个简单但有趣的 3D 人形机器人仿真系统。这个机器人可以通过键盘控制进行行走和转向&#xff0c;并具有基本的动画效果。 技术栈 HTML5Three.jsJavaScript 实现步骤 1. 基础设置 首先&#xff0c;我们需要…

Python大数据可视化:基于python大数据的电脑硬件推荐系统_flask+Hadoop+spider

开发语言&#xff1a;Python框架&#xff1a;flaskPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 价格区间界面 用户信息界面 品牌管理 笔记本管理 电脑主机…

修改vue-element-admin,如何连接我们的后端

改哪几个文件就可以连接我们后端 ​​​​​​​ 主要就这四个 main.js&#xff0c;屏蔽这个或者删除 vue-config 最后两个文件改下端口即可 这样基本就能发了&#xff0c;但是还要改下 改成api 然后还要修改request.js 这里改成我们返回的状态码 我讲一个东西很容易就懂了&…

uniapp实现为微信小程序扫一扫的功能

引言 随着微信小程序的快速发展,越来越多的开发者开始关注和学习微信小程序的开发。其中,微信小程序的扫一扫功能是非常常用且实用的功能之一。通过扫描二维码,用户可以获取到相关的信息或者实现特定的功能。 正文 在过去,开发者需要使用微信开发者工具以及相关的开发文档…

UE(虚幻)学习(四) 第一个C++类来控制小球移动来理解蓝图和脚本如何工作

UE5视频看了不少&#xff0c;但基本都是蓝图如何搞&#xff0c;或者改一下属性&#xff0c;理解UE系统现有组件使用的。一直对C脚本和蓝图之间的关系不是很理解&#xff0c;看到一个视频讲的很好&#xff0c;我也做笔记记录一下。 我的环境是UE5.3.2. 创建UE空项目 我们创建…

【Redis】Redis 安装与启动

在实际工作中&#xff0c;大多数企业选择基于 Linux 服务器来部署项目。本文演示如何使用 MobaXterm 远程连接工具&#xff0c;在 CentOS 7 上安装和启动 Redis 服务&#xff08;三种启动方式&#xff0c;包括默认启动、指定配置启动和开机自启&#xff09;。在安装之前&#x…

SpringCloudAlibaba实战入门之路由网关Gateway初体验(十一)

Spring Cloud 原先整合 Zuul 作为网关组件,Zuul 由 Netflix 公司提供的,现在已经不维护了。后面 Netflix 公司又出来了一个 Zuul2.0 网关,但由于一直没有发布稳定版本,所以 Spring Cloud 等不及了就自己推出一个网关,已经不打算整合 zuul2.0 了。 一、什么是网关 1、顾明…

【unity c#】深入理解string,以及不同方式构造类与反射的性能测试(基于BenchmarkDotNet)

出这篇文章的主要一个原因就是ai回答的性能差异和实际测试完全不同&#xff0c;比如说是先获取构造函数再构造比Activator.CreateInstance(type)快&#xff0c;实际却相反 对测试结果的评价基于5.0&#xff0c;因为找不到unity6确切使用的net版本&#xff0c;根据c#9推测是net5…

使用RKNN进行YOLOv8人体姿态估计的实战教程:yolov8-pose.onnx转yolov8-pose.rknn+推理全流程

之前文章有提到“YOLOv8的原生模型包含了后处理步骤,其中一些形状超出了RK3588的矩阵计算限制,因此需要对输出层进行一些裁剪”,通过裁剪后得到的onnx能够顺利的进行rknn转换,本文将对转rnkk过程,以及相应的后处理进行阐述。并在文末附上全部源码、数据、模型的百度云盘链…

C# OpenCV机器视觉:凸包检测

在一个看似平常却又暗藏玄机的午后&#xff0c;阿强正悠闲地坐在实验室里&#xff0c;翘着二郎腿&#xff0c;哼着小曲儿&#xff0c;美滋滋地品尝着手中那杯热气腾腾的咖啡&#xff0c;仿佛整个世界都与他无关。突然&#xff0c;实验室的门 “砰” 的一声被撞开&#xff0c;小…

【JavaEE进阶】@RequestMapping注解

目录 &#x1f4d5;前言 &#x1f334;项目准备 &#x1f332;建立连接 &#x1f6a9;RequestMapping注解 &#x1f6a9;RequestMapping 注解介绍 &#x1f384;RequestMapping是GET还是POST请求&#xff1f; &#x1f6a9;通过Fiddler查看 &#x1f6a9;Postman查看 …

Python 自动化 打开网站 填表登陆 例子

图样 简价&#xff1a; 简要说明这个程序的功能&#xff1a; 1. **基本功能**&#xff1a; - 自动打开网站 - 自动填写登录信息&#xff08;号、公司名称、密码&#xff09; - 显示半透明状态窗口实时提示操作进度 2. **操作流程**&#xff1a; - 打开网站后自动…

oracle怎样使用logmnr恢复误删除的数据

如果有同事误删除数据了&#xff0c;可以用logmnr挖掘归档日志&#xff0c;生成回滚sql&#xff0c;快速恢复数据&#xff0c;比用整个库的备份恢复要快得多。 一 操作步骤 1.1 创建目录 su - oracle mkdir logmnr create directory logmnr_dir as /home/oracle/logmnr; …

linux自动化一键批量检查主机端口

1、准备 我们可以使用下面命令关闭一个端口 sudo iptables -A INPUT -p tcp --dport 端口号 -j DROP我关闭的是22端口&#xff0c;各位可以关其它的或者打开其它端口测试&#xff0c;谨慎关闭22端口&#xff01;不然就会像我下面一样握手超时&#x1f62d;&#x1f62d;&…