【C++】基础语法

 

一、初识C++

0. Visual Studio 使用

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

1.1 Hello World!

#include <iostream>
using namespace std;

int main()
{
	cout << "Hello World!" << endl;
	system("pause");
	return 0;
}

1.2 注释

  • 单行注释
// 这是单行注释
  • 多行注释
/*
    这是多行注释
    可以注释多行
*/

1.3 变量

  • 给指定内存区间取名,方便管理内存空间
  • 数据类型 变量名 = 变量初始化值;
    int a = 10;

1.4 常量

  • 记录程序中不能修改的数据
  • #define 宏常量
    • 通常在文件上方定义,没有分号结尾
    • #define 宏常量名称 宏常量值
  • const 修饰的变量
    • 在变量定义前加const,修饰该变量为常量
    • const 变量类型 变量名 = 变量值;
// 4.1 #define 宏常量
#define DAY 7
int main() {
	// DAY = 14; // 错误:DAY是常量,一旦修改就会报错
	cout << "一周共有" << DAY << "天" << endl;

// 4.2 const 修饰变量
	const int MONTH = 12;
	// MONTH = 14; // 错误:const修饰的变量也成为常量
	cout << "一周共有" << MONTH << "个月份" << endl;

	system("pause");
	return 0;
}

1.5 关键字(标识符)

  • 不要用关键字给变量/常量起名
asmdoifreturntypedef
autodoubleinlineshorttypeid
booldynamic_castintsignedtypename
breakelselongsizeofunion
caseenummutablestaticunsigned
catchexplictnamespacestatic_castusing
chatexportnewstructvirtual
classexternoperatorswitchvoid
constfalseprivatetemplatevolatile
const_castfloatprotectedthiswchar_t
continueforpublicthrowwhile
defaultfriendregistertrue
deletegotoreinterpret_casttry

1.6 标识符命名规则

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

二、数据类型

  • 创建变量时必须指出相应的数据类型,否则无法给变量分配内存
  • 数据类型存在意义:给变量分配合适的内存空间

2.1 整型

数据类型占用空间取值范围
short2 bytes-2^15 ~ 2^15-1 (-32768 ~ 32767)
int4 bytes-2^31 ~ 2^31-1
longWindows 4 bytes, Linux 4 bytes / 8 bytes-2^31 ~ 2^31-1
long long8 bytes-2^63 ~ 2^63-1
  •  占用空间:short < int <= long <= long long
	short num = 32768; 
	cout << num << endl; // -32768

2.2 sizeof关键字

  • 统计数据类型所占内存大小
  • sizeof( 数据类型 / 变量 )
	short num1 = 10;
	cout << "short占用内存空间为:" << sizeof(short) << endl; //2
	cout << "num1占用内存空间为:" << sizeof(num1) << endl; // 2

	short num2 = 32768;
	cout << sizeof(num2) << endl; // 2

2.3 实型(浮点型) 

  • 表示小数
  • 默认情况输出小数会显示六位有效数字
数据类型占用空间有效数字范围
float4字节7位有效数字
double8字节15-16位有效数字
	float f1 = 3.14f; // 没有f默认双精度
	double d1 = 3.14;
	float f2 = 3.1415926;
	cout << f2 << endl; // 3.14159  默认显示六位有效数字

	cout << "float占用内存空间为:" << sizeof(float) << endl; // 4
	cout << "double占用内存空间为:" << sizeof(double) << endl; // 8
	// 科学计数法 e关键字
	float f3 = 3e2; // 3 * 10^2;
	float f4 = 3e-2; // 3 * (0.1)^2;
	cout << f3 << endl; // 300
	cout << f4 << endl; // 0.03

2.4 字符型

  • 表示单个字符,写在单引号
  • C和C++中字符型变量只占用1个字节内存
  • 字符型变量并不存储字符本身,而是存对应的ASCII码放入存储单位
  • ASKII码
    • 非打印控制符0-31,打印字符(键盘上能找到)31-126
    • 常见ASKII码:a-97, A-65
	char ch = 'a';
	cout << ch << endl; // a
	cout << "char占用内存空间为:" << sizeof(char) << endl; // 1

	char ch2 = "b"; // 错误:不能用双引号
	char ch2 = 'abcdef'; // 错误:单引号内只能有一个字符

	// 输出ASKII码值
	cout << (int)ch << endl; // 97

2.5 转义字符

  • 表示不能显示出来的ASKII字符
	cout << "Hello World!\n"; // Hello World!
	cout << "\\" << endl; // '\'
	cout << "aaa\tHelloWorld" << endl; // aaa     HelloWorld
	                                   // HelloWorld前空格数加字符一共是8个字符
转义字符含义ASKII码
\a警报

007

\b退格BS008
\f换页FF012
\n换行010
\r回车013
\t水平制表009
\v垂直制表011
\\代表一个反斜线字符 “\”092
\'代表一个单引号字符039
\"代表一个双引号字符034
\?代表一个问号063
\0数字0000
\ddd8进制转义字符,d范围0-73位8进制
\xhh16进制转义字符,h范围0-9 a-f A-F3位16进制

2.6 字符串型

  • C风格字符串:char 变量名[] = 字符串值;
  • C++风格字符串:string 变量名 = 字符串值;
    • 需要包含头文件 #include <string>
	// C风格
	char str[] = "Hello World!";
	cout << str << endl;

	// C++风格 需要包含头文件 #include <string>
	string str2 = "Hello World!";
	cout << str2 << endl;

2.7 布尔类型 bool

  • 只有两种值
    • true 真(本质是1或非0)
    • false 假(本质是0)
	bool flag = true; // true代表1
	cout << flag << endl; // 1
	flag = false;
	cout << flag << endl; // 0
	
	cout << "bool占用内存空间为:" << sizeof(bool) << endl; // 1

2.8 数据的输入

  • 从键盘获取数据
  • cin >> 赋值变量;
	int a = 0;
	cout << "请给整型变量a赋值:" << endl;
	cin >> a;
	cout << "整型变量a = " << a << endl;

	bool flag = false;
	cout << "请给bool类型flag赋值:" << endl;
	cin >> flag; // 输入非0数字结果都是1,输入true无效
	cout << "flag = " << flag << endl;

三、运算符

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

3.1 算术运算符

运算符术语示例结果
+10 + 515

-

10 - 55
*10 * 550
/10 / 52
+正号+55
-负号-5-5
%取模10 % 31
a++后置递增a = 2, b = a++a = 3, b = 2
++a前置递增a = 2, b = ++aa = 3, b = 3
a--后置递减a = 2, b = a--a = 1, b = 2
--a前置递减a = 2, b = --aa = 1, b = 1

1) 加减乘除正负

  • 两个整数相除结果依然是整数,小数部分去除
  • 两个小数可以相除 结果可以为小数
  • 除数不能为0
	cout << 10 / 3 << endl; // 3
	cout << 10 / 20 << endl; // 0
	cout << 0.5 / 0.2 << endl; // 2.5
	cout << 10 / 0 << endl; // 错误,除数不能为0

2) 取模

  • 除数不能为0
  • 小数不能做取模运算
	cout << 10 % 3 << endl; // 1
	cout << 10 % 20 << endl; // 10
	cout << 0.5 % 0.2 << endl; // 错误,被除数和除数都应为整数
	cout << 10 % 0 << endl; // 错误,除数不能为0

3) 递增递减运算

  • 前置:先加减,后表达式运算
  • 后置:先表达式运算,后加减
	int a = 10;
	int b1 = ++a * 10;
	cout << b1 << endl; // a = 11, b = 110

	a = 10;
	int b2 = a++ * 10;
	cout << b2 << endl; // a = 11, b = 100

3.2 赋值运算符

运算符术语示例结果
=等于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

3.3 比较运算符

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

1

	int a = 10;
	int b = 20;
	cout << (a == b) << endl; // 0
	cout << (a != b) << endl; // 1

3.4 逻辑运算符

  • C++中除了0,其余都为真
运算符术语示例结果
!!aa假!a真,a真!a假
&&a&&b同真为真 其余为假
||a||b同假为假 其余为真
	int a = 10;
	int b = 10;

	cout << !a << endl; // 0
	cout << !!a << endl; // 1

	cout << (a && b) << endl; // 0
	cout << (a || b) << endl; // 1

四、程序流程结构

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

4.1 选择结构

1) if语句
	int score = 0;
	cout << "请输入分数:" << endl;
	cin >> score;

	// 单行if
	if (score >= 60) {
		cout << "及格" << endl;
	}

	// 多行if
	if (score >= 60) {
		cout << "及格" << endl;
	} else {
		cout << "不及格" << endl;
	}

	// 多条if语句
	if (score > 90) {
		cout << "优秀" << endl;
	} else if (score >= 60) {
		cout << "及格" << endl;
	} else {
		cout << "不及格" << endl;
	}

	// 嵌套if
	if (score > 90) {
		if (score == 100) {
			cout << "满分" << endl;
		} else {
			cout << "优秀" << endl;
		}
	} else if (score >= 60) {
		cout << "及格" << endl;
	} else {
		cout << "不及格" << endl;
	}
2) 三目运算符
  • 表达式1 ? 表达式2 : 表达式3;
  • 表达式1成立则执行表达式2,不成立则执行表达式3
	int a = 10;
	int b = 20;
	int c = 0;
	c = (a > b ? a : b); // c = 20
	(a > b ? a : b) = 100; // a = 10, b = 100
3) switch语句
	switch (表达式)
	{
	    case 结果1: 执行语句;break;
	    case 结果1: 执行语句;break;
		...
	    default 执行语句;break;

	}
	int score = 0;
	cin >> score;

	switch (score) {
	case 10:
		cout << "优秀" << endl;
		break;
	case 9:
		cout << "及格" << endl;
		break;
	case 8:
		cout << "良好" << endl;
		break;
	default:
		cout << "一般" << endl;
		break;
  • if vs switch
    • switch判断是只能整型或字符型,不可以是一个区间
    • switch结构清晰,执行效率高

4.2 循环结构

1) while循环语句
  • 只要满足循环条件,就会执行循环语句
  • 循环条件为1是死循环
	// 循环打印 0~9
    int num = 0;
	while (num < 10) {
		cout << num << endl;
		num++;
	}
	// 添加随机数种子
	srand((unsigned int) time(NULL));

	// 生成随机数
	int num = rand() % 100 + 1; // rand()%100 生成0~99之间的随机数

	int val = 0;

	while (1) {
		cout << "请猜数:" << endl;
		cin >> val;
		if (val > num) {
			cout << "猜测过大" << endl;
		} else if (val < num) {
			cout << "猜测过小" << endl;
		} else {
			cout << "猜对了" << endl;
			break;
		}
	}
2) do-while 循环
  • do(循环代码) while(循环条件);
  • 先执行一遍语句后进行条件判断
	// 输出 0~9
    int num = 0;
	do {
		cout << num << endl;
		num++;
	} while (num < 10);
	int num = 0;
	do {
		cout << num << endl;
		num++;
	} while (num); // 死循环

	while (num) { // 不会输出
		cout << num << endl;
		num++;
	}
	// 水仙花数:各个数位三次方之和等于数字本身
	int num = 100;
	int a, b, c = 0;
	do {
		a = num / 100; // 百位
		b = num / 10 % 10; // 十位
		c = num % 10; // 个位
		if (a * a * a + b * b * b + c * c * c == num) {
			cout << num << endl;
		}
		num++;
	} while (num < 1000);
3) for循环
  • for(起始表达式; 条件表达式; 末尾循环体) { 循环语句;}
	for (int i = 0; i < 10; i++) {
		cout << i << endl;
	}
	for (int i = 1; i <= 100; i++) {
		if (i % 10 == 7 || i / 10 == 7 || i % 7 == 0) { // 个位有7、十位有7、7的倍数
			cout << "敲桌子" << endl;
		} else
			cout << i << endl;
	}
  • 嵌套循环
	// 打印9*9乘法表
	for (int i = 1; i < 10; i++) {
		for (int j = 1; j <= i; j++) {
			cout << i << " * " << j << " = " << i * j << ' ';
		}
		cout << endl;
	}

4.3 跳转语句

1) break
  • 跳出选择结构循环结构
    • switch语句中,终止case并跳出swich
    • 循环语句中,跳出当前循环语句
    • 嵌套循环中,跳出最近内层循环结构
	for (int i = 0; i < 10; i++) {
		if (i == 5) break; // i = 5就退出循环
	}
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			if (j == i + 1) break; // 结束j的循环 继续i的循环
			cout << "* ";
		}
		cout << endl;
	}
2) continue语句 
  • 在循环语句中,跳过本次循环中余下未执行语句,执行下一次循环
	for (int i = 0; i < 10; i++) {
		if (i % 2 == 0) continue; // 奇数输出,偶数不输出
		cout << i << endl;
	}
3) goto语句
  • 可以无条件跳转语句,如果标记存在,执行到goto语句时就会跳转到标记的位置
	cout << "pharse 1" << endl;
	cout << "pharse 2" << endl;
	goto FLAG;
	cout << "pharse 3" << endl;
	cout << "pharse 4" << endl;
FLAG:
	cout << "pharse 5" << endl; // 只打印 1 2 5

五、数组

5.1 概述

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

5.2 一维数组

1) 一维数组的三种定义方式
  • 数据类型 数组名[数组长度];
  • 数据类型 数组名[数组长度] = {值1, 值2, ...};
  • 数据类型 数组名[] = {值1, 值2, ...};
	// 方式1:数据类型 数组名 [数组长度];
	int arr[5];
	arr[0] = 10;
	arr[1] = 20;
	arr[2] = 30;
	arr[3] = 40;
	arr[4] = 50;

	// 方式2
	// 初始化时没有全部填写完,会用0填补余下数据
	int arr2[5] = { 10, 20, 30, 40, 50 };
	int arr3[5] = { 10,20,30 };
	cout << arr2[4] << endl; // 50
	cout << arr3[4] << endl; // 0

	// 方式3
	int arr4[] = { 90,80,70,60,50 };

	// 访问数组元素
	cout << arr[0] << endl; // 10

	// 遍历
	for (int i = 0; i <= 4; i++) {
		cout << arr[i] << endl;
	}
2) 一维数组名
  • 统计整个数组在内存中的长度    sizeof(数组名)
  • 获取数组在内存中的首地址
	int arr[] = { 90,80,70,60,50 };

	// 通过数组名统计整个数组占用内存大小
	cout << "整个数组占用内存空间:" << sizeof(arr) << endl; // 20
	cout << "每个元素占用内存空间:" << sizeof(arr[1]) << endl; // 4
	cout << "数组中元素个数:" << sizeof(arr)/sizeof(arr[1]) << endl; // 5

	// 通过数组名查看数组首地址
	cout << "数组的首地址为:" << (int)arr << endl; // 663747800
	cout << "数组首元素的地址为:" << (int)&arr[0] << endl; // 663747800
	cout << "数组第二个元素的地址为:" << (int)&arr[1] << endl; // 663747804

	// 数组名是常量,不可以进行赋值操作
	arr = 10; // 错误
	// 五只小猪称体重 
	int pig[5];
	int max = 0;
	int index = 0;
	for (int i = 0; i < 5; i++) {
		cout << "请输入第" << i+1 << "只小猪的体重" << endl;
		cin >> pig[i];
		if (pig[i] > max) {
			max = pig[i];
			index = i+1;
		}
	}
	cout << "第" << index << "只小猪最重,体重为:" << max << endl;
	// 数组倒置
    int arr[] = { 1,2,3,4,5 };

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

	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]);i++) {
		cout << arr[i] << endl;
	}
	// 冒泡排序
    int arr[] = { 2,4,0,5,7,1,3,9,8 };
	int length = sizeof(arr) / sizeof arr[0];
	for (int i = 0; i < length-1; i++) { // 总排序轮数 = 元素个数 - 1
		for (int j = 0; j < length - i-1; j++) { // 内层循环次数 = 元素个数 - i - 1
			if (arr[j] > arr[j+1]) {
				int temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
	}

5.3 二维数组 

1) 定义方式
  • 初始化时只能省略行数,列数不能省略
	// 方式1:数据类型 数组名[行数][列数]; 数组名[行数][列数] = ...;
	int arr1[2][3]; 
	arr1[0][0] = 1;
	arr1[0][1] = 2;

	// 方式2:数据类型 数组名[行数][列数] = { {数据1, 数据2,数据3 ...}, {数据3, 数据4,数据5 ...} ... };
	int arr2[2][3] =
	{
		{1,2,3},
		{4,5,6}
	};

	// 方式3:数据类型 数组名[行数][列数] = {数据1, 数据2,数据3 ... };
	int arr3[2][3] = { 1,2,3,4,5,6 };

	// 方式4:数据类型 数组名[][列数] = {数据1, 数据2,数据3 ... };
	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;
	}
2) 二维数组名
  • 查看二维数组内存空间
	int arr[2][3] = {
		{1,2,3},
		{4,5,6}
	};
	cout << "数组arr占用的内存空间为:" << sizeof(arr) << endl; // 24 4字节*6个字符
	cout << "数组arr第一行占用的内存空间为:" << sizeof(arr[0]) << endl; // 12
	cout << "数组arr第一个元素占用的内存空间为:" << sizeof(arr[0][0]) << endl; // 4

	cout << "数组arr行数:" << sizeof(arr) / sizeof(arr[0]) << endl;
	cout << "数组arr列数:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;
  • 获取二维数组首地址
	cout << "二维数组的首地址为:" << (int)arr << endl; // 558890152
	cout << "二维数组第1行的首地址为:" << (int)arr[0] << endl; // 558890152
	cout << "二维数组第1个元素的首地址为:" << (int)&arr[0][0] << endl; // 558890152
	cout << "二维数组第2行的首地址为:" << (int)arr[1] << endl; // 558890164 与第一行差12

六、函数

6.1 概述

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

6.2 函数的定义

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

6.3 函数的调用

  • 函数调用时实参的值会传递给形参

int add(int num1, int num2) { // num1和num2并没有实际的值,形参
	int sum = num1 + num2;
	return sum;
}

int main() {
	int a = 10;
	int b = 20;
	int c = add(a, b); // a和b为实际参数,实参
	cout << c << endl;
}

 6.4 值传递

  • 做值传递时,形参发生任何改变,都不会影响实参
// 如果函数不需要返回值,声明时候可以写void,可以不写return
void swap(int num1, int num2) {
	int temp = num1;
	num1 = num2;
	num2 = temp;
}

int main() {
	int a = 10;
	int b = 20;
	swap(a, b); // a = 10, b = 20
}

6.5 函数的常见样式 

  • 无参无返
  • 有参无返
  • 无参有返
  • 有参有返
void test01() {
	cout << "无参无返" << endl;
}

void test02(int a) {
	cout << "有参无返,参数为a" << endl;
}

int test03() {
	cout << "无参有返" << endl;
	return 10;
}

int test04(int a) {
	cout << "有参有返" << endl;
	return 100 + a;
}

int main() {
	test01();
	test02(10);
	int a = test03(); // a = 10
	int b = test04(100); // b = 200;
}

6.6 函数的声明 

  • 没有函数声明的话,函数写在main函数后调用时会报错
  • 提前告诉编译器函数的存在,可以利用函数的声明
  • 函数声明可以有多次,但函数定义只能有一次
// 函数声明
int max(int a, int b);

int main() {
	int a = 10;
	int b = 20;
	cout << max(a, b) << endl;
}

// 函数定义
int max(int a, int b) {
	return a > b ? a : b;
}

6.7 函数的分文件编写 

  • 步骤:
    • 创建后缀名为.h的头文件
    • 创建后缀名为.cpp的源文件
    • 在头文件中写函数的声明,外加 #include<iostream> 和 using namespace std;
    • 在源文件中写函数的定义,外加一句 #inlude “头文件名.h"
    • 在调用项目中引用 #include “头文件名.h”

七、指针

7.1 指针的基本概念

  • 通过指针保存一个地址,间接访问内存
  • 内存编号是从0开始记录的,一般用16进制数字表示
  • 可以利用指针变量保存地址

7.2 指针变量的定义和使用

  • 指针定义:数据类型* 指针变量名;
  • 指针记录a的地址
  • 指针前加*代表解引用,找到指针指向的内存
	// 1 定义指针: 数据类型* 指针变量名
	int a = 10;
	int* p;

	// 指针记录a的地址
	p = &a;
	cout << "指针p为:" << p << endl; // 000000A53A4FFAF4
	cout << "a的地址为:" << &a << endl; // 000000A53A4FFAF4

	// 2 使用指针: 指针前加*代表解引用,找到指针指向的内存
	*p = 1000;
	cout << *p << endl; // 1000
	cout << a << endl; // 1000

7.3 指针占用内存空间

  • 在32位操作系统下:占用4个字节空间
  • 在64位操作系统下:占用8个字节空间
	int a = 10;
	int* p = &a;

	cout << sizeof(p) << endl; // 8
	cout << sizeof(int*) << endl; // 8
	cout << sizeof(float*) << endl; // 8
	cout << sizeof(double*) << endl; // 8
	cout << sizeof(char*) << endl; // 8

7.4 空指针和野指针

  • 空指针:指针变量指向内存中编号为0的内存空间
  • 用于 初始化指针变量
  • 空指针指向的内存是不可以访问的
    • 0~255之间的内存编号是被系统占用的,不可以访问
	int* p = NULL;
	// *p = 100; // 产生异常:nullptr
	//cout << *p << endl; // 对*p的操作都会引发空指针异常
  • 野指针:指针变量指向非法的内存空间
	int* p = (int*)0x1100; // 让p随便指向一个非法内存空间
	//cout << *p << endl; // 产生异常:读取访问权限冲突
  • 空指针和野指针都不是我们申请的空间,因此不要访问 

7.5 const修饰指针

1) 修饰指针:常量指针
  • const int * p = &a;
  • 指针指向可以修改,指针指向的值不可以改
	int a = 10;
	int b = 10;

    // 常量指针
	const int* p = &a; 
	p = &b; // 正确:指针指向可以改
	*p = 20; // 错误:指针指向的值不可以改

	a = 20;
	cout << *p << endl; // 20
	cout << a << endl; // 20
2) 修饰常量:指针常量 
  • int * const p = &a;
  • 指针指向不可以修改,指针指向的值可以修改
	// 指针常量
	int* const p = &a;
	*p = 20; // 正确,指向的值可以改
	p = &b; // 错误,指针指向不可以修改
3) 既修饰指针,又修饰常量
  • 指针指向和指针指向的值都不可以修改
	const int* const p = &a;
	*p = 20; // 错误
	p = &b; // 错误

7.6 指针和数组

  • 利用指针访问数组中元素
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	cout << "第一个元素为:" << arr[0] << endl;
	int* p = arr; // arr就是数组的首地址
	cout << "利用指针访问第1个元素:" << *p << endl;

	p++; // 让指针向后偏移四个字节
	cout << "利用指针访问第2个元素:" << *p << endl;

	// 利用指针遍历数组
	int* p2 = arr;
	for (int i = 0;i < 10; i++) {
		cout << *p2 << endl;
		p2++;
	}

7.7 指针和函数 

  • 值传递不会改变实参值
  • 地址传递会改变实参值
// 值传递
void swap01(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}

// 地址传递
void swap02(int* p1, int* p2) {
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

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

	swap01(a, b); // 值传递:形参a, b值交换,实参并未发生改变
	cout << "a = " << a << ", b = " << b << endl;

	swap02(&a, &b);
	cout << "a = " << a << ", b = " << b << endl; // 地址传递会改变实参
}

 7.8 指针、数组、函数

#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++) {
			if (arr[j] > arr[j + 1]) {
				int temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

void printArray(int* arr, int len) {
	for (int i = 0; i < len; i++) {
		cout << arr[i] << endl;
	}
}

int main() {
	int arr[] = { 3,6,4,5,1 };
	int len = sizeof(arr) / sizeof(arr[0]);
	bubbleSort(arr, len);
	printArray(arr, len);
}

 八、结构体

8.1 结构体的基本概念

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

8.2 结构体的定义和使用

  • struct 结构体名 {结构体成员列表};
  • 变量创建方式
    • struct 结构体名 变量名
    • struct 结构体名 变量名 = {成员1值, 成员2值 ...}
    • 定义结构体是顺便创建变量
#include<iostream>
using namespace std;
#include<string>

// 1. 创建学生数据类型 (自定义数据类型)
struct Student {
	// 成员列表
	string name;
	int age;
	double score;
}s3;

// 2. 通过学生类型创建具体学生
int main() {
	// 结构体对象变量创建时,struct关键字可以省略,结构体定义时不可省略
	// 2.1  struct Student s1
	struct Student s1;
	s1.name = "Alice";
	s1.age = 18;
	s1.score = 100;
	cout << "name = " << s1.name << ", age = " << s1.age << ", score = " << s1.score << endl;

	// 2.2  struct Student s2 = {...}
	struct Student s2 = { "Bob", 17, 97 };
	cout << "name = " << s2.name << ", age = " << s2.age << ", score = " << s2.score << endl;

	// 2.3 定义结构体时顺便创建结构体变量
	s3.name = "Cindy";
	s3.age = 20;
	s3.score = 60;
	cout << "name = " << s3.name << ", age = " << s3.age << ", score = " << s3.score << endl;
}

8.3 结构体数组 

  • 将自定义的结构体放到数组中方便维护
  • struct 结构体名 数组名[元素个数] = {{}, {}, ...};
// 1. 定义结构体
struct Student {
	string name;
	int age;
	double score;
};

int main() {
	// 初始化结构体数组
	struct Student stuArray[3] = {
		{"Alice", 18,100},
		{ "Bob", 17, 97 },
		{ "Cindy", 20, 60 }
	};

	// 修改数组值
	stuArray[2].score = 99;

	// 结构体数组遍历输出
	for (int i = 0; i < 3; i++) {
			cout << "name = " << stuArray[i].name 
				<< ", age = " << stuArray[i].age 
				<< ", score = " << stuArray[i].score << endl;
	}
}

8.4 结构体指针

  • 利用 -> 通过指针访问结构体中的成员
	// 创建学生结构体变量
	struct Student s = { "Alice", 18,100 };

	// 通过指针指向结构体变量
	Student* p = &s;

	// 通过指针访问结构体变量中的数据
	cout << "name = " << p->name
		<< ", age = " << p->age
		<< ", score = " << p->score << endl;

8.5 结构体嵌套结构体

  • 结构体中的成员可以是另一个结构体
struct Student {
	string name;
	int age;
	double score;
};

struct Teacher {
	int id;
	string name;
	int age;
	struct Student stu;
};

int main() {
	Teacher t;
	t.id = 1001;
	t.name = "Potter";
	t.age = 30;
	t.stu.name = "Ron";
	t.stu.score = 60;
	cout << "Teacher's name: " << t.name << ", Teacher's student's name: " << t.stu.name << endl;

}

8.6 结构体做函数参数

  • 将结构体作为参数向函数中传递
  • 传递方式:
    • 值传递
    • 地址传递
// 值传递
void printStu1(struct Student s) {
	s.age = 100; // 值传递不会修改主函数中实参值
	cout << "printStu1_Name: " << s.name
		<< ", age: " << s.age
		<< ", score: " << s.score << endl;
}

// 地址传递
void printStu2(struct Student* p) {
	p->age = 200; // 地址传递会修改主函数中实参值
	cout << "printStu2_Name: " << p->name
		<< ", age: " << p->age
		<< ", score: " << p->score << endl;
}

int main() {
	struct Student s;
	s.name = "Alice";
	s.age = 18;
	s.score = 100;
	cout << "main(): name = " << s.name << ", age = " << s.age << ", score = " << s.score << endl;
	printStu1(s);
	printStu2(&s);
}

8.7 结构体中const使用场景

  • const防止误操作
  • 将函数形参改为指针可以减少内存空间,而且不会复制出新副本
void printStu(const Student* p) {
	//p->age = 200; // 不允许进行写操作
	cout << "printStu2_Name: " << p->name
		<< ", age: " << p->age
		<< ", score: " << p->score << endl;
}

int main() {
	struct Student s = { "Alice",18,100 };
	printStu(&s);
}

8.8 练习案例

#include<iostream>
using namespace std;
#include<string>
#include<ctime>

struct Student {
	string sName;
	int score;
};

struct Teacher {
	string tName;
	struct Student stuArray[5];
};

void allocateSpace(struct Teacher tArray[], int len) {
	string nameSeed = "ABCDE";
	// 循环为每名老师赋值
	for (int i = 0; i < len; i++) {
		tArray[i].tName = "Teacher_";
		tArray[i].tName += nameSeed[i];
		// 循环为每名学生赋值
		for (int j = 0; j < 5; j++) {
			tArray[i].stuArray[j].sName = "Student_";
			tArray[i].stuArray[j].sName += nameSeed[j];
			// 随机数生成学生分数
			int random = rand() % 61 + 40;
			tArray[i].stuArray[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].stuArray[j].sName
				<< ",考试分数:" << tArray[i].stuArray[j].score << endl;
		}
	}
}

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

	struct Teacher tArray[3];
	int len = sizeof(tArray) / sizeof(tArray[0]);
	allocateSpace(tArray, len);
	printInfo(tArray, len);
}
#include <iostream>
using namespace std;
#include <string>

struct Hero {
	string name;
	int age;
	string gender;
};

void ageSort(struct Hero hero[], int len) {
	for (int i = 0; i < len - 1; i++) {
		for (int j = 0; j < len - i - 1;j++) {
			if (hero[j].age > hero[j + 1].age) {
				Hero tempHero = hero[j];
				hero[j] = hero[j + 1];
				hero[j + 1] = tempHero;
			}
		}
	}
}

void printList(Hero hero[], int len) {
	for (int i = 0; i < len; i++) {
		cout << "HeroName: " << hero[i].name
			<< ", HeroAge: " << hero[i].age
			<< ", HeroGender: " << hero[i].gender << endl;
	}
}

int main() {
	struct Hero heroList[5] = {
		{"LiuBei", 23, "M"},
		{"GuanYu", 22, "F"},
		{"ZhangFei",20,"M"},
		{"XiaoQiao",21,"F"},
		{"DiaoChan",19,"F"}
	};
	int len = sizeof(heroList) / sizeof(heroList[1]);
	ageSort(heroList, len);
	printList(heroList, len);

	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C++是一种通用的编程语言,它支持面向对象的编程风格,并且具有强大的系统编程能力。下面是C++的一些基础语法: 1. 注释:在C++中,注释可以用来解释代码,以便于其他人阅读和理解。单行注释使用双斜线(//),多行注释使用斜线和星号(/* ... */)。 2. 标识符:标识符是变量、函数、类等的名称。标识符由字母、数字和下划线组成,并且以字母或下划线开头。 3. 变量:在C++中,需要声明变量来存储数据。变量的声明包括类型和名称。例如,int表示整数类型,而float表示浮点数类型。 4. 数据类型:C++提供了多种数据类型,包括整型(int、short、long)、浮点型(float、double)、字符型(char)、布尔型(bool)等。 5. 运算符:C++支持各种运算符,例如算术运算符(+、-、*、/)、关系运算符(==、!=、<、>)、逻辑运算符(&&、||、!)等。 6. 控制流语句:C++提供了多种控制流语句,例如条件语句(if-else)、循环语句(for、while、do-while)、跳转语句(break、continue、return)等。 7. 函数:函数是可重用的代码块,用于执行特定的任务。函数由函数头和函数体组成,函数头包括返回类型、函数名和参数列表。 8. 类和对象:C++是面向对象的语言,支持类和对象的概念。类是一种用户定义的数据类型,用于封装数据和方法。对象是类的实例,可以通过调用对象的方法来操作数据。 这只是C++语言的一些基础语法,还有很多其他的概念和特性。如果你对某个特定的主题有更深入的兴趣,我可以为你提供更详细的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值