C++ 基础入门

第一章 C++ 介绍

一、为什么要学习 C++

二、C++ 为什么难学

  • C++ 支持的编程范式(paradigm)
    • 过程式(procedual)
    • 数据抽象(data abstraction)
    • 基于对象(object-based)
    • 面向对象式(object-oriented)
    • 函数式(functional)
    • 泛型形式
    • 模板元形式
  • 值语义雨对象语义
    • 值语义可以拷贝与赋值、对象语义不可以进行拷贝与赋值
  • function/bind的救赎(上)、这篇文章对编程范式进行一些探讨

三、C++ 11值得学习的新特性

  • 只能指针如 shared_ptr、weak_ptr等
  • rvalue reference;
  • function/bind
  • lambda expression and closure

四、开发工具选择

  • Visual Studio

第二章 C++ 初识

一、第一个 C++ 程序

编写一个 C++ 程序总共分为 4 个步骤

  • 创建项目
  • 创建文件
  • 编写代码
  • 运行程序

1、创建项目

Visual Studio 使我们用来编写 C++ 程序的主要工具,我们先将它打开

2、创建文件

  • 鼠标右键源文件

  • 添加

  • 新建项

  • 编写代码

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	// 输出 Hello World
    	cout << "Hello World" << endl;
    	system("pause");
    	return 0;
    }
    
  • 执行代码

二、注释

作用:在代码中添加一些说明和解释,方便自己或其他程序员阅读代码

两种格式:

  • 单行注释:// 描述信息
    • 通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明
  • 多行注释:/* 描述信息 */
    • 通常放在一段代码的上方,对该段代码做整体说明

提示:编译器在编译代码时会忽略注释的内容

#include <iostream>
using namespace std;

/*
	main 是一个程序的入口,
	每个程序都必须有这个一个函数
	有且只有一个
*/
int main()
{
	// 输出 Hello World
	cout << "Hello World" << endl;
	system("pause");
	return 0;
}

三、变量

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

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// 变量的定义
	// 语法:数据类型 变量名 = 初始值;
	int num = 10;

	cout << "num = " << num << endl;
	system("pause");
	return 0;
}

四、常量

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

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

  • #define 宏常量:#define 常量名 常量值
    • 通常在文件上方定义,标识一个常量
  • const 修饰的变量 const 数据类型 常量名 = 变量值
    • 通常在变量定义前加关键字 const,修饰该变量为常量,不可修改

示例:

#include <iostream>
using namespace std;

// 定义一个宏常量
#define DAY 7


int main()
{
	// day = 8; 报错,宏常量不可修改
	cout << "一周里总共有 " << DAY << " 天" << endl;

	// const 修饰变量
	const int month = 12;
	// month = 24; 报错,const修饰的变量也成为常量
	cout << "一年里总共有 " << month << " 个月" << endl;

	system("pause");
	return 0;
}

五、关键字

作用:关键字是 C++ 中预先表刘的单词(标识符)

  • 在定义变量或常量的时候,不要使用关键字
asm else new this
auto enum operator throw
bool explicit private true
break export protected try
case extern public typedef
catch false register typeid
char float reinterpret_cast typename
class for return union
const friend short unsigned
const_cast goto signed using
continue if sizeof virtual
default inline static void
delete int static_cast volatile
do long struct wchar_t
double mutable switch while
dynamic_cast namespace template

示例:

#include <iostream>
using namespace std;

int main()
{
	// int int = 10; int 是关键字,不可以作为变量的名称

	system("pause");
	return 0;
}

六、标识符命名规则

作用:C++ 规定给标识符(变量,常量)命名时,有一套自己的规则

  • 标识符不能是关键字
  • 标识符只能由字母、数字。下划线组成
  • 第一个字符必须为字母或下划线
  • 标识符中字母区分大小写

建议:给标识符命名时,争取做到建明制衣的效果,方便自己和他人的阅读

示例:

#include <iostream>
using namespace std;

/*
	标识符命名规则
	1、标识符不可以是关键字
	2、标识符是由字母、数字、下划线构成
	3、标识符第一个字符必须为字母或下划线
	4、标识符中字母区分大小写
*/

int main()
{
	// 1、标识符不可以是关键字 
	// int int = 10;

	// 2、标识符是由字母、数字、下划线构成
	int abc = 10;
	int _abc = 20;
	int _123abc = 30;

	// 3、标识符第一个字符必须为字母或下划线
	// int 123_abc = 40;

	// 4、标识符中字母区分大小写
	int aaa = 100;
	cout << aaa << endl;
	// cout << AAA << endl;

	system("pause");
	return 0;
}

第三章 数据类型

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

一、整型

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

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

数据类型 占用空间 取值范围
short(短整型) 2字节 (-2^15 ~ 2^15 - 1)
int(整型) 4字节 (-2^31 ~ 2^31 - 1)
long(长整型) Windows为4字节,Linux为4字节(32位),8字节(64位) (-2^31 ~ 2^31 - 1)
long long(长长整型) 8字节 (-2^63 ~ 2^63 - 1)

示例:

#include <iostream>
using namespace std;

int main()
{
	// 1、短整型 (-32768 ~ 32767)
	short num1 = 32768;

	// 2、 整型 (-2,147,483,648 ~ 2,147,483,647)
	int num2 = 32768;

	// 3、长整型 (-2,147,483,648 ~ 2,147,483,647)
	long num3 = 10;

	// 4、长长整型 (-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)
	long long num4 = 10;

	cout << num1 << endl;
	cout << num2 << endl;
	cout << num3 << endl;
	cout << num4 << endl;

	system("pause");
	return 0;
}

二、sizeof 关键字

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

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// 1、短整型 (-32768 ~ 32767)
	short num1 = 32768;

	// 2、 整型 (-2,147,483,648 ~ 2,147,483,647)
	int num2 = 32768;

	// 3、长整型 (-2,147,483,648 ~ 2,147,483,647)
	long num3 = 10;

	// 4、长长整型 (-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)
	long long num4 = 10;

	cout << "short 类型所占内训空间为: " << sizeof(short) << endl;
	cout << "int 类型所占内训空间为: " << sizeof(int) << endl;
	cout << "long 类型所占内训空间为: " << sizeof(long) << endl;
	cout << "long long 类型所占内训空间为: " << sizeof(long long) << endl;

	cout << "num1 所占内训空间为: " << sizeof(num1) << endl;
	cout << "num2 所占内训空间为: " << sizeof(num2) << endl;
	cout << "num3 所占内训空间为: " << sizeof(num3) << endl;
	cout << "num4 所占内训空间为: " << sizeof(num4) << endl;

	system("pause");
	return 0;
}

结论:short < int <= long < long long

三、实型(浮点型)

作用:用于表示小数

浮点型变量分为两种:

  • 单精度 float
  • 双精度 double

两者的区别在于表示的有效数字范围不同

数据类型 占用空间 有效数字范围
float 4字节 7位有效数字
double 8字节 15~16位有效数字

示例:

#include <iostream>
using namespace std;

int main()
{
	// 1、单精度 float
	float f1 = 3.1415926f;

	// 2、双精度 double
	double d1 = 3.1415927;

	// 默认情况下输出一个小数,会显示出6位有效数字
	cout << "f1 = " << f1 << "; floatSize = " << sizeof(float) << endl;
	cout << "d1 = " << d1 << "; doubleSize = " << sizeof(double) << endl;

	// 3、科学计数法
	float f2 = 3e2; // 3 * 10 ^ 2
	cout << "f2 = " << f2 << endl;

	float f3 = 3e-2; // 3 * 0.1 ^ 2
	cout << "f3 = " << f3 << endl;
	
	system("pause");
	return 0;
}

四、字符型

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

语法:char ch = '1'

注意:在显示字符变量时用单引号括起来,不要用双引号,单引号内只能有一个字符,不可以是字符串

  • C 和 C++ 中字符型变量只占用 1个字节
  • 字符型变量并不是把字符本身放到内存中存储,而是将对应的 ASCII 编码放到存储单元

示例:

#include <iostream>
using namespace std;

int main()
{
	// 1、字符型 char
	char ch = 'a';
	cout << "ch = " << ch << "; charSize = " << sizeof(char) << endl;

	// 2、 字符型变量对应 ASCII 编码
	cout << "ch = " << ch << "; charASCII = " << int(ch) << endl;

	system("pause");
	return 0;
}

五、转义字符

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

现阶段我们常用的转义字符有:\n \\ \t

转义字符 含义 ASCII码值(十进制)
\a 响铃符(报警) 007
\b 退格符,将光标位置移到下一页开头 008
\f 进纸符,将光标位置移到下一页开头 012
\n 换行符,将光标位置移到下一行开头 010
\r 回车符,将光标位置移到本行开头 013
\t 水平制表符,光标跳到下一个Tab位置 009
\v 垂直制表符 011
\\ 单反斜杠 092
\' 单引号 039
\" 双引号 034
? 问号 063
\0 空字符 000
\ooo 用1~3位八进制数 ooo 为码值所对应的字符 ooo(八进制)
\xhh 用1、2位十六进制 hh 为码符所对应的字符 hh(十六进制)

示例:

#include <iostream>
using namespace std;

int main()
{
	// 转义字符
	// 换行符 \n

	cout << "Hello World" << endl;
	cout << "Hello World\n";

	// 反斜杠 \\

	cout << "\\" << endl;

	// 水平制表符 \t
	cout << "C\tHello World" << endl;
	cout << "C++\tHello World" << endl;
	cout << "Java\tHello World" << endl;
	cout << "Python\tHello World" << endl;

	system("pause");
	return 0;
}

六、字符串型

作用:用于表示一串字符

两种风格:

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

    • 示例:

      #include <iostream>
      using namespace std;
      
      int main()
      {
      	// 字符串型
      	char str1[] = "Hello World";
      	cout << str1 << endl;
      
      	system("pause");
      	return 0;
      }
      

    注意:C风格字符串, 需要用 双引号 括起来

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

    • 示例:

      #include <iostream>
      #include <string> // 版本高的可以不用
      using namespace std;
      
      int main()
      {
      	// 字符串型
      	string str = "Hello World";
      	cout << str << endl;
      
      	system("pause");
      	return 0;
      }
      

    注意:C++ 风格字符串, 需要加入头文件 #include <string> // 版本高的可以不用

七、布尔类型

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

bool 类型只有两个值:

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

bool 类型占 1个字节 大小

示例:

#include <iostream>
using namespace std;

int main()
{
	// 布尔类型
	bool status = true;
	cout << status << endl;

	// 重新赋值
	status = false;
	cout << status << endl;

	// 查看占用内存空间
	cout << "size of bool = " << sizeof(bool) << endl;

	system("pause");
	return 0;
}

八、数据的输入

作用:用于键盘获取数据

关键字:cin

语法:cin >> 变量;

示例:

#include <iostream>
using namespace std;

int main()
{
	// 数据的输入
	// 整型输入
	int a = 0;
	cout << "请输入整型变量:" << endl;
	cin >> a;
	cout << a << endl;

	// 浮点型输入
	double d = 3.14;
	cout << "请输入浮点型变量:" << endl;
	cin >> d;
	cout << d << endl;

	// 字符型输入
	char c = 'a';
	cout << "请输入字符型变量:" << endl;
	cin >> c;
	cout << c << endl;

	// 字符串型输入
	string s = "";
	cout << "请输入字符串型变量:" << endl;
	cin >> s;
	cout << s << endl;

	// 布尔型输入
	bool b = true;
	cout << "请输入布尔型变量:" << endl;
	cin >> b;
	cout << b << endl;

	system("pause");
	return 0;
}

第四章 运算符

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

本章我们主要讲解以下几类运算符

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

一、算数运算符

作用:用于处理四则运算

算数运算符包括以下符号:

运算符 术语 示例 结果
+ 正号 +3 3
- 负号 -3 -3
+ 10 + 5 15
- 10 - 5 5
* 10 * 5 50
/ 10 / 5 2
% 取模(取余) 10 % 3 1
++ 前置递增 a = 2; b = ++a; a = 3; b = 3;
++ 后置递增 a = 2; b = a++; a = 3; b = 2;
-- 前置递减 a = 2; b = --a; a = 1; b = 1;
-- 后置递减 a = 2; b = a--; a = 1; b = 2;

示例:

#include <iostream>
using namespace std;

int main()
{
	// 算数运算符
	int a1 = 10;
	int b1 = 3;
	// 加法运算
	cout << a1 << " + " << b1 << " = " << a1 + b1 << endl;
	// 减法运算
	cout << a1 << " - " << b1 << " = " << a1 - b1 << endl;
	// 乘法运算
	cout << a1 << " × " << b1 << " = " << a1 * b1 << endl;
	// 除法运算(两个整数相除,结果依然是整数,将小数部分去除)
	cout << a1 << " ÷ " << b1 << " = " << a1 / b1 << endl;
	// 取余运算
	cout << a1 << " % " << b1 << " = " << a1 % b1 << endl;
	
	// 递增运算 - 前置递增(先让变量 +1 然后进行表达式运算)
	int a = 10;
	++a;
	cout << "++a = " << a << endl;

	// 递增运算 - 后置递增(先让表达式运算 后让变量 +1)
	int b = 10;
	b++;
	cout << "b++ = " << b << endl;

	// 前置和后置的区别
	int a2 = 10;
	int b2 = ++a2 * 10;
	cout<< "a2 = " << a2 << "; b2 = " << b2 << endl;

	int a3 = 10;
	int b3 = a3++ * 10;
	cout << "a3 = " << a3 << "; b3 = " << b3 << endl;

	system("pause");
	return 0;
}

二、赋值运算符

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

赋值运算符包括以下几个符号

运算符 术语 示例 结果
= 赋值 a = 2; b = 3; a = 2; b = 3;
+= 加等于 a = 0; a += 2; a = 2;
-= 减等于 a = 5; a -= 3; a = 2;
*= 乘等于 a = 2; a *= 2; a = 4;
/= 除等于 a = 4; a /= 2; a = 2;
%= 模等于 a = 3; a %= 2; a = 1;

示例:

#include <iostream>
using namespace std;

int main()
{
	// 赋值运算符
	// =
	int a = 10;
	a = 100;
	cout << "a = " << a << endl;

	// +=
	a = 10;
	a += 2; // a = a + 2
	cout << "a = " << a << endl;

	// -=
	a = 10;
	a -= 2; // a = a + 2
	cout << "a = " << a << endl;

	// *=
	a = 10;
	a *= 2; // a = a * 2
	cout << "a = " << a << endl;
	
	// /=
	a = 10;
	a /= 2; // a = a / 2
	cout << "a = " << a << endl;
	
	// %=
	a = 10;
	a %= 3; // a = a % 3
	cout << "a = " << a << endl;

	system("pause");
	return 0;
}

三、比较运算符

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

比较运算符有以下符号:

运算符 术语 示例 结果
== 等于 4 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0
> 大于 4 > 3 1
<= 小于等于 4 <= 3 0
>= 大于等于 4 >= 3 1

示例:

#include <iostream>
using namespace std;

int main()
{
	// 比较运算符
	int a = 10;
	int b = 20;
	// ==
	cout << a << " == " << b << " = " << (a == b) << endl;
	// !=
	cout << a << " != " << b << " = " << (a != b) << endl;
	// <
	cout << a << " < " << b << " = " << (a < b) << endl;
	// >
	cout << a << " < " << b << " = " << (a < b) << endl;
	// <=
	cout << a << " <= " << b << " = " << (a <= b) << endl;
	// >=
	cout << a << " >= " << b << " = " << (a >= b) << endl;

	system("pause");
	return 0;
}

四、逻辑运算符

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

逻辑运算符有以下符号:

运算符 术语 示例 结果
! !a 如果 a 为假,则 !a 为真;反之 !a 为假
&& a && b 如果 a 和 b 都为真,则结果为真;反之为假
|| a || b 如果 a 或 b 为真,则结果为真;反之为假

示例:

#include <iostream>
using namespace std;

int main()
{
	// 逻辑运算符
	// 非 真变假,假变真
	int a = 10;
	cout << "\n 非运算:" << endl;
	cout << " !a = " << !a << endl;
	cout << " !!a = " << !!a << endl;
	
	// 与
	cout << "\n 与运算:" << endl;
	int a1 = 10;
	int b1 = 10;
	cout << a1 << " && " << b1 << " = " << (a1 && b1) << endl;
	a1 = 0;
	cout << a1 << " && " << b1 << " = " << (a1 && b1) << endl;
	b1 = 0;
	cout << a1 << " && " << b1 << " = " << (a1 && b1) << endl;

	// 或
	cout << "\n 或运算:" << endl;
	int a2 = 10;
	int b2 = 10;
	cout << a2 << " || " << b2 << " = " << (a2 || b2) << endl;
	a2 = 0;
	cout << a2 << " || " << b2 << " = " << (a2 || b2) << endl;
	b2 = 0;
	cout << a2 << " || " << b2 << " = " << (a2 || b2) << endl;
	system("pause");
	return 0;
}

第五章 程序流程解构

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

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

一、选择结构

1、if 语句

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

if 语句的三种形式:

  • 单行格式 if 语句
  • 多行格式 if 语句
  • 多条件的 if 语句

(1) 单行格式 if 语句

语法:

if (条件) 
{
    // 条件满足执行的语句
}

示例:

#include <iostream>
using namespace std;

int main()
{
	// 选择结构 单行格式 if 语句
	// 输入一个分数,如果分数大于 600 分 视为开上一本大学,并在屏幕上打印
	int score = 0;
	cout << "请输入考生分数:" << endl;
	cin >> score;
	cout << "该考生分数:" << score << endl;
    // if 条件后边不要写分号 if (score > 600);
	if (score > 600)
	{
		cout << "恭喜您考上了一本大学!!!" << endl;
	}
	
	system("pause");
	return 0;
}

(2) 多行格式 if 语句

语法:

if (条件) 
{
    // 执行满足条件的代码块
}
else
{
    // 执行不满足条件的代码块
}

示例:

#include <iostream>
using namespace std;

int main()
{
	// 选择结构 多行格式 if 语句
	/* 输入一个分数
    	大于 600 - 恭喜您考上了一本大学!!!
    	小于 600 - 很遗憾您没有考上一本大学!!!
    */
	int score = 0;
	cout << "请输入考生分数:" << endl;
	cin >> score;
	cout << "该考生分数:" << score << endl;
	if (score > 600) 
	{
		cout << "恭喜您考上了一本大学!!!" << endl;
	}
	else
	{
		cout << "很遗憾您没有考上一本大学!!!" << endl;
	}
	system("pause");
	return 0;
}

(3) 多条件的 if 语句

语法:

if (条件1)
{
    // 满足 条件1 执行的代码块
}
else if (条件2)
{
    // 满足 条件2 执行的代码块
}
...
else
{
    // 以上条件都不满足执行的代码块
}

示例:

#include <iostream>
using namespace std;

int main()
{
	// 选择结构 多条件的 if 语句
	/* 
		输入一个分数
		大于 600 - 一本
		大于 500 - 二本
		大于 400 - 三本
		小于 400 - 回去喂猪
	*/
	int score = 0;
	cout << "请输入考生分数:" << endl;
	cin >> score;
	cout << "该考生分数:" << score << endl;
	if (score > 600) 
	{
		cout << "恭喜您考上了一本大学!!!" << endl;
	}
	else if (score > 500)
	{
		cout << "恭喜您考上了二本大学!!!" << endl;
	}
	else if (score > 400)
	{
		cout << "恭喜您考上了三本大学!!!" << endl;
	}
	else
	{
		cout << "恭喜您可以回去喂猪了!!!" << endl;
	}
	system("pause");
	return 0;
}

(4) 嵌套 if 语句

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

案例需求:

  • 提示用户输入一个高考分数,根据分数做出如下判断
  • 分数如果大于 600 分视为考上一本,大于 500 分考上二本,大于 400 分考上三本,其余视为未考上本科
  • 在一本分数中,如果大于 700 分,考入北大, 大于 650 分,考入清华,大于 600 分,考入西安电子科技大学

示例:

#include <iostream>
using namespace std;

int main()
{
	int score = 0;
	cout << "请输入考生分数:" << endl;
	cin >> score;
	cout << "该考生分数:" << score << endl;
	if (score > 600) 
	{
		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;
}

(5) 课后练习

三只小猪称体重

有三只小猪 ABC,分别输入三只小猪的体重,并且判断哪只小猪最重

案例:

#include <iostream>
using namespace std;

int main()
{
	// 创建三只小猪的体重变量
	int pig1 = 0;
	int pig2 = 0;
	int pig3 = 0;
	// 输入三只小猪的重量
	cout << "请输入小猪A的体重:" << endl;
	cin >> pig1;
	cout << "请输入小猪B的体重:" << endl;
	cin >> pig2;
	cout << "请输入小猪C的体重:" << endl;
	cin >> pig3;
	// 打印小猪的重量
	cout << "小猪A的体重为:" << pig1 << endl;
	cout << "小猪B的体重为:" << pig2 << endl;
	cout << "小猪C的体重为:" << pig3 << endl;
	if (pig1 > pig2) // A > B
	{
		if (pig1 > pig3) // A > C
		{
			cout << "小猪A是最重的!!!" << endl;
		}
		else // A < C
		{
			cout << "小猪C是最重的!!!" << endl;
		}
	}
	else // A < B
	{
		if (pig2 > pig3) // B > C
		{
			cout << "小猪B是最重的!!!" << endl;
		}
		else // B < C
		{
			cout << "小猪C是最重的!!!" << endl;
		}
	}
	system("pause");
	return 0;
}

2、三目运算符

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

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

解释:

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

示例:

#include <iostream>
using namespace std;

int main()
{
	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;

	system("pause");
	return 0;
}

3、switch 语句

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

语法:

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// switch 给电影打分
	// 10 ~ 9 经典
	// 8 ~ 7 非常好
	// 6 ~ 5 一般
	// 5 以下 垃圾
	// 1. 提示用户给电影评分
	cout << "请给《上海堡垒》这部电影打分:" << endl;
	// 用户开始进行打分
	int score = 0;
	cin >> score;
	cout << "您给《上海堡垒》这部电影打的分数为:" << score << endl;
	switch (score)
	{
	case 10:
	case 9:
		cout << "您认为《上海堡垒》这部电影是经典电影" << endl;
		break;
	case 8:
	case 7:
		cout << "您认为《上海堡垒》这部电影非常好" << endl;
		break;
	case 6:
	case 5:
		cout << "您认为《上海堡垒》这部电影一般" << endl;
		break;
	default:
		cout << "您认为《上海堡垒》这部电影是一部烂片" << endl;
		break;
	}


	system("pause");
	return 0;
}

switch 缺点:判断的时候只能是整型或者字符型,不可以是一个区间

switch 优点:结构清晰,执行效率高

二、循环结构

1、while 循环语句

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

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

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// while 循环语句
	// 在屏幕中打印 0 ~ 9 这是个数
	int num = 0;
	while (num <= 9)
	{
		cout << num << endl;
		num++;
	}

	system("pause");
	return 0;
}

课后练习:
案例描述:系统随机生成 1 ~ 100 之间的数字,玩家猜测,如果猜错,提示玩家数字过大或过小,如果猜对恭喜玩家胜利,并且退出游戏

#include <iostream>
// #include <ctime> 老版本需要导入
using namespace std;

int main()
{
	// 添加随机数种子 作用利用当前系统时间生成随机数,防止每次随机数都一样
	srand((unsigned int)time(NULL));

	// 1、系统生成随机数
	int num = rand() % 100 + 1; // rand()%100 + 1 生成 0 + 1 ~ 99 + 1 随机数
	cout << "随机生成的数字为: " << num << endl;
	// 2、玩家进行猜测
	int input_num = 0;
	while (true)
	{
		cout << "请输入您猜测的数字: ";
		cin >> input_num;
		// 3、判断玩家的猜测
		// 猜对 退出游戏
		// 猜错 提示猜的结果 过大或者过小 重新返回第2步
		if (input_num == num)
		{
			cout << "恭喜您猜对了!!!" << endl;
			break;
		} 
		else if (input_num > num)
		{
			cout << "您输入的数字太大了!!!" << endl;
		}
		else {
			cout << "您输入的数字太小了!!!" << endl;
		}
	}
	
	system("pause");
	return 0;
}

2、do...while 循环语句

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

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

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// do...while 循环语句
	int num = 0;
	do
	{
		cout << num << endl;
		num++;
	} 
	while (num < 10);
	
	system("pause");
	return 0;
}

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

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

请利用 do...while 语句,求出三位数中的水仙花数

#include <iostream>
using namespace std;

int main()
{
	// 请利用 do...while 语句,求出三位数中的水仙花数
	int num = 100;
	do
	{	
        // 获取个位数
		int ones = num % 10;
        // 获取十位数
		int tens = (num / 10) % 10;
        // 获取百位数
		int hundreds = num / 100;
        // 判断是否是水仙花数
		if (hundreds * hundreds * hundreds + tens * tens * tens + ones * ones * ones == num)
		{
			cout << num << " 是一个水仙花数!!!" << endl;
		}
		num++;
	} 
	while (num < 1000);
	
	system("pause");
	return 0;
}

3、for 循环语句

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

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// for 循环语句 输出 0 ~ 9
	for (int i = 0; i < 10; i++)
	{
		cout << i << endl;
	}
	
	system("pause");
	return 0;
}

注意:for循环中的表达式,要用分号进行分隔

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

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

#include <iostream>
using namespace std;

int main()
{
	// 从1开始数到数字 100,如果数字个位含有7,或者十位数字含有 7,或者该数字是 7 的倍数,我们打印敲桌子,其余数字直接打印输出
	for (int i = 1; i < 100; i++)
	{
	
		if (i % 10 == 7 || i / 10 == 7 || i % 7 == 0) 
		{
			cout << "敲桌子!!!" << endl;
		}
		else
		{
			cout << i << endl;
		}
	}
	system("pause");
	return 0;
}

4、嵌套循环

作用:在循环体重在嵌套一层循环,解决一些实际问题

示例:

#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;
}

课后练习

案例描述:九九乘法表

#include <iostream>
using namespace std;

int main()
{
	// 九九乘法表
	for (int i = 1; i < 10; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			cout << j << " × " << i << " = " << j * i << "; ";
		}
		cout << endl;
	}
	system("pause");
	return 0;
}

三、循环控制语句

1、break 语句

作用:用于跳出 选择结构 或者 循环结构

break 使用的时机:

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

示例1:

#include <iostream>
using namespace std;

int main()
{
	// 在 switch 语句中使用 break
	cout << "请选择您挑战的副本难度:\n 1、普通 \n 2、中等 \n 3、困难" << endl;
	int select = 0;
	cin >> select;
	switch (select)
	{
	case 1:
		cout << "您挑战的副本难度为: 普通" << endl;
		break;
	case 2:
		cout << "您挑战的副本难度为: 中等" << endl;
		break;
	default:
		cout << "您挑战的副本难度为: 困难" << endl;
		break;
	}

	system("pause");
	return 0;
}

示例2:

#include <iostream>
using namespace std;

int main()
{
	for (int i = 0; i < 10; i++)
	{
		if (i == 5)
		{
			break;
		}
		cout << i << endl;
	}
	system("pause");
	return 0;
}

示例3:

#include <iostream>
using namespace std;

int main()
{
	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;
}

示例4:

#include <iostream>
using namespace std;

int main()
{
	int num = 0;
	while (true)
	{
		if (num == 5)
		{
			break;
		}
		cout << num << endl;
		num++;
	}

	system("pause");
	return 0;
}

2、continue 语句

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

示例:

#include <iostream>
using namespace std;

int main()
{
	for (int i = 0; i < 100; i++)
	{
		if (i % 2 == 0)
		{
			continue;
		}
		cout << i << endl;
	}
	system("pause");
	return 0;
}

3、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;
	system("pause");
	return 0;
}

注意:在程序中不建议使用 goto 语句,一面造成程序混乱

第六章 数组

一、概述

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

特点:

  • 数组中的每个 数据元素都是相同的数据类型
  • 数组是由 连续的内存 位置组成的

二、一维数组

1、一维数组定义方式

一维数组定义的三种方式:

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// 定义方式1: 数据类型 数组名[数字长度];
	cout << "定义方式1: 数据类型 数组名[数字长度];" << endl;
	int scores[5];

	// 利用下标赋值
	scores[0] = 100;
	scores[1] = 90;
	scores[2] = 80;
	scores[3] = 70;
	scores[4] = 60;

	for (int i = 0; i < 5; i++)
	{
		cout << scores[i] << endl;
	}


	// 定义方式2:数据类型 数组名[数组长度] = { 值1, 值2, ... };
	cout << "\n定义方式2:数据类型 数组名[数组长度] = { 值1, 值2, ... };" << endl;
	// int ages[5] = { 10, 23, 31 };
	int ages[5] = { 10, 23, 31, 64, 18 };
	for (int i = 0; i < 5; i++)
	{
		cout << ages[i] << endl;
	}

	// 定义方式3:数据类型 数组名[] = { 值1, 值2, ... };
	cout << "\n定义方式3:数据类型 数组名[ ] = { 值1, 值2, ... };" << endl;
	string names[] = { "波多野结衣", "三上悠亚", "桥本有菜", "河北彩花", "苍井空", "小泽玛利亚" };
	for (int i = 0; i < 6; i++)
	{
		cout << names[i] << endl;
	}

	system("pause");
	return 0;
}

总结:

  • 数组名的命名规范与变量名命名规范一致,不要和变量重名
  • 数组中的下标从 0 开始索引

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;
	cout << "数组中第二个元素的首地址为: " << (int)&arr[1] << endl;

	// arr = 100; 数组名是常量,不可以进行赋值操作
    
	system("pause");
	return 0;
}

课后练习

案例一:五只小猪称体重

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


int main()
{
	// 定义一个最大值变量
	int max = 0;
	// 创建5只小猪体重的数组
	int arr[5] = { 300, 350, 200, 400, 250 };
	// 循环数组更新最大值
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (max < arr[i])
		{
			max = arr[i];
		}
		else
		{
			continue;
		}
	}

	cout << "最重的小猪体重为: " << max << endl;
	system("pause");
	return 0;
}

案例二:数组元素逆置

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

#include <iostream>
using namespace std;

int main()
{
	// 定义数组
	int arr[5] = { 1, 3, 2, 5, 4 };

	// 定义起始元素下标
	int start_index = 0;

	// 定义结尾元素下标
	int end_index = sizeof(arr) / sizeof(arr[0]) - 1;

	cout << "数组逆置前:[";
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (i == sizeof(arr) / sizeof(arr[0]) - 1)
		{
			cout << arr[i] << "]";
		}
		else
		{
			cout << arr[i] << ", ";
		}

	}
	cout << endl;

	// 数组逆置
	while (start_index < end_index)
	{
		// 定义一个临时变量
		int temp = arr[start_index];
		// 实现元素互换
		arr[start_index] = arr[end_index];
		arr[end_index] = temp;
		// 更新下标
		start_index++;
		end_index--;
	}

	// 打印逆置后的数组
	cout << "数组逆置后:[";
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (i == sizeof(arr) / sizeof(arr[0]) - 1)
		{
			cout << arr[i] << "]";
		}
		else
		{
			cout << arr[i] << ", ";
		}

	}
	cout << endl;

	system("pause");
	return 0;
}

3、排序算法

(1) 冒泡排序

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

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

示例:将数组 { 3,2,8,0,5,7,1,3,9 } 进行升序排序

#include <iostream>
using namespace std;

int main()
{
	// 将数组 { 3,2,8,0,5,7,1,3,9 } 进行升序排序
	int arr[9] = { 3,2,8,0,5,7,1,3,9 };
	int arr_length = sizeof(arr) / sizeof(arr[0]);
	
	cout << "数组排序前:[";
	for (int i = 0; i < arr_length; i++)
	{
		if (i == arr_length - 1)
		{
			cout << arr[i] << "]";
		}
		else
		{
			cout << arr[i] << ", ";
		}

	}
	cout << endl;

	// 数据排序
	for (int i = 0; i < arr_length; i++)
	{
		for (int j = 0; j < arr_length -1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}

	cout << "数组排序后:[";
	for (int i = 0; i < arr_length; i++)
	{
		if (i == arr_length - 1)
		{
			cout << arr[i] << "]";
		}
		else
		{
			cout << arr[i] << ", ";
		}

	}
	cout << endl;

	system("pause");
	return 0;
}

三、二维数组

二维数组就是 在一维数组上多加了一个纬度。

1、二维数组定义方式

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

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

建议:以上四种定义方式,利用 第二种更加直观,提高代码的可读性

示例:

#include <iostream>
using namespace std;

int main()
{
	// 二维数组的定义方式
	/*
		1. 数据类型 数组名[行数][列数];
		2. 数据类型 数组名[行数][列数] = {{数据1, 数据2}, {数据3, 数据4}};
		3. 数据类型 数组名[行数][列数] = {数据1, 数据2, 数据3, 数据4};
		4. 数据类型 数组名[][列数] = { 数据1, 数据2, 数据3, 数据4 };
	*/

	// 方式1:数据类型 数组名[行数][列数];
	int arr1[2][3];
	arr1[0][0] = 1;
	arr1[0][1] = 2;
	arr1[0][2] = 3;
	arr1[1][0] = 4;
	arr1[1][1] = 5;
	arr1[1][2] = 6;
	// cout << arr1[0][0] << endl;
	// cout << arr1[0][1] << endl;
	// cout << arr1[0][2] << endl;
	// cout << arr1[1][0] << endl;
	// cout << arr1[1][1] << endl;
	// cout << arr1[1][2] << endl;

	// 外层循环打印行数,内层循环打印列数
	for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
	{
		for (int j = 0; j < sizeof(arr1[0]) / sizeof(arr1[0][0]); j++)
		{
			cout << arr1[i][j] << endl;
		}
	}
	cout << endl;

	// 方式2:数据类型 数组名[行数][列数] = {{数据1, 数据2}, {数据3, 数据4}};
	int arr2[2][3] = {
		{1,2,3},
		{4,5,6}
	};
	// 外层循环打印行数,内层循环打印列数
	for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++)
	{
		for (int j = 0; j < sizeof(arr2[0]) / sizeof(arr2[0][0]); j++)
		{
			cout << arr2[i][j] << endl;
		}
	}
	cout << endl;


	// 方式3:数据类型 数组名[行数][列数] = { 数据1, 数据2, 数据3, 数据4 };
	int arr3[2][3] = { 1,2,3,4,5,6 };
	// 外层循环打印行数,内层循环打印列数
	for (int i = 0; i < sizeof(arr3) / sizeof(arr3[0]); i++)
	{
		for (int j = 0; j < sizeof(arr3[0]) / sizeof(arr3[0][0]); j++)
		{
			cout << arr3[i][j] << endl;
		}
	}
	cout << endl;

	// 方式4:数据类型 数组名[][列数] = { 数据1, 数据2, 数据3, 数据4 };
	int arr4[][3] = { 1,2,3,4,5,6 };
	// 外层循环打印行数,内层循环打印列数
	for (int i = 0; i < sizeof(arr4) / sizeof(arr4[0]); i++)
	{
		for (int j = 0; j < sizeof(arr4[0]) / sizeof(arr4[0][0]); j++)
		{
			cout << arr4[i][j] << endl;
		}
	}

	system("pause");
	return 0;
}

2、二维数组数组名

  • 查看二维数组所占内存空间
  • 获取二维数组首地址

示例:

#include <iostream>
using namespace std;

int main()
{
	// 二维数组数组名
	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;

	// 查看二维数组的首地址
	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;
	system("pause");
	return 0;
}

课后练习:

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

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

示例:

#include <iostream>
using namespace std;

int main()
{
	string names[3] = { "张三" , "李四", "王五" };
	int scores[3][3] = {
		{100,100,100},
		{90,50,100},
		{60,70,80}
	};
	for (int i = 0; i < sizeof(scores) / sizeof(scores[0]); i++)
	{
		int total_score = 0;
		for (int j = 0; j < sizeof(scores[0]) / sizeof(scores[0][0]); j++)
		{
			total_score += scores[i][j];
		}
		cout << "学生: " << names[i] << " 成绩总分为:" << total_score << endl;
	}
	system("pause");
	return 0;
}

第七章 函数

一、概述

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

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

二、函数的定义

函数的定义一般主要有 5个 步骤‘

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

语法:

返回值类型 函数名 (参数列表)
{
    /*
    	函数体语句
    	...
    */
    return 表达式;
}

示例:

#include <iostream>
using namespace std;

// 实现一个加法函数,功能是,传入两个整数数据,计算数据相加的结果,并返回
int add(int num1, int num2)
{
	int sum = num1 + num2;
	return sum;
}

三、函数的调用

功能:使用定义好的函数

语法:函数名(参数)

示例:

#include <iostream>
using namespace std;


// 实现一个加法函数,功能是,传入两个整数数据,计算数据相加的结果,并返回
// num1, num2 称为形式参数,简称形参
int add(int num1, int num2)
{
	int sum = num1 + num2;
	return sum;
}

int main()
{
    // 定义两个 int类型的变量,变量名随便
    int num1 = 10;
    int num2 = 20;
    // 调用 add 函数 调用时的 num1, num2 称为实际参数,简称实参,调用函数时,实参的值会传递给形参
    int sum = add(num1, num2);
	cout << sum << endl;

	system("pause");
	return 0;
}

总结:函数定义力小括号内称为形参,函数调用时传入的参数称为实参

四、值传递

  • 所谓值传递,就是函数调用时实参将值传入给形参
  • 值传递时,如果形参发生变化,并不会影响实参

示例:

#include <iostream>
using namespace std;

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; 返回值不需要的时候,可以不写
}

int main()
{
	//调用函数
	int num1 = 10;
	int num2 = 20;
	swap(num1, num1);

	cout << "实参:" << endl;
	cout << "num1 = " << num1 << endl;
	cout << "num2 = " << num2 << endl;

	system("pause");
	return 0;
}

五、函数的常见样式

常见的函数样式有四种

  1. 无参无返
  2. 有参无返
  3. 无参有返
  4. 有参有返

示例:

#include <iostream>
using namespace std;


// 函数常见样式
// 1.无参无返
void func01()
{
	// void a = 10; // 无类型不可以创建变量,原因:无法分配内存
	cout << "this is func01" << endl;
	// funt01(); 函数调用
}

// 2.有参无返
void func02(int a)
{
	cout << "this is func02 参数a = " << a << endl;
	// funt02(100); 函数调用
}

// 3.无参有返
int func03()
{
	cout << "this is func03" << endl;
	return 100;
	// funt03(); 函数调用
}

// 4.有参有返
int func04(int a)
{
	cout << "this is func04 参数a = " << a << endl;
	return a + 100;
	// funt03(100); 函数调用
}

int main()
{
	// 无参无返调用函数
	func01();

	// 有参无返调用函数
	func02(100);

	// 无参有返调用函数
	cout << func03() << endl;

	// 有参有返调用函数
	cout << func04(100) << endl;

	system("pause");
	return 0;
}

六、函数的声明

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

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

示例:

#include <iostream>
using namespace std;


// 函数的生命
// 声明可以多次,定义只能一次
// 声明:
int max(int a, int b);
int max(int a, int b);
// 定义:
int max(int a, int b)
{
	return a > b ? a : b;
}

int main()
{
	cout << max(88, 66) << endl;
	cout << max(66, 88) << endl;

	system("pause");
	return 0;
}

总结:提前告诉编译器函数的存在,可以利用函数的生命

函数定义之后,函数的生命可以卸载调用函数之后

七、函数的分文件填写

作用:让带吗结构更加清晰

函数份文件编写一般有四个步骤

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

示例:

  • swap.h 文件

    #include <iostream>
    using namespace std;
    
    // 函数的声明
    void swap(int a, int b);
    
  • swap.cpp 文件

    #include "swap.h"
    
    // 函数的定义
    void swap(int a, int b)
    {
    	cout << "交换前:" << endl;
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    	int temp = a;
    	a = b;
    	b = temp;
    	cout << "交换后:" << endl;
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    }
    
  • main.cpp

    #include <iostream>
    using namespace std;
    
    #include "swap.h"
    
    int main()
    {
    	swap(88, 66);
    	swap(66, 88);
    
    	system("pause");
    	return 0;
    }
    

第八章 指针(重点)

一、指针的基本概念

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

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

二、指针变量的定义和使用

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

示例:

#include <iostream>
using namespace std;

int main()
{
	// 1、定义指针
	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;
	
	system("pause");
	return 0;
}

三、指针所占内存空间

提问:指针也是中数据类型,name这种数据类型占用多少内存空间?

示例:

#include <iostream>
using namespace std;

int main()
{
	int a = 10;
	// int* p;
	// p = &a; // 指针指向数据a的内存地址
    int* p = &a; // 等价上边的两行代码
	
    // 32位操作系统下,指针占用4个字节空间大小,64位操作系统下,指针占用8个字节空间大小(不管是什么数据类型)
	cout << "*p = " << *p << endl;	// * 解引用
	cout << "int 指针大小为:" << sizeof(p) << endl;
	cout << "char 指针大小为:" << sizeof(char *) << endl;
	cout << "float 指针大小为:" << sizeof(float *) << endl;
	cout << "double 指针大小为:" << sizeof(double *) << endl;

	system("pause");
	return 0;
}

四、空指针和野指针

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

用途:初始化指针变量

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

1、空指针

指针变量 p 指向 内存地址编号为 0 的空间

#include <iostream>
using namespace std;

int main()
{
	// 指针变量 p 指向 内存地址编号为 0 的空间
	int* p = NULL;

	// 访问空指针报错
	// 内存编号 0 ~ 255 为系统占用内存,不允许用户访问
	cout << *p << endl;

	system("pause");
	return 0;
}

2、野指针

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

#include <iostream>
using namespace std;

int main()
{
	// 指针变量 p 指向 内存地址编号为 0x1100 的空间
	int* p = (int *)0x1100;

	// 访问野指针报错
	cout << *p << endl;

	system("pause");
	return 0;
}

五、const 修饰指针

const 修饰指针的有三种情况:

  1. const 修饰指针 -- 常量指针
  2. const 修饰常量 -- 指针常量
  3. const 即修饰指针,又修饰常量

示例:

#include <iostream>
using namespace std;

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

	// 1、const 修饰的是指针,指针指向可以修改,指针指向的值不可以更改
	const int* p1 = &a;
	p1 = &b; // 修改指针指向
	// *p1 = 100; 报错
	cout << *p1 << endl;

	// 2、const 修饰的是常量,指针指向不可以修改,指针指向的值可以更改
	int* const p2 = &a;
	// p2 = &b; 报错
	*p2 = 100;
	cout << *p2 << endl;

	// 3、const 即修饰指针,又修饰常量, 指针和指针指向的值都不可以修改
	const int* const p3 = &a;
	// p3 = &b; 报错
	// *p3 = 100; 报错
	cout << *p3 << endl;

	system("pause");
	return 0;
}

六、指针和数组

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

示例:

#include <iostream>
using namespace std;

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int* p = arr; // 指向数组的指针
	cout << "第一个元素:" << arr[0] << endl;
	cout << "指针访问第一个元素:" << *p << endl;

	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		// 利用循环遍历指针数组
		cout << *p << endl;
		p++;
	}

	system("pause");
	return 0;
}

七、指针和函数

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

示例:

#include <iostream>
using namespace std;

// 值传递
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()
{
	int a = 10;
	int b = 20;
    // 值传递 不会改变实参 
	swap01(a, b);
	cout << "execute swap01 after a = " << a << endl;
	cout << "execute swap01 after b = " << b << endl;
	
    // 指针传递 会改变实参 
	swap02(&a, &b);
	cout << "execute swap02 after a = " << a << endl;
	cout << "execute swap02 after b = " << b << endl;

	system("pause");
	return 0;
}

总结:如果不想修改实参,就用值传递,如果想修改实参,就用指针传递

八、指针&数组&函数

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

例如数组:int arr[10] = {4,3,6,9,1,2,10,8,7,5};

示例:

#include <iostream>
using namespace std;

// 地址传递 int* arr 也可以写成 int arr[]
void bubbleSort(int* arr, int len)
{
	// 数据排序
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len - 1 - i; j++)
		{
			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)
{
	cout << ":[";
	for (int i = 0; i < len; i++)
	{
		if (i == len - 1)
		{
			cout << arr[i] << "]";
		}
		else
		{
			cout << arr[i] << ", ";
		}

	}
	cout << endl;
}

int main()
{
	int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	// 调用打印方法
	cout << "数组排序前";
	printArray(arr, len);

	// 调用排序算法
	bubbleSort(arr, len);

	// 调用打印方法
	cout << "数组排序前";
	printArray(arr, len);
	
	system("pause");
	return 0;
}

第九章 结构体

一、结构体基本概念

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

二、结构体定义和使用

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

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

  • struct 结构体名 变量名
  • struct 结构体名 变量名
  • 定义结构体是顺便创建变量

示例:

#include <iostream>
using namespace std;

// 结构体定义 - 自定义数据类型就是一些基础类型的集合
// 1、定义老师数据类型
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
}s3;

int main()
{
	// 2、通过老师类型创建具体学生
	// 2.1 struct Teacher s1 
    // C++ 中 结构体创建时 struct 关键字可以省略
	struct Teacher s1;
	// 给 s1 属性赋值, 通过 . 访问结构体变量中的属性
	s1.name = "桥本有菜";
	s1.age = 18;
	s1.gender = 'F';
	s1.score = 18.8f;
	s1.status = true;
	cout << "姓名:" << s1.name << "; 性别:" << s1.gender << "; 年龄:" << s1.age << "岁; 分数:" << s1.score << "; 状态:" << s1.status << endl;

	// 2.2 struct Teacher s2 = {...}
	struct Teacher s2 = {
		"三上悠亚",
		22,
		'F',
		16.2f,
		false
	};
	cout << "姓名:" << s2.name << "; 性别:" << s2.gender << "; 年龄:" << s2.age << "岁; 分数:" << s2.score << "; 状态:" << s2.status << endl;

	// 2.3 在定义结构体时顺便创建结构体变量
	s3.name = "小泽玛利亚";
	s3.age = 36;
	s3.gender = 'F';
	s3.score = 28.8f;
	s3.status = true;
	cout << "姓名:" << s3.name << "; 性别:" << s3.gender << "; 年龄:" << s3.age << "岁; 分数:" << s3.score << "; 状态:" << s3.status << endl;

	system("pause");
	return 0;
}

C++ 中 结构体创建时 struct 关键字可以省略。 定义时不可以省略

结构体变量利用操作符 “.” 访问成员

三、结构体数组

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

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

示例:

#include <iostream>
using namespace std;

// 1、定义结构体
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
};


int main()
{
	// 2、创建结构体数组
	struct Teacher arr[3] = {
		{ "桥本有菜", 18, 'F', 18.8f, true },
		{ "三上悠亚", 22, 'F', 16.2f, false },
		{ "小泽玛利亚", 36, 'F', 28.8f, true },
	};

	// 3、修改结构体数组中的数值
	arr[2].name = "河北彩花";
	arr[2].age = 26;

	// 4、循环打印老师信息
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		cout << "姓名:" << arr[i].name << "; 性别:" << arr[i].gender << "; 年龄:" << arr[i].age << "岁; 分数:" << arr[i].score << "; 状态:" << arr[i].status << endl;
	}

	system("pause");
	return 0;
}

四、结构体指针

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

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

示例:

#include <iostream>
using namespace std;

// 1、定义结构体
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
};


int main()
{
	// 2、创建结构体变量
	struct Teacher teacher = { "桥本有菜", 18, 'F', 18.8f, true };
	// 3、通过指针指向结构体变量
	struct Teacher* p = &teacher;
	// 4、通过指针访问结构体变量中的数据
	cout << "姓名:" << p->name << "; 性别:" << p->gender << "; 年龄:" << p->age << "岁; 分数:" << p->score << "; 状态:" << p->status << endl;
	// 5、通过指针修改结构体变量中的数据
	p->name = "三上悠亚";
	p->age = 22;
	p->status = false;
	cout << "姓名:" << p->name << "; 性别:" << p->gender << "; 年龄:" << p->age << "岁; 分数:" << p->score << "; 状态:" << p->status << endl;

	system("pause");
	return 0;
}

总结:结构体指针可以通过 -> 操作符 来访问结构体中的成员

五、结构体嵌套结构体

作用:结构体中的成员可以是另一个结构体

例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体

示例:

#include <iostream>
using namespace std;

// 1、定义学生结构体
struct Student {
	string name;
	int age;
	char gender;
	bool status;
};

// 2、定义教师结构体
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
	struct Student stu; // 子结构体 学生
};


int main()
{
	// 3、创建老师
	Teacher t;
	t.name = "桥本有菜";
	t.age = 18;
	t.gender = 'F';
	t.score = 18.8f;
	t.status = true;
	t.stu.name = "刘安冰";
	t.stu.age = 24;
	t.stu.gender = 'M';
	t.stu.status = true;

	cout << "老师信息 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;
	cout << "学生信息 - " << "姓名:" << t.stu.name << "; 性别:" << t.stu.gender << "; 年龄:" << t.stu.age << "岁" << endl;

	system("pause");
	return 0;
}

六、结构体做函数参数

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

传递方式有两种:

  • 值传递
  • 地址传递

示例:

#include <iostream>
using namespace std;

// 1、定义教师结构体
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
};

// 2、值传递
void printTeacher1(struct Teacher t)
{
	t.name = "三上悠亚";
	t.age = 22;
	t.status = false;
	cout << "子函数中 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;
}

// 3、地址传递
void printTeacher2(struct Teacher* p)
{
	p->name = "三上悠亚";
	p->age = 22;
	p->status = false;
	cout << "子函数中 - " << "姓名:" << p->name << "; 性别:" << p->gender << "; 年龄:" << p->age << "岁; 分数:" << p->score << "; 状态:" << p->status << endl;
}

int main()
{
	// /4、创建老师
	struct Teacher t;
	t.name = "桥本有菜";
	t.age = 18;
	t.gender = 'F';
	t.score = 18.8f;
	t.status = true;
	cout << "主函数中 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;
	printTeacher1(t);
	cout << "主函数中 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;
	printTeacher2(&t);
	cout << "主函数中 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;

	system("pause");
	return 0;
}

总结:如果不想修改主函数中的数据,用值传递,反之用地址传递

七、结构体中 const 使用场景

作用:用 const 来防止误操作

示例:

#include <iostream>
using namespace std;

// 1、定义教师结构体
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
};

// 2、const 使用场景 将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
void printTeacher(const Teacher* t)
{
	/* 操作失败,因为添加了 const 修饰符
	t->name = "三上悠亚";
	t->age = 22;
	t->status = false;
	*/
	cout << "子函数中 - " << "姓名:" << t->name << "; 性别:" << t->gender << "; 年龄:" << t->age << "岁; 分数:" << t->score << "; 状态:" << t->status << endl;
}


int main()
{
	// 3、创建老师
	struct Teacher t = { "桥本有菜", 18, 'F', 18.8f, true };
	cout << "主函数中 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;
	printTeacher(&t);
	cout << "主函数中 - " << "姓名:" << t.name << "; 性别:" << t.gender << "; 年龄:" << t.age << "岁; 分数:" << t.score << "; 状态:" << t.status << endl;

	system("pause");
	return 0;
}

八、结构体案例

1、案例一

案例描述:学校正在做毕设项目,每名老师带领无名学生,总共3名老师,需求如下

  • 设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和存放5名学生的数组作为成员
  • 学生的成员有姓名、考试分数、创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
  • 最终打印出老师数据以及老师所带的学生数据

示例:

#include <iostream>
using namespace std;


// 1、定义学生结构体
struct Student
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
};


// 2、定义教师结构体
struct Teacher
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	char gender;	// 性别
	float score;	// 分数
	bool status;	// 状态
	Student students[5]; // 学生列表
};


// 3、定义创建数据函数
void allocateSpace(Teacher teachers[], int len)
{
	string names[3] = { "桥本有菜", "三上悠亚", "小泽玛利亚" };
	string studentNameSeed = "ABCDE";
	for (int i = 0; i < len; i++)
	{
		teachers[i].name = names[i];
		teachers[i].age = 18;
		teachers[i].gender = 'F';
		teachers[i].score = 18.8f;
		teachers[i].status = true;
		for (int j = 0; j < sizeof(teachers[i].students) / sizeof(teachers[i].students[0]); j++)
		{
			float random = rand() % 61 + 40; // 40 ~ 100
			teachers[i].students[j].name = "学生-";
			teachers[i].students[j].name += studentNameSeed[j];
			teachers[i].students[j].age = 12;
			teachers[i].students[j].gender = 'M';
			teachers[i].students[j].score = random;
			teachers[i].students[j].status = random > 60.0f ? true : false;
		}
	}
}


// 4、定义打印函数
void printInfo(const Teacher teachers[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << "老师信息: " << "姓名:" << teachers[i].name << "; 性别:" << teachers[i].gender << "; 年龄:" << teachers[i].age << "岁; 分数:" << teachers[i].score << "; 状态:" << teachers[i].status << endl;
		for (int j = 0; j < sizeof(teachers[i].students) / sizeof(teachers[i].students[0]); j++)
		{
			cout << "\t学生信息: " << "姓名:" << teachers[i].students[j].name << "; 性别:" << teachers[i].students[j].gender << "; 年龄:" << teachers[i].students[j].age << "岁; 分数:" << teachers[i].students[j].score << "; 状态:" << teachers[i].students[j].status << endl;
		}
	}
}

int main()
{
	// 随机数种子
	srand((unsigned int)time(NULL));

	// 4、创建3名老师的数组
	struct Teacher teachers[3];

	// 5、通过函数给三名老师的信息赋值,并给老师带的学生信息赋值
	int len = sizeof(teachers) / sizeof(teachers[0]);
	allocateSpace(teachers, len);

	// 6、打印所有老师及所带的学生信息
	printInfo(teachers, len);

	system("pause");
	return 0;
}

2、案例二

案例描述:设计一个英雄的结构体,包括姓名,年龄,性别;创建结构体数组,数组中存放 5名 英雄

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

姓名 年龄 性别
刘备 23
关羽 22
张飞 20
赵云 21
貂蝉 19

示例:

#include <iostream>
using namespace std;


// 定义结构体
struct Hero
{
	// 成员列表
	string name;	// 姓名
	int age;		// 年龄
	string gender;	// 性别
};

// 排序
void bubbleSort(Hero heros[], int len)
{
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len - 1 - i; j++)
		{
			cout << heros[i].age << " " << heros[j + 1].age << endl;
			if (heros[j].age > heros[j + 1].age)
			{
				Hero temp = heros[j];
				heros[j] = heros[j + 1];
				heros[j + 1] = temp;
			}
		}
	}
}

// 打印
void printHeros(Hero heros[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << heros[i].name << "今年" << heros[i].age << "岁,他是个" << heros[i].gender << "的" << endl;
	}
}


int main()
{
	// 创建结构体数组
	struct Hero heros[5] = {
		{ "刘备", 23, "男" },
		{ "关羽", 22, "男" },
		{ "张飞", 20, "男" },
		{ "赵云", 21, "男" },
		{ "貂蝉", 19, "女" },
	};
	int len = sizeof(heros) / sizeof(heros[0]);

	printHeros(heros, len);
	bubbleSort(heros, len);
	cout << endl;
	printHeros(heros, len);
	
	system("pause");
	return 0;
}

第十章 扩展

二、通讯录管理系统

1、系统需求

通讯录是一个可以记录亲人、好友信息的工具

本教程中主要利用 C++ 来实现一个通讯录管理系统

系统中需要实现的功能如下:

  • 添加联系人:向通讯录中添加信任,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录 1000 人
  • 显示联系人:显示通讯录中所有联系人信息
  • 删除联系人:按照姓名进行删除指定联系人
  • 查找联系人:按照姓名查看制定联系人信息
  • 修改联系人:按照姓名重新修改指定联系人
  • 清空联系人:清空通讯录中所有信息
  • 退出通讯录:退出当前使用的通讯录

2、创建项目

打开 Visual Studio 2019 点击创建新项目,创建新的 C++ 项目

3、菜单功能

功能描述:用户选择功能的界面

菜单界面效果如下图:

步骤:

  • 封装函数显示该界面 如 void showMenu()
  • 在main 函数中调用封装好的函数

示例

#include <iostream>
using namespace std;

// 封装显示菜单函数
void showMenu()
{
	cout << "***************************" << endl;
	cout << "*****  1、添加联系人  *****" << endl;
	cout << "*****  2、显示联系人  *****" << endl;
	cout << "*****  3、删除联系人  *****" << endl;
	cout << "*****  4、查找联系人  *****" << endl;
	cout << "*****  5、修改联系人  *****" << endl;
	cout << "*****  5、修改联系人  *****" << endl;
	cout << "*****  6、清空联系人  *****" << endl;
	cout << "*****  0、退出通讯录  *****" << endl;
	cout << "***************************" << endl;
}


int main()
{
	// 菜单调用
	showMenu();

	system("pause");
	return 0;
}

4、退出功能

功能描述:退出通讯录系统

思路:根据用户不同选择,进入不同的功能,可以选择 switch 分支,将整个架构进行搭建

当用户选择 0 时,执行退出,选择其他先不做操作,也不会退出程序

示例:

#include <iostream>
using namespace std;

// 封装显示菜单函数
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()
{
	
	int select = 0;

	while (true)
	{
		// 菜单调用
		showMenu();
		cin >> select;
		switch (select)
		{
		case 1:
			cout << "1、添加联系人" << endl;
			break;
		case 2:
			cout << "2、显示联系人" << endl;
			break;
		case 3:
			cout << "3、删除联系人" << endl;
			break;
		case 4:
			cout << "4、查找联系人" << endl;
			break;
		case 5:
			cout << "5、修改联系人" << endl;
			break;
		case 6:
			cout << "6、清空联系人" << endl;
			break;
		case 0:
			cout << "欢迎下次使用!!!" << endl;
			system("pause");
			return 0;
			break;
		default:
			break;
		}
	}

	system("pause");
	return 0;
}

5、添加联系人

功能描述:实现添加联系人,联系人上限为 1000 人,联系人信息包括(姓名、性别、年龄、联系电话、家庭住址)

添加联系人实现步骤:

  • 设计联系人结构体
  • 设计通讯录结构体
  • main函数中创建通讯录
  • 封装添加联系人函数
  • 测试添加联系人功能
// 封装添加联系人函数
void addcontactPerson(struct addressBook* address_books)
{
	// 判断通讯录是否超过最大值
	if (address_books->contactPersonSize >= MAX)
	{
		cout << "通讯录已满,无法添加!!!" << endl;
	}
	else
	{
		// 添加联系人 姓名、性别、年龄、联系电话、家庭住址
		string name;
		cout << "请输入姓名:";
		cin >> name;
		address_books->contact_persons[address_books->contactPersonSize].name = name;
		
		int gender;
		cout << "请输入性别 1男 2女:";
		while (true)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				address_books->contact_persons[address_books->contactPersonSize].gender = gender;
				break;
			} 
			else
			{
				cout << "输入有误,请重新输入" << endl;
				cout << "请输入性别 1男 2女:";
			}
		}
		
		int age;
		cout << "请输入年龄:";
		cin >> age;
		address_books->contact_persons[address_books->contactPersonSize].age = age;
		
		string phone;
		cout << "请输入联系电话:";
		cin >> phone;
		address_books->contact_persons[address_books->contactPersonSize].phone = phone;
		
		string address;
		cout << "请输入家庭住址:";
		cin >> address;
		address_books->contact_persons[address_books->contactPersonSize].address = address;

		address_books->contactPersonSize++;
		cout << "添加成功!!!" << endl;
		system("pause");
		system("cls");
	}
}

6、显示联系人

功能描述:显示通讯录中已有的联系人信息

显示联系人实现步骤:

  • 封装显示联系人函数
  • 测试现实联系人功能

思路:判断如果当前通讯录中没有人员,就提示为空,大叔大于 0 ,显示通讯录中信息

示例:

// 封装显示联系人函数
void showContactPersonAll(const struct addressBook address_books)
{
	if (address_books.contactPersonSize == 0)
	{
		cout << "通讯录中还没有联系人!!!" << endl;
	}
	else
	{
		for (int i = 0; i < address_books.contactPersonSize; i++)
		{
			cout << "姓名:" << address_books.contact_persons[i].name << "; 年龄:" << address_books.contact_persons[i].age << "; 性别:" << (address_books.contact_persons[i].gender == 1 ? "男" : "女") << "; 练习方式:" << address_books.contact_persons[i].phone << "; 家庭住址:" << address_books.contact_persons[i].address << endl;
		}
	}
	system("pause");
	system("cls");
}

7、删除联系人

功能描述:按照姓名进行删除指定联系人

删除联系人实现步骤

  • 封装检测联系人是否存在函数
  • 封装删除练习人函数
  • 测试删除联系人

封装检测联系人是否存在函数:删除联系人之前,我们需要先判断用户输入的联系人是否存在,如果存在则删除,不存在提示用户没有要删除的联系人,因此我们可以把检测联系人是否存在封装成一个函数,如果存在,返回联系人在通讯录中的位置,不存在返回 -1

封装删除练习人函数:根据用户输入的联系人判断通讯录中是否有此人

查找到进行删除,并提示删除成功

查不到提示查无此人

示例

// 封装检测联系人是否存在
int isExist(struct addressBook* address_books, string name)
{
	for (int i = 0; i < address_books->contactPersonSize; i++)
	{
		if (address_books->contact_persons[i].name == name)
		{
			return i;
		}
	}
	return -1;
}


// 封装删除联系人函数
void delContactPerson(struct addressBook* address_books) 
{
	string name;
	cout << "请输入要删除的姓名:";
	cin >> name;
	int index = isExist(address_books, name);
	if (index == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		// 将指定要删除的名称 后的联系人向前移动,并且让通讯录中记录的人员个数做 -1 的操作
		for (int i = index; i < address_books->contactPersonSize; i++)
		{
			address_books->contact_persons[i] = address_books->contact_persons[i + 1];
		}
		address_books->contactPersonSize--;
		cout << "删除成功!!!" << endl;
	}
	system("pause");
	system("cls");
}

8、查找联系人

功能描述:按照姓名查看指定联系人信息

查找联系人实现步骤

  • 封装查找联系人函数
  • 测试查找指定联系人

实现思路:判断用户指定的联系人是否存在,如果存在显示心爱,不存在则提示查无此人

示例:

// 封装查找联系人函数
void findContactPerson(const struct addressBook address_books)
{
	string name;
	cout << "请输入要查找的姓名:";
	cin >> name;
	int index = isExist(address_books, name);
	if (index == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		cout << "姓名:" << address_books.contact_persons[index].name << "; 年龄:" << address_books.contact_persons[index].age << "; 性别:" << (address_books.contact_persons[index].gender == 1 ? "男" : "女") << "; 练习方式:" << address_books.contact_persons[index].phone << "; 家庭住址:" << address_books.contact_persons[index].address << endl;
	}
	system("pause");
	system("cls");
}

9、修改联系人

功能描述:按照姓名重新修改指定联系人

修改联系人实现步骤:

  • 封装修改联系人函数
  • 测试修改联系人功能

实现思路:查找用户输入的联系人,查找成功进行修改操作,查找失败提示查无此人

示例:

// 封装修改联系人函数
void updateContactPerson(struct addressBook* address_books)
{
	string name;
	cout << "请输入要查找的姓名:";
	cin >> name;
	int index = isExist(*address_books, name);
	if (index == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		// 编辑联系人 姓名、性别、年龄、联系电话、家庭住址
		string name;
		cout << "请输入姓名:";
		cin >> name;
		address_books->contact_persons[address_books->contactPersonSize].name = name;

		int gender;
		cout << "请输入性别 1男 2女:";
		while (true)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				address_books->contact_persons[address_books->contactPersonSize].gender = gender;
				break;
			}
			else
			{
				cout << "输入有误,请重新输入" << endl;
				cout << "请输入性别 1男 2女:";
			}
		}

		int age;
		cout << "请输入年龄:";
		cin >> age;
		address_books->contact_persons[address_books->contactPersonSize].age = age;

		string phone;
		cout << "请输入联系电话:";
		cin >> phone;
		address_books->contact_persons[address_books->contactPersonSize].phone = phone;

		string address;
		cout << "请输入家庭住址:";
		cin >> address;
		address_books->contact_persons[address_books->contactPersonSize].address = address;
		cout << "修改成功!!!" << endl;
	}
	system("pause");
	system("cls");
}

10、清空联系人

功能描述:清空通讯录中所有信息

清空联系人实现步骤

  • 封装清空联系人函数
  • 测试清空联系人

实现思路:将通讯录所有联系人清理掉,只要将通讯录的联系人数量置为 0 ,做逻辑清空即可。

示例:

// 封装清空联系人函数
void clearContactPerson(struct addressBook* address_books)
{
	address_books->contactPersonSize = 0;
	cout << "通讯录已清空!!!" << endl;
	system("pause");
	system("cls");
}

11、总结

完整代码

#include <iostream>
using namespace std;

#define MAX 1000 // 最大人数

// 设计联系人结构体 联系人信息包括(姓名、性别、年龄、联系电话、家庭住址)
struct contactPerson
{
	string name;	// 姓名
	int gender;		// 性别 1男 2女
	int age;		// 年龄
	string phone;	// 联系电话
	string address;	// 家庭住址
};

// 设计通讯录结构体
struct addressBook
{
	// 通讯录中保存的数组联系人
	struct contactPerson contact_persons[MAX];

	// 通讯录中当前记录练习人个数
	int contactPersonSize;
};

// 封装显示菜单函数
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;
}


// 封装添加联系人函数
void addContactPerson(struct addressBook* address_books)
{
	// 判断通讯录是否超过最大值
	if (address_books->contactPersonSize >= MAX)
	{
		cout << "通讯录已满,无法添加!!!" << endl;
	}
	else
	{
		// 添加联系人 姓名、性别、年龄、联系电话、家庭住址
		string name;
		cout << "请输入姓名:";
		cin >> name;
		address_books->contact_persons[address_books->contactPersonSize].name = name;

		int gender;
		cout << "请输入性别 1男 2女:";
		while (true)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				address_books->contact_persons[address_books->contactPersonSize].gender = gender;
				break;
			}
			else
			{
				cout << "输入有误,请重新输入" << endl;
				cout << "请输入性别 1男 2女:";
			}
		}

		int age;
		cout << "请输入年龄:";
		cin >> age;
		address_books->contact_persons[address_books->contactPersonSize].age = age;

		string phone;
		cout << "请输入联系电话:";
		cin >> phone;
		address_books->contact_persons[address_books->contactPersonSize].phone = phone;

		string address;
		cout << "请输入家庭住址:";
		cin >> address;
		address_books->contact_persons[address_books->contactPersonSize].address = address;

		address_books->contactPersonSize++;
		cout << "添加成功!!!" << endl;
		system("pause");
		system("cls");
	}
}


// 封装显示联系人函数
void showContactPersonAll(const struct addressBook address_books)
{
	if (address_books.contactPersonSize == 0)
	{
		cout << "通讯录中还没有联系人!!!" << endl;
	}
	else
	{
		for (int i = 0; i < address_books.contactPersonSize; i++)
		{
			cout << "姓名:" << address_books.contact_persons[i].name << "; 年龄:" << address_books.contact_persons[i].age << "; 性别:" << (address_books.contact_persons[i].gender == 1 ? "男" : "女") << "; 练习方式:" << address_books.contact_persons[i].phone << "; 家庭住址:" << address_books.contact_persons[i].address << endl;
		}
	}
	system("pause");
	system("cls");
}


// 封装检测联系人是否存在
int isExist(const struct addressBook address_books, string name)
{
	for (int i = 0; i < address_books.contactPersonSize; i++)
	{
		if (address_books.contact_persons[i].name == name)
		{
			return i;
		}
	}
	return -1;
}


// 封装删除联系人函数
void delContactPerson(struct addressBook* address_books)
{
	string name;
	cout << "请输入要删除的姓名:";
	cin >> name;
	int index = isExist(*address_books, name);
	if (index == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		// 将指定要删除的名称 后的联系人向前移动,并且让通讯录中记录的人员个数做 -1 的操作
		for (int i = index; i < address_books->contactPersonSize; i++)
		{
			address_books->contact_persons[i] = address_books->contact_persons[i + 1];
		}
		address_books->contactPersonSize--;
		cout << "删除成功!!!" << endl;
	}
	system("pause");
	system("cls");
}


// 封装查找联系人函数
void findContactPerson(const struct addressBook address_books)
{
	string name;
	cout << "请输入要查找的姓名:";
	cin >> name;
	int index = isExist(address_books, name);
	if (index == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		cout << "姓名:" << address_books.contact_persons[index].name << "; 年龄:" << address_books.contact_persons[index].age << "; 性别:" << (address_books.contact_persons[index].gender == 1 ? "男" : "女") << "; 练习方式:" << address_books.contact_persons[index].phone << "; 家庭住址:" << address_books.contact_persons[index].address << endl;
	}
	system("pause");
	system("cls");
}


// 封装修改联系人函数
void updateContactPerson(struct addressBook* address_books)
{
	string name;
	cout << "请输入要查找的姓名:";
	cin >> name;
	int index = isExist(*address_books, name);
	if (index == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		// 编辑联系人 姓名、性别、年龄、联系电话、家庭住址
		string name;
		cout << "请输入姓名:";
		cin >> name;
		address_books->contact_persons[index].name = name;

		int gender;
		cout << "请输入性别 1男 2女:";
		while (true)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				address_books->contact_persons[index].gender = gender;
				break;
			}
			else
			{
				cout << "输入有误,请重新输入" << endl;
				cout << "请输入性别 1男 2女:";
			}
		}

		int age;
		cout << "请输入年龄:";
		cin >> age;
		address_books->contact_persons[index].age = age;

		string phone;
		cout << "请输入联系电话:";
		cin >> phone;
		address_books->contact_persons[index].phone = phone;

		string address;
		cout << "请输入家庭住址:";
		cin >> address;
		address_books->contact_persons[index].address = address;
		cout << "修改成功!!!" << endl;
	}
	system("pause");
	system("cls");
}


// 封装清空联系人函数
void clearContactPerson(struct addressBook* address_books)
{
	address_books->contactPersonSize = 0;
	cout << "通讯录已清空!!!" << endl;
	system("pause");
	system("cls");
}


// 程序入口函数
int main()
{
	// main函数中创建通讯录
	addressBook address_books;
	// 初始化通讯录中当前人数个数
	address_books.contactPersonSize = 0;
	// 菜单选择
	int select = 0;

	while (true)
	{
		// 菜单调用
		showMenu();
		cout << "请输入您的操作:";
		cin >> select;
		switch (select)
		{
		case 1:
			addContactPerson(&address_books); // 利用地址传递,可以修饰实参
			break;
		case 2:
			showContactPersonAll(address_books); // 用 const 来防止误操作
			break;
		case 3:
			delContactPerson(&address_books);
			break;
		case 4:
			findContactPerson(address_books);
			break;
		case 5:
			updateContactPerson(&address_books);
			break;
		case 6:
			clearContactPerson(&address_books);
			break;
		case 0:
			cout << "欢迎下次使用!!!" << endl;
			system("pause");
			return 0;
			break;
		default:
			break;
		}
	}

	system("pause");
	return 0;
}

一、Visual studio 2019 快捷键

1、常用快捷键

快捷键 功能
Ctrl+K+C 注释代码
Ctrl+K+U 取消注释代码
Ctrl+K+D 格式化全部代码
Ctrl+Shift+A 新建类
Ctrl+R+G 删除无效Using
Ctrl+H 批量替换
Ctrl+J 自动提示
Ctrl+G 跳转到指定行
Ctrl+E+E 在交互窗口中运行选中代码(很实用)
Alt+Enter 快速引用
shift+F9 监控(代码运行时)
shift+F6 生成(当前类库)
F6 生成(整个解决方案中类库)
Shift+F12 查找所有引用
Tab+Tab 代码联想
cw+Tab+Tab Console.WriteLine()

2、项目相关的快捷键

快捷键 功能
Ctrl + Shift + B 生成项目
Ctrl + Alt + L 显示 Solution Explorer(解决方案资源管理器)
Shift + Alt+ C 添加新类
Shift + Alt + A 添加新项目到项目
CTRL + F7 生成编译
CTRL + O 打开文件
CTRL + SHIFT + O 打开项目
CTRL + SHIFT + C 显示类视图窗口
F4 显示属性窗口
SHIFT + F4 显示项目属性窗口
CTRL + SHIFT + E 显示资源视图
F12 转到定义
CTRL + F12 转到声明
CTRL + ALT + J 对象浏览
CTRL + ALT + F1 帮助目录
CTRL + F1 动态帮助
F1 帮助
SHIFT + F1 当前窗口帮助
CTRL + ALT + F3 帮助-搜索
SHIFT + ALT + ENTER 全屏显示
CTRL + - 向后定位
CTRL + SHIFT + - 向前定位
CTRL + F4 关闭文档窗口
CTRL + PAGE DOWN 光标定位到窗口上方
CTRL + PAGE UP 光标定位到窗口下方
CTRL + F6
CTRL + TAB 下一个文档窗口
CTRL + SHIFT + F6
CTRL + SHIFT + TAB 上一个文档窗口
ALT + F6 下一个面板窗口
CTRL + K, CTRL + L 取消remark
CTRL + K, CTRL + C 注释选择的代码
CTRL + K, CTRL + U 取消对选择代码的注释
CTRL + M, CTRL + O 折叠代码定义
CTRL + M, CTRL + L 展开代码定义
CTRL + DELETE 删除至词尾
CTRL + BACKSPACE 删除至词头
SHIFT + TAB 取消制表符
CTRL + U 转小写
CTRL + SHIFT + U 转大写
CTRL + SHIFT + END 选择至文档末尾
CTRL + SHIFT + HOME 选择至文档末尾开始
SHIFT + END 选择至行尾
SHIFT + HOME 选择至行开始处
SHIFT + ALT + END 垂直选择到最后尾
SHIFT + ALT + HOME 垂直选择到最前面
CTRL + A 全选
CTRL + W 选择当前单词
CTRL + SHIFT + PAGE UP 选择至本页前面
CTRL + SHIFT + PAGE DOWN 选择至本页后面
CTRL + END 文档定位到最后
CTRL + HOME 文档定位到最前
CTRL + G 转到…
CTRL + K, CTRL + P 上一个标签
CTRL + K, CTRL + N 下一个标签
ALT + F10 调试-ApplyCodeChanges
CTRL + ALT+ Break 停止调试
CTRL + SHIFT + F9 取消所有断点
CTRL + F9 允许中断
CTRL + SHIFT + F5 调试-重新开始
F5 运行调试
CTRL + F5 运行不调试
F10 跨过程序执行
F11 单步逐句执行
CTRL + J 列出成员
CTRL + PAGE DOWN 下一个视图
CTRL + B 格式-粗体
CTRL + SHIFT + T 格式-文字缩进

3、编辑相关的键盘快捷键

快捷键 功能
Ctrl + Enter 在当前行插入空行
Ctrl + Shift + Enter 在当前行下方插入空行
Ctrl + 空格键 使用 IntelliSense(智能感知)自动完成
Alt + Shift + 箭头键(←,↑,↓,→) 选择代码的自定义部分
Ctrl + } 匹配大括号、括号
Ctrl + Shift +} 在匹配的括号、括号内选择文本
Ctrl + Shift + S 保存所有文件和项目
Ctrl + K,Ctrl + C 注释选定行
Ctrl + K,Ctrl + U 取消选定行的注释
Ctrl + K,Ctrl + D 正确对齐所有代码
Shift + End 从头到尾选择整行
Shift + Home 从尾到头选择整行
Ctrl + Delete 删除光标右侧的所有字
Ctrl+K,D 格式化全部代码
Ctrl+K,F 格式化选中的代码
Shift+Alt+Enter 切换全屏编辑
Ctrl+B,T / Ctrl+K,K 切换书签开关
Ctrl+B,N / Ctrl+K,N 移动到下一书签
Ctrl+B,P 移动到上一书签
Ctrl+B,C 清除全部标签
Ctrl+I 渐进式搜索
Ctrl+Shift+I 反向渐进式搜索
Ctrl+F 查找
Ctrl+Shift+F 在文件中查找
F3 查找下一个
Shift+F3 查找上一个
Ctrl+H 替换
Ctrl+Shift+H 在文件中替换
Alt+F12 查找符号(列出所有查找结果)
Ctrl+Shift+V 剪贴板循环
Ctrl+左右箭头键 一次可以移动一个单词
Ctrl+上下箭头键 滚动代码屏幕,但不移动光标位置。
Ctrl+Shift+L 删除当前行
Ctrl+M,M 隐藏或展开当前嵌套的折叠状态
Ctrl+M,L 将所有过程设置为相同的隐藏或展开状态
Ctrl+M,P 停止大纲显示
Ctrl+E,S 查看空白
Ctrl+E,W 自动换行
Ctrl+G 转到指定行
Shift+Alt+箭头键 选择矩形文本
Alt+鼠标左按钮 选择矩形文本
Ctrl+Shift+U 全部变为大写
Ctrl+U 全部变为小写

4、导航相关的键盘快捷键

快捷键 功能
Ctrl +Up/Down 滚动窗口但不移动光标
Ctrl + - 让光标移动到它先前的位置
Ctrl ++ 让光标移动到下一个位置
F12 转到定义

5、调试相关的键盘快捷键

快捷键 功能
Ctrl + Alt + P 附加到进程
F10 调试单步执行
F5 开始调试
Shift + F5 停止调试
Ctrl + Alt + Q 添加快捷匹配
F9 设置或删除断点
F6 生成解决方案
Ctrl+F6 生成当前项目
F7 查看代码
Shift+F7 查看窗体设计器
Ctrl+F5 开始执行(不调试)
Shift+F5 停止调试
Ctrl+Shift+F5 重启调试
Ctrl+F9 启用/停止断点
Ctrl+Shift+F9 删除全部断点
Ctrl+F10 运行到光标处
F11 逐语句

6、搜索相关的键盘快捷键

快捷键 功能
Ctrl + K Ctrl + K 将当前行添加书签
Ctrl + K Ctrl + N 导航至下一个书签
Ctrl + . 如果你键入一个类名如 Collection,且命名空间导入不正确的话,那么这个快捷方式组合将自动插入导入
Ctrl + Shift + F 在文件中查找
Shift + F12 查找所有引用
Ctrl + F 显示查找对话框
Ctrl + H 显示替换对话框
Ctrl + G 跳转到行号或行
Ctrl + Shift + F 查找所选条目在整个解决方案中的引用

7、窗口相关的键盘快捷键

快捷键 功能
Ctrl+W,W 浏览器窗口
Ctrl+W,S 解决方案管理器
Ctrl+W,C 类视图
Ctrl+W,E 错误列表
Ctrl+W,O 输出视图
Ctrl+W,P 属性窗口
Ctrl+W,T 任务列表
Ctrl+W,X 工具箱
Ctrl+W,B 书签窗口
Ctrl+W,U 文档大纲
Ctrl+D,B 断点窗口
Ctrl+D,I 即时窗口
Ctrl+Tab 活动窗体切换
Ctrl+Shift+N 新建项目
Ctrl+Shift+O 打开项目
Ctrl+Shift+S 全部保存
Shift+Alt+C 新建类
Ctrl+Shift+A 新建项

8、单元测试相关键盘快捷键

快捷键 功能
Ctrl + R , A 执行所有测试
Ctrl + R , T 执行当前所在测试方法
Ctrl + R , D 执行最后一次测试的所有测试
Ctrl + R , F 执行最后一次测试的所有测试的失败测试

9、其他快捷键

快捷键 功能
Ctrl+J / Ctrl+K,L 列出成员
Ctrl+Shift+空格键 / Ctrl+K,P 参数信息
Ctrl+K,I 快速信息
Ctrl+E,C / Ctrl+K,C 注释选定内容
Ctrl+E,U / Ctrl+K,U 取消选定注释内容
Ctrl+K,M 生成方法存根
Ctrl+K,X 插入代码段
Ctrl+K,S 插入外侧代码
F12 转到所调用过程或变量的定义

软考密码:Xing19971215qwe

posted @ 2023-06-01 14:26  菜鸟程序员_python  阅读(228)  评论(0)    收藏  举报