c/c++教程 - 总集1. c基础语法

从今天起开始C++的学习,为以后学习QT、OpenCV铺路。

本篇是C++教程中C部分的总集,为本专栏里所有 1.x部分的集合,嫌一篇篇看麻烦的直接看本篇好了。

开发环境搭建Visual Studio 2019 C++开发环境搭建

推荐教程视频https://www.bilibili.com/video/BV1et411b73Z?from=search&seid=4205594350351753444

已投币三连,非常好的视频教程,感谢up主的奉献。

 

一、代码的注释

代码注释常用于标注代码功能、记录作者和版本修改信息,方便阅读查看。

// 单行注释

/* ...
   ...
   多行注释
   ...
   ...
 */

#include <iostream>
using namespace std;

/*
   多行注释
   main 主函数
 */
int main() {
	cout << "Hello World!!" << endl;	// 单行注释,打印输出Hello world!!
	system("pause");
	return 0;
}

cout:c out,打印输出,相当于 printf。

cin:c in,检测输入,相当于 scanf。

endl:end line,换行结束,相当于键盘敲回车。

system("pause");:让程序暂停,按任意键继续。

 

二、变量

变量,字面意思,可以被改变的数据。而实际是给计算机的一段内存空间起名,方便操作这段内存的数据。

变量如果需要被使用,需要先声明变量。声明变量的格式:

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

#include <iostream>
using namespace std;

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

 

三、常量

可以被修改的数据叫做变量,不可被修改的数据叫常量。

C++定义常量有两种方法:

(1)#define宏常量:#define    常量名    常量值

通常在代码文件的上方声明。

#define  常量名  常量值

#define  Year  2020
#define  Name  "XiaoMing"

(2)const修饰变量:const    数据类型    常量名    =    常量值

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

const  int  year = 2020;

常量被修改,编译器会报错。

 

四、关键字

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

注意:给变量或者常量起名称时,不要和关键字重复,会有语法歧义。

 

五、标识符(变量、常量)命名规则

(1)标识符不能是关键字

(2)标识符只能由 数字、字母、下划线 组成。

(3)标识符的第一个字符必须是 字母或者下划线。

(4)标识符中字母区分大小写

 

可以是 inta,但不能是 int。

year2020、Status、_a、Student_66 这些都符合命名规则,但 2class、618_Day 这样以 数字开头的不行。

Age 和 age 代表的变量并不是同一个,是两个独立且互不相关的变量。

标识符命名尽量简介直观,方便自己和他人阅读。

 

六、数据类型

(1)整形

整型数据类型的区别,主要是占用空间的不同,从而导致取值范围不同,有大有小。

int最为常用。

数据类型占用空间取值范围
short(短整型)2个字节(Byte)(-2^15 ~ 2^15-1)
int(整形)四个字节(-2^31 ~ 2^31-1)
long(长整型)windows为4个字节、32位linux为4个字节、64位linux为8个字节(-2^31 ~ 2^31-1)
long long(长长整型)8个字节(-2^63 ~ 2^63-1)


(2)实型(浮点型)

表示小数。区别在于表示的有效数字范围不同。

数据类型占用空间有效数字范围
float(单精度浮点)4字节7位有效数字
double(双精度浮点)8字节15~16位有效数字

注意:有效数字范围,并不是指小数点后的数,而是整个浮点的数的数量。例如 3.14,有效数字为3。

默认的 cout  << 输出浮点类型,会显示6位有效数字。

 

(3)字符型

显示单个字符。c/c++中,字符型变量只占用一个字节。

字符型变量不是将字符放入内存中,而是将对应的ASCII编码放入内存。

char ch = 'a';

ASCII 编码对照表:https://baike.baidu.com/item/ASCII/309296?fr=aladdin

 

(4)转义字符

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

对照表:https://www.cnblogs.com/lsqbk/p/10259044.html

 

(5)字符串类型

表示一串字符。

C风格字符串:

char str1[] = "123abc";

C++风格字符串:

string str1 = "123abc";    // 需要包含头文件 #include <string>

 

(6)布尔类型

代表真或假的值。

bool的值只有两个:

true - 真,1

false - 假,0

 

(7)数据的输入

用于从键盘获取数据。

语法:cin >> 变量

 

(8)sizeof 统计内存大小

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

sizeof(数据类型/变量)
#include <iostream>
using namespace std;

int main() {

	cout << "short\t\t占用空间:" << sizeof(short) << endl;
	cout << "int\t\t占用空间:" << sizeof(int) << endl;
	cout << "long\t\t占用空间:" << sizeof(long) << endl;
	cout << "long long\t占用空间:" << sizeof(long long) << endl;

	cout << "float\t\t占用空间:" << sizeof(float) << endl;
	cout << "double\t\t占用空间:" << sizeof(double) << endl;

	cout << "char\t\t占用空间:" << sizeof(char) << endl;
	cout << "bool\t\t占用空间:" << sizeof(bool) << endl;

	system("pause");
	return 0;
}
---------------------------------------------------------------------------
short           占用空间:2
int             占用空间:4
long            占用空间:4
long long       占用空间:8
float           占用空间:4
double          占用空间:8
char            占用空间:1
bool            占用空间:1
请按任意键继续. . .

sizeof 和 strlen 区别sizeof 和 strlen 区别

 

七、运算符

运算符用于执行代码的运算。

运算符分类:

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

 

(1)算术运算符

处理四则运算。

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

 

(2)赋值运算符

将表达式的值赋给变量。

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

 

(3)比较运算符

表达式的比较,并返回一个真值或假值。

运算符术语示例结果
==相等于5 == 20
!=不等于5 != 21
<小于5 < 20
>大于5 > 21
<=小于等于5 <= 20
>=大于等于5 >= 21

注意:= 和 == 的使用区别。

 

(4)逻辑运算符

根据表达式的值返回真值或假值

运算符术语示例结果
!!a如果 a为假,则 !a为真。反之则反
&&逻辑与a && ba,b全为1时, a && b = 1。a,b任意一个为0, a && b = 0。
||逻辑或a || ba,b全为0时, a || b = 0。a,b任意一个为1, a || b = 1。

注意:& 和 &&、| 和 || 的使用区别。与 与逻辑与,或 与 逻辑或。

 

八、程序流程结构

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

顺序结构:程序按顺序执行,不发生跳转。

选择结构:依据条件是否满足,有选择的执行相应功能。

循环结构:依据条件是否满足,循环多次执行某段代码。

 

(1)选择结构

1. 使用 if语句,语法为:

if (条件) {
    /* 满足条件后,可执行括号中内容 */
    // ...
}
if (条件1) {
    /* 满足条件1后,执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
else if (条件2) {
    /* 如果条件1不满足,而条件2满足,执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
else if (条件3) {
    /* 如果条件1、条件2均不满足,而条件3满足,执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
...
...
...
if (条件1) {
    /* 满足条件1后,执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
else if (条件2) {
    /* 如果条件1不满足,而条件2满足,执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
else if (条件3) {
    /* 如果条件1、条件2均不满足,而条件3满足,执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
...
...
...
else {
    /* 如果条件1、条件2、条件3...均不满足,则执行本括号中程序 */
    // ...
    /* 执行完程序后,结束整个if结构 */
}
int main() {

	int a = 0;

	if (a < 0) {
		cout << "a小于0" << endl;
	}
	else if (a > 0) {
		cout << "a大于0" << endl;
	}
	else {
		cout << "a等于0" << endl;
	}

	system("pause");
	return 0;
}
---------------------------------------------------
a等于0
请按任意键继续. . .

if支持多重嵌套。

 

2. 三目运算符

三目运算符可实现简单的判断。语法:

表达式1 ? 表达式2 : 表达式3
// 如果表达式1为真,则执行表达式2,并返回表达式2的结果。
// 如果表达式1为假,则执行表达式3,并返回表达式3的结果。
int main() {

	int a = 10;

	a > 0 ? cout << "a大于0" << endl : cout << "a小于0" << endl;

	system("pause");
	return 0;
}
------------------------------------------------------------------
a大于0
请按任意键继续. . .

 

3. switch语句。执行多条件分支语句。语法:

switch (表达式) {
    case 结果1: 执行代码段; break;
    case 结果2: 执行代码段; break;
    case 结果3: 执行代码段; break;
    ...
    ...
    ...
    defaule: 执行代码段; break;
}
	int usr=0;
	cout << "请输入1、2、3其中一个数字" << endl;
	cin >> usr;
	switch (usr)
	{
	case 1:
		cout << "输入了1" << endl; break;
	case 2:
		cout << "输入了2" << endl; break;
	case 3:
		cout << "输入了3" << endl; break;
	default:
		cout << "不在规定范围内输入" << endl; break;
	}
--------------------------------------------------------------
请输入1、2、3其中一个数字
3
输入了3
请按任意键继续. . .

注意:别少写break,少写break代码会继续向下执行。直到再次遇到break,才会结束整个switch。

 

(2)循环结构

1. while循环语句。语法:

while (条件) {
    /* 满足条件后,执行本括号中程序 */
    // ...
    /* 执行完程序后,接着判断条件。如满足,继续循环执行本括号程序;如不满足,结束while循环 */
}

 

2. do while循环语句。语法:

do {
    // 先执行一次本括号程序
    // ...
    /* 执行完程序后,判断条件。如满足,继续循环执行本括号程序;如不满足,结束while循环 */
}while (条件)

 

3. for循环语句。满足循环条件,执行循环语句。语法:

for (表达式1; 表达式2; 表达式3)
{
    循环语句
}

for (初始化语句; 循环条件; 自增或自减)
{
    循环语句
}
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 10; j++)
		{
			cout << "j ";
		}
		cout << "i" << endl;
	}
-------------------------------------------
j j j j j j j j j j i
j j j j j j j j j j i
j j j j j j j j j j i
j j j j j j j j j j i
j j j j j j j j j j i
请按任意键继续. . .

(3)跳转语句

break语句:用于跳出选择结构或循环结构。

(注意:break只会跳出距离它最近的for、while这些循环语句,跟if没有关系)

作用:

出现在switch语句中,作用是终止case并跳出switch。

出现在循环语句中,作用是跳出当前的循环语句。

出现在嵌套循环语句中,跳出最近的内层循环语句。

	int usr=0;
	cout << "请输入1、2、3其中一个数字" << endl;
	cin >> usr;
	switch (usr)
	{
	case 1:
		cout << "输入了1" << endl; //break;
	case 2:
		cout << "输入了2" << endl; //break;
	case 3:
		cout << "输入了3" << endl; //break;
	default:
		cout << "不在规定范围内输入" << endl; //break;
	}
---------------------------------------------------------------
请输入1、2、3其中一个数字
2
输入了2
输入了3
不在规定范围内输入
请按任意键继续. . .
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 10; j++)
		{
			if (j >= 5)
				break;
			cout << "j ";
		}
		cout << "i" << endl;
	}
---------------------------------------------------------
j j j j j i
j j j j j i
j j j j j i
j j j j j i
j j j j j i
请按任意键继续. . .
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 10; j++)
		{
			cout << "j ";
		}
		cout << "i" << endl;
		break;
	}
------------------------------------------------------
j j j j j j j j j j i
请按任意键继续. . .

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

	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 10; j++)
		{
			if (j == 5 || j == 8)
			{
				continue;
			}
			cout << j;
		}
		cout << "i" << endl;
	}
--------------------------------------------------------
01234679i
01234679i
01234679i
01234679i
01234679i
请按任意键继续. . .

goto语句:可以无条件跳转语句。

(注意:少用,goto不利于梳理代码逻辑)

	cout << "执行代码段1" << endl;
	goto CODE_1;
	cout << "执行代码段2" << endl;
	cout << "执行代码段3" << endl;
	CODE_1:
	cout << "执行代码段4" << endl;
---------------------------------------------------------
执行代码段1
执行代码段4
请按任意键继续. . .

 

九、数组

数组:一个里面存放了相同类型数据元素的集合。

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

注意:数组的下标是从0开始索引。

 

(1.1)一维数组

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

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

int str1[5];
int str1[5] = { -2, -1, 0, 1, 2};
int str1[] = { -2, -1, 0, 1, 2};
	int i=0;
	int str1[5];
	str1[0] = -2;
	str1[1] = -1;
	str1[2] = 0;
	str1[3] = 1;
	str1[4] = 2;

	for (i = 0; i <5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;
----------------------------------------------------------
-2 -1 0 1 2
请按任意键继续. . .
	int i=0;
	int str1[5] = { -2, -1, 0, 1, 2 };

	for (i = 0; i <5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;
-----------------------------------------------------------
-2 -1 0 1 2
请按任意键继续. . .
	int i=0;
	int str1[] = { -2, -1, 0, 1, 2 };

	for (i = 0; i <5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;
-------------------------------------------------------
-2 -1 0 1 2
请按任意键继续. . .

 

(1.2)一维数组数组名

一维数组名称的用途:

1.可以统计整个数组在内存中的长度。

2.可以获取数组在内存中的首地址。

	int i=0;
	int str1[5] = { -2, -1, 0, 1, 2 };

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

	cout << "str1[]整个数组占用的空间:" << sizeof(str1) << endl;
	cout << "str1[0]元素占用的空间:" << sizeof(str1[0]) << endl;
	cout << "str1[]数组中元素个数:" << sizeof(str1) / sizeof(str1[0]) << endl;
	cout << "str1[]数组的内存首地址:" << str1 << endl;
	cout << "str1[0]元素的内存首地址:" << &str1[0] << endl;
	cout << "str1[1]元素的内存首地址:" << &str1[1] << endl;
----------------------------------------------------------------------------------------
-2 -1 0 1 2
str1[]整个数组占用的空间:20
str1[0]元素占用的空间:4
str1[]数组中元素个数:5
str1[]数组的内存首地址:00D8FA64
str1[0]元素的内存首地址:00D8FA64
str1[1]元素的内存首地址:00D8FA68
请按任意键继续. . .

 

(1.3)一维数组常用算法

寻找最大值:

	int i=0;
	int str1[5] = { -2, -1, 0, 1, 2 };
	int start = 0;
	int end = sizeof(str1) / sizeof(str1[0]);
	int xtemp = 0;

	for (i = 0; i < end; i++)
	{
		if (str1[i] > str1[xtemp])
		{
			xtemp = i;
		}
	}

	for (i = 0; i < 5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;
	cout << "str1[]数组中元素个数:" << end << endl;
	cout << "str1[]数组中第几个元素为最大值:" << xtemp + 1 << endl;
	cout << "最大值为:" << str1[xtemp] << endl;
--------------------------------------------------------------------------
-2 -1 0 1 2
str1[]数组中元素个数:5
str1[]数组中第几个元素为最大值:5
最大值为:2
请按任意键继续. . .

 

逆置(整个数组首位互换):

	int str1[5] = { -2, -1, 0, 1, 2 };
	int start = 0;
	int end = sizeof(str1) / sizeof(str1[0]) - 1;
	int xtemp = 0;

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

	while (start < end)
	{
		xtemp = str1[start];
		str1[start] = str1[end];
		str1[end] = xtemp;
		start++;
		end--;
	}

	for (i = 0; i < 5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;
--------------------------------------------------------------
-2 -1 0 1 2
2 1 0 -1 -2
请按任意键继续. . .

 

冒泡排序:

	int i=0,j=0;
	int str1[5] = { 8, 2, 5, 4, 6 };
	int start = 0;
	int end = sizeof(str1) / sizeof(str1[0]) - 1;
	int xtemp = 0;

	cout << "数组原始值:";
	for (i = 0; i < 5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;

	for (i = end; i > 0; i--)
	{
		for (j = 0; j < i; j++)
		{
			if (str1[j] > str1[j + 1])
			{
				xtemp = str1[j];
				str1[j] = str1[j + 1];
				str1[j + 1] = xtemp;
			}
		}
	}

	cout << "冒泡排序后:";
	for (i = 0; i < 5; i++)
	{
		cout << str1[i] << " ";
	}
	cout << endl;
----------------------------------------------------------------------
数组原始值:8 2 5 4 6
冒泡排序后:2 4 5 6 8
请按任意键继续. . .

 

(2.1)二维数组

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

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

int str1[2][3];
int str1[2][3] = { { -2, -1, 0}, { 1, 2, 3} };
int str1[2][3] = { -2, -1, 0, 1, 2, 3};
int str1[][3] = { -2, -1, 0, 1, 2, 3};
	int i=0,j=0;
	int str1[2][3] = { { -2, -1, 0}, { 1, 2, 3} };
	//int str1[2][3] = { -2, -1, 0, 1, 2, 3 };
	//int str1[][3] = { -2, -1, 0, 1, 2, 3 };

	for (i = 0; i < 2; i++)
	{
		for (j = 0; j < 3; j++)
		{
			cout << str1[i][j] << " ";
		}
		cout << endl;
	}
----------------------------------------------------------------
-2 -1 0
1 2 3
请按任意键继续. . .

 

(2.2)二维数组数组名

二维数组名称的用途:

1.统计二维数组所占内存空间。

2.获取二维数组在内存中的首地址。

	int i = 0,j = 0;
	int str1[2][3] = 
	{ 
		{ -2, -1, 0},
		{ 1, 2, 3}
	};

	for (i = 0; i < 2; i++)
	{
		for (j = 0; j < 3; j++)
		{
			cout << str1[i][j] << " ";
		}
		cout << endl;
	}

	cout << "str1[][]二维数组占用的空间:" << sizeof(str1) << endl;
	cout << "str1[][]第一行占用的空间:" << sizeof(str1[0]) << endl;
	cout << "str1[0][0]元素占用的空间:" << sizeof(str1[0][0]) << endl;
	cout << endl;
	cout << "str1[][]二维数组的行数:" << sizeof(str1) / sizeof(str1[0]) << endl;
	cout << "str1[][]二维数组的列数:" << sizeof(str1[0]) / sizeof(str1[0][0]) << endl;
	cout << "str1[][]二维数组中所有元素个数:" << sizeof(str1) / sizeof(str1[0][0]) << endl;
	cout << endl;
	cout << "str1[][]二维数组的内存首地址:" << str1 << endl;
	cout << "str1[0][0]第一行行首的内存首地址:" << &str1[0][0] << endl;
	cout << "str1[0][1]元素的内存首地址:" << &str1[0][1] << endl;
	cout << "str1[1][0]第二行行首的内存首地址:" << &str1[1][0] << endl;
-----------------------------------------------------------------------------------------
-2 -1 0
1 2 3
str1[][]二维数组占用的空间:24
str1[][]第一行占用的空间:12
str1[0][0]元素占用的空间:4

str1[][]二维数组的行数:2
str1[][]二维数组的列数:3
str1[][]二维数组中所有元素个数:6

str1[][]二维数组的内存首地址:00CFF844
str1[0][0]第一行行首的内存首地址:00CFF844
str1[0][1]元素的内存首地址:00CFF848
str1[1][0]第二行行首的内存首地址:00CFF850
请按任意键继续. . .

(2.3)二维数组应用案例

 

十、函数

(1)函数的定义

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

组成

1.返回值类型:一个函数可以返回一个值。

2.函数名:函数的名称。

3.参数列:使用函数时,传入的数据。

4.函数体语句:花括号内的代码,函数内需要执行的语句,用户代码。

5.return表达式:和返回值类型匹配。函数执行完后,返回相应数据。

 

语法

返回值类型  函数名 (参数列表)
{
    函数体语句

    return表达式
}

int add (int num1, int num2)
{
    int sum = num1 + num2;
    return sum;
}

int main(){
    /* 用户代码段 */
    // ...
    // ...
    system("pause");
    return 0;
}

 

(2)函数的调用,形参,实参

#include <iostream>
using namespace std;

// 函数定义
int add(int num1, int num2)	// int num1, int num2为形式参数,简称形参
{
	int sum = num1 + num2;
	return sum;
}

int main() {
	
	// a,b称为 实际参数,简称实参
	int a = 11, b = 23;
	// 调用add函数
	int sum = add(a, b);
	cout << "a + b = " << sum << endl;

	system("pause");
	return 0;
}
------------------------------------------------------------------------
a + b = 34
请按任意键继续. . .

 

(3)值传递

要点:实参传递给形参后,形参的改变不会影响到实测。

#include <iostream>
using namespace std;

// 函数定义
int test1(int num1, int num2)
{
	cout << "输入的 num1 = " << num1 << endl;
	cout << "输入的 num2 = " << num2 << endl;
	cout << endl;

	num1 += 10;
	num2 += 20;

	cout << "输出的 num1 = " << num1 << endl;
	cout << "输出的 num2 = " << num2 << endl;
	cout << endl;

	return 0;
}

int main() {
	
	// a,b称为 实际参数,简称实参
	int a = 11, b = 23;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << endl;

	// 调用add函数
	test1(a, b);

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << endl;

	system("pause");
	return 0;
}
----------------------------------------------------------------------
a = 11
b = 23

输入的 num1 = 11
输入的 num2 = 23

输出的 num1 = 21
输出的 num2 = 43

a = 11
b = 23

请按任意键继续. . .

 

(4)函数的常见样式

常见的函数样式有4种:

1.无参无返

2.有参无返

3.无参有返

4.有参有返

 

(5)函数的声明

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

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

#include <iostream>
using namespace std;

// 函数的声明
int test1(int num1, int num2);

int main() {
	
	// a,b称为 实际参数,简称实参
	int a = 11, b = 23;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << endl;

	// 调用add函数
	int max = test1(a, b);
	cout << "较大值 = " << max << endl;

	system("pause");
	return 0;
}

// 函数定义
int test1(int num1, int num2)
{
	return num1 > num2 ? num1 : num2;
}
------------------------------------------------------------------
a = 11
b = 23

较大值 = 23
请按任意键继续. . .

 

(6)函数的分文件编写

函数太多,不能写同一个文件中。而且功能混淆,不便于梳理、阅读、移植。

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

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

1.创建后缀名为.h的头文件

2.创建后缀名为.cpp的源文件

3.在头文件中写函数的声明

4.在源文件中写函数的定义

 

将(5)的代码分文件编写:

demo.cpp

#include <iostream>
using namespace std;
#include "swap.h"

int main() {
	
	// a,b称为 实际参数,简称实参
	int a = 11, b = 23;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << endl;

	// 调用add函数
	int max = swap(a, b);
	cout << "较大值 = " << max << endl;

	system("pause");
	return 0;
}

swap.cpp

#include "swap.h"

// 函数定义
int swap(int num1, int num2)
{
	return num1 > num2 ? num1 : num2;
}

swap.h

#include <iostream>
using namespace std; 

// 函数的声明
int swap(int num1, int num2);

 

十一、指针

(1)指针的定义和使用

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

 

(1)指针变量的定义和使用:

指针变量定义语法:

数据类型  *  变量名;
#include <iostream>
using namespace std;

int main() {
	
	int a = 13;
	int* p;

	// 指针指向数据a的地址
	p = &a;

	cout << "a的内存地址为:" << &a << endl;
	cout << "指针p为:" << p << endl;
	cout << endl;

	// 解引用
	*p = 100;

	cout << "a = " << a << endl;
	cout << "*p = " << *p << endl;

	system("pause");
	return 0;
}
------------------------------------------------------------
a的内存地址为:007FF988
指针p为:007FF988

a = 100
*p = 100
请按任意键继续. . .

 

(2)指针所占用的空间

指针也是一种数据类型,这种数据类型占用多少内存字节呢?

#include <iostream>
using namespace std;

int main() {
	
	int a = 13;
	int* p;

	// 指针指向数据a的地址
	p = &a;

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

Debug x86:------------------------------------------------------------------------
sizeof(int * ) = 4
sizeof(float * ) = 4
sizeof(double * ) = 4
sizeof(char * ) = 4
请按任意键继续. . .

Debug x64:------------------------------------------------------------------------
sizeof(int * ) = 8
sizeof(float * ) = 8
sizeof(double * ) = 8
sizeof(char * ) = 8
请按任意键继续. . .

指针所占用的内存空间大小,只跟操作系统有关。32位系统为4字节,64位系统为8字节。

指针前面的数据类型,只是表示这段指针对应的值的数据类型,并不是指针的类型。

修改程序运行在32位、64位操作系统环境,在这里勾选 x86、x64。

 

(3)空指针

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

用途:初始化指针变量。

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

#include <iostream>
using namespace std;

int main() {

	//空指针
	int* p = NULL;

	//*p = 100;
	cout << "指针p指向的内存地址: " << p << endl;
	cout << "指针p指向的值为: " << *p << endl;

	system("pause");
	return 0;
}
-------------------------------------------------------
指针p指向的内存地址: 00000000

D:\VS_C++_PRJ\demo01\Debug\demo01.exe (进程 11668)已退出,代码为 -1073741819。
按任意键关闭此窗口. . .

 

(4)野指针

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

注意:在程序中,尽量避免出现野指针。

#include <iostream>
using namespace std;

int main() {

	//野指针
	int * p = (int *)0x21003000;

	//*p = 100;
	cout << "指针p指向的内存地址: " << p << endl;
	cout << "指针p指向的值为: " << *p << endl;

	system("pause");
	return 0;
}
---------------------------------------------------------------------------
指针p指向的内存地址: 21003000

D:\VS_C++_PRJ\demo01\Debug\demo01.exe (进程 7944)已退出,代码为 -1073741819。
按任意键关闭此窗口. . .

 

(5)const修饰指针

const修饰指针有三种情况:
1.const修饰指针  ----  常量指针

2.const修饰指针  ----  指针常量

3.const既修饰指针,也修饰常量

const修饰指针  ----  常量指针:

int a = 10, b = 10;

// 常量指针
// 特点:指针的指向可以修改,但是指针指向的值不可修改
const int * p = &a;

*p = 20;    // 错误,指针指向的值不可以修改
p = &b;     // 正确,指针的指向可以修改

const修饰指针  ----  指针常量:

int a = 10, b = 10;

// 指针常量
// 特点:指针的指向不可以修改,指针指向的值可以修改
int * const p = &a;

*p = 20;    // 正确,指针指向的值可以修改
p = &b;     // 错误,指针的指向不可以修改

const既修饰指针,也修饰常量:

int a = 10, b = 10;

// 指针常量
// 特点:指针的指向、指针指向的值,都不可以修改
const int * const p = &a;

*p = 20;    // 错误,指针指向的值不可以修改
p = &b;     // 错误,指针的指向不可以修改

 

(6)指针和数组

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

int main() {

	int str1[10] = {11, 56, 82, 42, 85, 45, 89, 23, 41, 57};
	int* p = str1;

	cout << *p << endl;
	cout << *p + 1 << endl;
	cout << *(p + 1) << endl;

	p++;
	cout << *p << endl;

	system("pause");
	return 0;
}
-------------------------------------------------------------------
11
12
56
56
请按任意键继续. . .

 

(7)指针和函数(地址传递)

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

与10.3值传递,对比着看。

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

int swap(int * num1, int * num2)
{
	int xtemp = *num1;
	*num1 = *num2;
	*num2 = xtemp;

	return 0;
}

int main() {

	int a = 22;
	int b = 55;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << endl;

	swap(&a, &b);
	
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << endl;

	system("pause");
	return 0;
}
---------------------------------------------------------
a = 22
b = 55

a = 55
b = 22

请按任意键继续. . .

(8)指针、数组、函数,配合使用案例

 

十二、结构体

(1)结构体定义和使用

基本概念:结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。

结构体定义和使用:

语法:

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

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

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

代码:

/* ------------------ 1.struct  结构体名  变量名; 之后进行赋值操作 ------------------ */
struct Student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

int main() {

	//struct Student xiaoMing;
	Student xiaoMing;	// struct关键字可以省略

	xiaoMing.name = "小明";
	xiaoMing.age = 18;
	xiaoMing.score = 96;

	xiaoMing = { "小明", 18, 96 };

	cout << "姓名:" << xiaoMing.name << "  年龄:" << xiaoMing.age << "  分数:" << xiaoMing.score << endl;

	system("pause");
	return 0;
}

/* -------------- 2.struct  结构体名  变量名 = { 成员1值, 成员2值... }; -------------- */
struct Student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

int main() {

	Student xiaoMing = {"小明", 18, 96};

	cout << "姓名:" << xiaoMing.name << "  年龄:" << xiaoMing.age << "  分数:" << xiaoMing.score << endl;

	system("pause");
	return 0;
}

/* -------------------- 3.定义结构体时顺便创建变量; -------------------- */
struct Student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

int main() {

	xiaoMing.name = "小明";
	xiaoMing.age = 18;
	xiaoMing.score = 96;

	xiaoMing = { "小明", 18, 96 };

	cout << "姓名:" << xiaoMing.name << "  年龄:" << xiaoMing.age << "  分数:" << xiaoMing.score << endl;

	system("pause");
	return 0;
}
-----------------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
请按任意键继续. . .


使用 typedef 定义 struct 结构体方法https://blog.csdn.net/Mark_md/article/details/107656790

 

(2)结构体数组

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

语法:

struct  结构体名  数组名[ 元素个数 ] = { {}, {}, ... {} };
struct Student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

int main() {

	struct Student stuArray[3] =
	{
		{ "小明", 18, 96 },
		{ "小红", 20, 100 },
		{ "小亮", 21, 98 }
	};

	for (int i = 0; i < 3; i++)
	{
		cout << "姓名:" << stuArray[i].name 
			<< "  年龄:" << stuArray[i].age 
			<< "  分数:" << stuArray[i].score << endl;
	}

	system("pause");
	return 0;
}
----------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
姓名:小红  年龄:20  分数:100
姓名:小亮  年龄:21  分数:98
请按任意键继续. . .

 

(3)结构体指针

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

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

示例:

struct Student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

int main() {

	struct Student xiaoMing = { "小明", 18, 96 };
	Student* p = &xiaoMing;
	
	cout << "姓名:" << p->name
		<< "  年龄:" << p->age
		<< "  分数:" << p->score << endl;

	system("pause");
	return 0;
}
-----------------------------------------------------------------
姓名:小明  年龄:18  分数:96
请按任意键继续. . .

 

(4)结构体嵌套

结构体嵌套结构体:

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

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

示例:

struct student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

struct teacher
{
	int id;			// 职工编号
	string name;		// 教师姓名
	int age;		// 教师年龄
	struct student stu;	// 子结构体 学生
};

int main() {

	teacher wang;

	wang.id = 112374;
	wang.name = "王芳";
	wang.age = 26;
	wang.stu.name = "小明";
	wang.stu.age = 18;
	wang.stu.score = 96;
	
	cout << "教师姓名:" << wang.name
		<< "  教师年龄:" << wang.age
		<< "  教师ID号:" << wang.id << endl;
	cout << "学生姓名:" << wang.stu.name
		<< "  学生年龄:" << wang.stu.age
		<< "  学生分数:" << wang.stu.score << endl;

	system("pause");
	return 0;
}
-------------------------------------------------------------------------
教师姓名:王芳  教师年龄:26  教师ID号:112374
学生姓名:小明  学生年龄:18  学生分数:96
请按任意键继续. . .

 

(5)结构体做函数参数

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

传递方式分两种:值传递,地址传递。

值传递示例:

struct student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

void printStudent(student stu)
{
	cout << "姓名:" << stu.name
		<< "  年龄:" << stu.age
		<< "  分数:" << stu.score << endl;

	stu.name = "无";
	stu.age = 0;
	stu.score = 0;
}

int main() {

	student xiaoMing = { "小明", 18, 96 };

	printStudent(xiaoMing);

	cout << "姓名:" << xiaoMing.name
		<< "  年龄:" << xiaoMing.age
		<< "  分数:" << xiaoMing.score << endl;

	system("pause");
	return 0;
}
---------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
姓名:小明  年龄:18  分数:96
请按任意键继续. . .

地址传递示例:

struct student
{
	// 成员列表
	string name;    // 姓名
	int age;	// 年龄
	int score;	// 分数
};

void printStudent(student * stu)
{
	cout << "姓名:" << stu->name
		<< "  年龄:" << stu->age
		<< "  分数:" << stu->score << endl;

	stu->name = "无";
	stu->age = 0;
	stu->score = 0;
}

int main() {

	student xiaoMing = { "小明", 18, 96 };

	printStudent(&xiaoMing);

	cout << "姓名:" << xiaoMing.name
		<< "  年龄:" << xiaoMing.age
		<< "  分数:" << xiaoMing.score << endl;

	system("pause");
	return 0;
}
--------------------------------------------------------------------------
姓名:小明  年龄:18  分数:96
姓名:无  年龄:0  分数:0
请按任意键继续. . .

如果不想实参结构体内容,用值传递,反之用地址传递。

地址传递还可以使用数组,可实现同样功能,书写与阅读比指针更加直观。

 

(6)结构体中const使用场景

作用:用const来防止误操作

值传递会copy,会占内存空间,复制也会多花时间。所以如果可以用地址传递,可以提高执行效率。

而地址传递可能会对原始对象进行误修改,这时候就可以加 const。如果出现修改,编译器会报错

示例:

void printStudent(const student * stu)
{
	cout << "姓名:" << stu->name
		<< "  年龄:" << stu->age
		<< "  分数:" << stu->score << endl;

	stu->name = "无";    // 编译器会报错
	stu->age = 0;
	stu->score = 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值