【完结】自学C鸭鸭笔记(一)—— C++基础入门

学习资料见:https://www.bilibili.com/video/BV1et411b73Z

C++基础入门

1 初识C++

1.1 第一个C++程序

#include<iostream>
using namespace std;

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

	return 0;
}

1.2 变量

变量的定义和赋值和C语言一样
格式为:变量类型 变量名=数据

#include<iostream>
using namespace std;

int main()
{
	int a=10; //定义变量语句
	cout << "a="<< a << endl;
	system("pause");
	return 0;
}

运行结果为:
在这里插入图片描述

1.3 常量

常量定义的两种方式

  1. 宏定义 格式为:#define 常量名 常量数值
  2. 用 const 格式为:const 常量类型 常量名称=常量数值
#include<iostream>
using namespace std;

#define Day 7   //宏定义常量格式

int main()
{
	int a = 10;

	cout << "一周有" << Day << "天" << endl;  //验证定义结果

	const int month = 12; //第二种定义常量的方式

	cout << "一年总共有" << month << "个月份" << endl; //验证定义结果

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

2 数据类型

数据类型的存在意义就是可以给变量一个合理的内存空间。

2.1 整型(integer)

C++中能够表示整型的类型有一下几种:

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

2.2 sizeof关键字

作用:利用sizeof关键字可以统计数据类型所占的内存空间大小。
语法sizeof(数据类型/变量)
示例

#include<iostream>
using namespace std;

int main()
{
	int num1 = 10;

	cout << "num1占用的内存空间为" << sizeof(num1) << "个字节" << endl;
	cout << "int占用的内存空间为" << sizeof(int) << "个字节" << endl;
	//注意:sizeof(),括号里的可以是变量名,也可以是变量类型
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

2.3 实型(浮点型)

作用:用于表示小数
浮点型变量分为两种:

  1. 单精度浮点型float
  2. 双精度浮点型double
数据类型占用空间有效数字范围
float4字节7位有效数字
double8字节15~16位有效数字

示例

#include<iostream>
using namespace std;

int main()
{
	float f1 = 3.14f;  //注意:在float的数据类型上最好加一个f,要不然系统容易出问题
	double d1 = 3.14;

	cout << "f1的值为" << f1 << endl;
	cout << "d1的值为" << d1 << endl;

	float f2 = 3.1415926;
	double d2 = 3.1415926;

	cout << "f2的值为" << f2 << endl;  //注意:编译器默认保留6位有效数字
	cout << "d2的值为" << d2 << endl;

	//统计占用内存空间
	cout << "f1占用的内存空间为" << sizeof(f1) << "个字节" << endl;
	cout << "d1占用的内存空间为" << sizeof(d1) << "个字节" << endl;
	//注意:sizeof(),括号里的可以是变量名,也可以是变量类型

	//科学计数法
	float f3 = 2e3; //2*10^3
	float f4 = 2e-3; //2*10^-3

	cout << "f3的值为" << f3 << endl;
	cout << "f4的值为" << f4 << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

2.4 字符型

  1. 字符型数据类型创建方式
    语法:char 变量名='字符' 例如:char ch = 'a';
    注意:只能用单引号。
  2. 字符型变量所占内存空间大小
    char型变量只占用1个字节。
  3. 字符型变量常见错误
    • 能用双引号
    • 单引号里面只能放一个字符
  4. 字符型变量对应的ASCII码值

示例:

#include<iostream>
using namespace std;

int main()
{
	char ch1 = 'a';
	char ch2 = 'A';

	cout << "a的ASCII码值为:" << (int)ch1 << endl; //(int)ch1 为强制转换类型,将ch1转换为整型
	cout << "A的ASCII码值为:" << (int)ch2 << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

2.5 转义字符

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

转义字符含义ASCII码值(十进制)
\a警报007
\b退格(BS),将当前位置移到前一列008
\f换页(FF),将当前位置移到下页开头012
\n换行(LF),将当前位置移到下行开头010
\r回车(CR),将当前位置移到本行开头013
\t水平制表(HT)(跳到下一个TAB位置)009
\v垂直制表(VT)011
\\代表一个反斜线字符092
\’代表一个单引号字符039
\"代表一个双引号字符034
\?代表一个问号字符063

示例:

#include<iostream>
using namespace std;

int main()
{
	//在c++中有endl表示换行,但是在C语言中没有,就用\n表示
	cout << "hello world\n";

	//想要打印一个\,只有一个\是不行的,需要两个
	cout << "\\" << endl;

	//\t水平制表,一个制表符是八个字母
	cout << "aaaa\thelloworld" << endl;
	cout << "aaa\thelloworld" << endl;
	cout << "aaaaaa\thelloworld" << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

2.6 字符串

作用:用于表示一串字符
两种风格:

  1. C语言风格字符串: char 变量名[]="字符串值"
    例如:char str[]="hello world";
  2. C++语言风格字符串:string 变量名="字符串值"
    例如:string str1="hello world";
    注意:在使用string时,需要前面加头文件
#include<string>

2.7 布尔类型 bool

作用:布尔数据类型代表真的或假的值。
bool类型只占一个字节的大小
示例:

#include<iostream>
using namespace std;

int main()
{
	//创建布尔运算类型
	bool flag = true;
	cout << flag << endl;
	flag =false;
	cout << flag << endl;
	//计算布尔运算类型的大小
	cout << "布尔运算类型的大小" << sizeof(flag) << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

2.8 数据的输入

作用:从键盘中获取数据。
关键字:cin。
语法cin>>变量;
示例:

#include<iostream>
using namespace std;
#include<string>
int main()
{
	//整型
	int a;
	cout << "请输入一个整型值:" << endl;
	cin >> a;
	cout << "输入的值为:" << a << endl;
	//浮点型
	float f;
	cout << "请输入一个浮点型的数据:" << endl;
	cin >> f;
	cout << "输入的值为:" << f << endl;
	//字符型
	char ch;
	cout << "请输入一个字符型的数据:" << endl;
	cin >> ch;
	cout << "输入的值为:" << ch << endl;
	//字符串
	string str;
	cout << "请输入一个字符串的数据:" << endl;
	cin >> str;
	cout << "输入的值为:" << str << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

3 运算符

3.1 算数运算符

作用:用于四则运算。

运算符术语示例结果
+正号+33
-负号-3-3
+10+515
-10-55
*10*550
\10/52
%取模(取余)10%31
++前置递增a=2;b=++aa=3;b=3
++后置递增a=2;b=a++a=3;b=3
- -前置递减a=2;b=- -aa=1;b=1
- -后置递减a=2;b=a- -a=1;b=2

除法注意

  1. 两个整型相除,结果还是整型。
  2. 两个数只要有一个是浮点型,除法结果就是浮点型。
  3. 0不可以当作被除数

取模注意

  1. 取模运算是基于除法,因为除数不能为0。
  2. 两个小数不能进行取模运算。

3.2 赋值运算符

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

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

3.3 比较运算符

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

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

3.4 逻辑运算符

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

运算符术语示例结果
!!a若a为假,则!a为真
&&a&&b都为真,则是真(可理解为乘法)
||a||b一个是真,则是真(可理解为加法)

4 程序流程结构

C/C++支持最基本的三种结构:

  • 顺序结构
  • 选择结构
  • 循环结构

4.1 选择结构

4.1.1 if 语句

if语句的三种形式

  • 单行格式if语句
  • 多行格式if语句
  • 多条件的if语句
  1. 单行格式的if语句:if(条件){被执行的语句}
Created with Raphaël 2.2.0 开始 判断条件 执行语句 结束 yes no
  1. 多行格式的if语句:if(条件){被执行的语句1}else{被执行的语句2}
Created with Raphaël 2.2.0 开始 判断条件 执行语句1 结束 执行语句2 yes no
  1. 多条件的if语句if(条件1){被执行的语句1}else if(条件2){被执行的语句2}…else{被执行的语句n}
Created with Raphaël 2.2.0 开始 判断条件1 执行语句1 结束 判断条件2 执行语句2 判断条件3 执行语句3 执行语句4 yes no yes no yes no

嵌套if语句
if中嵌套一个if

4.1.2 三目运算符

作用:通过三目运算实现简单的判断。
语法表达式1 ? 表达式2 : 表达式3
解释
如果表达式1为真,则执行表达式2的语句
如果表达式1为假,则执行表达式3的语句
示例:

#include<iostream>
using namespace std;

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

	//以下代码的作用:将a,b中数值较大的赋给c
	c = (a > b ? a : b);
	cout << "c=" << c << endl;

	//注意:三目运算输出的是变量,下面代码说明
	(a > b ? a : b) = 100;
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

4.1.3 switch语句

swith优缺点分析:

  • 优点:结构清晰,执行效率高(跟if比)。
  • 缺点:判断的值只能是整型和字符型,不能表示区间。

4.2 循环结构

4.2.1 while循环语句

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

Created with Raphaël 2.2.0 开始 循环条件 执行循环语句 结束 yes no

示例:目的:依次打印0~20

#include<iostream>
using namespace std;

int main()
{
	//目的:依次输出0~20
	int num = 0;
	while (num < 21)
	{
		cout << num << endl;
		num++;
	}
	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

小游戏:猜数字

程序示例:

#include<iostream>
using namespace std;
#include<ctime>  //使用随机种子必备头文件

int main()
{
	srand((unsigned int)time(NULL));//添加随机数种子,利用当前系统时间生成随机数

	int num = rand() % 100 + 1;  //生成随机数,%100代表生成0~99的数字,加一生成1~100
	int time = 0;
	cout << "您给自己几次机会?" << endl;
	cin >> time;
	cout << "请您从0—100中猜一个数字" << endl;
	int val = 0;
	while (time--)
	{
		cin >> val;
		if (val > num)
		{
			cout << "大了!" << endl;
		}
		else if(val<num)
		{
			cout << "小了!" << endl;
		}
		else
		{
			cout << "恭喜您,猜对了!" << endl;
			break;
		}
	}
	if (time <= 0)
	{
		cout << "很遗憾,您的额度已用完!" << endl;
	}
	

	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

4.2.2 do…while循环语句

语法do{执行语句}while(循环条件)
注意:与while的区别是先执行一次循环,再判断是否满足条件。

Created with Raphaël 2.2.0 开始 执行循环语句 循环条件 结束 yes no
小游戏:水仙花数

解释水仙花数:每一位的三次方之和还等于数字本身。
比如:153=1^3+5^3+3^3。
问题:用do while 求出所有三位数中的水仙花数。
示例:

#include<iostream>
using namespace std;


int main()
{
	int  num = 100;
	do
	{
		int a = 0;  //个位
		int b = 0;  //十位
		int c = 0;  //百位

		a = num % 10;
		b = num / 10 % 10;
		c = num / 100 % 10;
		if (a*a*a+b*b*b+c*c*c==num)
		{
			cout << num << endl;
		}
		num++;
	} while (num < 1000);

	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

4.2.3 for循环语句

语法for(起始表达式;条件表达式;末尾循环体){循环语句;}
示例:用for循环输出0~9。

#include<iostream>
using namespace std;


int main()
{
	for (int i = 0; i < 10; i++)
	{
		cout << i << endl;
	}

	system("pause");
	return 0;

}

程序运行结果
在这里插入图片描述

小游戏:敲桌子

解释:从1数到100,遇到个位有7,十位有7或者是7的倍数的数时,输出:敲桌子。
程序示例

#include<iostream>
using namespace std;


int main()
{
	int i ;
	for (i = 1; i < 101; i++)
	{
		if (i % 10 == 7 || i / 10 == 7 || i % 7 == 0)
		{
			cout << "敲桌子" << endl;
		}
		else
		{
			cout << i << endl;
		}
	}
	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

4.2.4 嵌套循环

用嵌套循环打印一个10*10 的星图
示例

#include<iostream>
using namespace std;


int main()
{
	int i,j;
	for (i = 0 ; i < 10; i++)
	{
		for (j = 0; j < 10; j++)
		{
			cout << "* ";
		}
		cout << endl;
	}
	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

小游戏:九九乘法表

利用嵌套循环,实现打印九九乘法表。
示例

#include<iostream>
using namespace std;


int main()
{
	int i,j;
	for (i = 0 ; i < 9; i++)
	{
		for (j = 0; j < i+1; j++)
		{
			cout << j + 1 << "*" << i + 1 << "=" << (j + 1)*(i + 1)<<"\t";
		}
		cout << endl;
	}
	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

4.3 跳转语句

4.3.1 break语句

作用:用于跳出选择结构循环结构
break使用的时机:

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

4.3.2 continue语句

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

#include<iostream>
using namespace std;


int main()
{
	//目的:只输出1~100中的奇数
	int i;
	for (i = 1; i <= 100; i++)
	{
		if (i % 2 == 0)
		{
			continue; //跳过输出偶数的语句
		}
		cout << i << endl;
	}
	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

注意:continue不会使循环停止,而break会跳出整个循环。

4.3.3 goto语句

作用:可以无条件跳转语句。
语法goto 标记

示例

#include<iostream>
using namespace std;


int main()
{
	cout << "1.XXXXX" << endl;
	
	cout << "2.XXXXX" << endl;
	goto FLAG;
	cout << "3.XXXXX" << endl;

	cout << "4.XXXXX" << endl;
	FLAG: //注意:FLAG后面要加冒号
	cout << "5.XXXXX" << endl;

	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

5 数组

5.1 概述

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

5.2 一维数组

5.2.1 一维数组的定义方式

  1. 数据类型 数组名[数组长度];
  2. 数据类型 数组名[数组长度]={值1,值2,…};
    如果在初始化时没有全部赋值,会用0来填补剩余的数据。
  3. 数据类型 数组名[ ]={值1,值2,…};

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

注意2:定义数组的时候,不管采用什么方法,都需要知道数组的具体长度。

5.2.2 一维数组数组名

一名数组名称的用途

  1. 可以统计整个数组在内存中的长度。
  2. 可以获取数组在内存中的首地址。

示例:

#include<iostream>
using namespace std;


int main()
{
	//数组名的作用:
	//1、可以知道数组所占内存空间的大小:
	int arr[] = { 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 << endl << "数组在内存中的首地址为" << (int)arr << endl; //给出地址默认为十六进制,这里强制转换为十进制
	cout << "第一个元素在内存中的首地址为" << (int)&arr[0] << endl;//&为取址符
	cout << "第二个元素在内存中的首地址为" << (int)&arr[1] << endl;//&为取址符
	system("pause");
	return 0;

}

程序运行结果:
在这里插入图片描述

一维数组练习
  1. 练习案例1:五只小猪称体重
    案例描述:在一个一维数组中记录了五只小猪的体重,找出并打印最终的小猪的体重。

示例:

#include<iostream>
using namespace std;


int main()
{
	//1.得到五只小猪的体重
	int arr[] = { 200,350,430,250,340 };
	//2.依次进行比较
	int max = 0;
	int i;
	for (i = 0; i < 5; i++)
	{
		max = arr[i] > max ? arr[i] : max;
	}
	cout << "最重的小猪的体重为" << max << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

  1. 练习案例2:数组元素逆置
    案例描述:声明一个五个元素的数组,并且将元素逆置。

示例:

#include<iostream>
using namespace std;


int main()
{
	//1、声明一个数组并且打印出来
	int arr[] = { 2,5,1,3,4 };
	cout << "原数组为:" << endl;
	for (int i = 0; i < 5; i++)
	{
		cout << arr[i] << endl;
	}

	//2、对数组进行逆置
	//2.1 创建第一个元素和最后一个元素的下标
	int start = 0;
	int end = sizeof(arr) / sizeof(arr[0]) - 1;//这里可以直接使end=4,但是这写以后不管数组多么长都可以适用
	//2.2 创建一个中间变量
	int temp;
	//2.3 开始换
	while (start < end)
	{
		temp = arr[start];
		arr[start] = arr[end];
		arr[end] = temp;

		start++; end--;
	}
	//3 打印逆置之后的数组
	cout << "逆置之后的数组为" << endl;
	for (int i = 0; i < 5; i++)
	{
		cout << arr[i] << endl;
	}
	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

5.2.3 冒泡排序

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

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

在这里插入图片描述

示例:用冒泡排序将数组中的数据升序排列

#include<iostream>
using namespace std;


int main()
{
	//目的:对一组数据进行升序排序——冒泡排序
	//1.定义数组并计算长度
	int arr[] = { 4,2,8,0,5,7,1,3,9 };
	int length = sizeof(arr) / sizeof(arr[0]);

	//2.打印原数组
	cout << "原数组为:" << endl;
	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << endl;
	}
	//3.用冒泡排序法进行排序
	for (int j = 0; j < length-1; j++)  //比较的轮数是元素个数减1
	{
		for (int k = 0; k < length - j - 1; k++)  //每一轮的比较论述是(元素个数-1)-轮数(第一轮是0)
		{
			if (arr[k] > arr[k + 1])
			{
				int temp = arr[k];
				arr[k] = arr[k + 1];
				arr[k + 1] = temp;
			}
		}
	}
	//4.打印排序完之后的数组
	cout << "排序完成之后的数组为:" << endl;
	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << endl;
	}
	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

5.3 二维数组

5.3.1 二维数组的定义方式

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

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

注意:更推荐第2种定义方式,更加直观。

5.3.2 二维数组命名

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

示例:

#include<iostream>
using namespace std;


int main()
{
	//1.二维数组名称可以查看数组所占内存空间大小
	int arr[2][3]=
	{
		{1,2,3},
		{4,5,6}
	};

	cout << "二维数组所占内存空间大小为:" << sizeof(arr) << endl;
	cout << "二维数组第一行所占内存空间大小为:" << sizeof(arr[0]) << endl;
	cout << "二维数组第一个元素所占内存空间大小为:" << sizeof(arr[0][0]) << endl;

	cout << endl<< "二维数组总元素个数为" << sizeof(arr) / sizeof(arr[0][0]) << endl;
	cout << "二维数组行数为:" << sizeof(arr) / sizeof(arr[0]) << endl;
	cout << "二维数组列数为:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;

	//2.二维数组首地址
	cout << endl << "二维数组首地址为:" << (int)arr << endl;
	cout << "二维数组第一行首地址为:" << (int)arr[0] << endl;
	cout << "二维数组第二行首地址为:" << (int)arr[1] << endl;
	cout << "二维数组第一个元素的首地址为:" << (int)&arr[0][0] << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

5.3.3 二维数组应用案例

考试成绩统计:
案例描述:输出三名同学的总成绩

姓名语文数学英语
张三100100100
李四9050100
王五607080

示例:

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

int main()
{
	int score[3][3]=
	{
		{100,100,100},
		{90.50,100},
		{60,70,80}
	};
	string name[3] = { "张三","李四","王五" };

	int sum = 0;

	for (int i = 0; i < 3; i++)
	{
		sum = 0;
		for (int j = 0; j < 3; j++)
		{
			sum += score[i][j];
		}
		cout <<name[i]<< "的总成绩为:" << sum << endl;
	}

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

6 函数

6.1 概述

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

6.2 函数的定义

函数的定义主要包括一下5个步骤:

  1. 返回值类型
  2. 函数名
  3. 参数表列
  4. 函数体语句
  5. return表达式

语法

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

6.3 函数的调用

功能:使用已经定义好的函数。
语法函数名(参数)
示例:

#include<iostream>
using namespace std;

//函数的定义
int add(int num1, int num2)
{
	int sum = num1 + num2;
	return sum;
}
int main()
{
	//函数的调用
	int a = 10;
	int b = 20;

	int c = add(a, b);
	
	cout << c << endl;
	system("pause");
	return 0;
}

6.4 值传递

  • 值传递:函数调用时实参将数值传给形参。
  • 值传递时,如果形参发生改变,不会影响实参。

6.5 函数的常见样式

函数的常见样式有4种

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

6.6 函数的声明

作用:当函数写在main函数后面的时候,需要提前告诉编译器函数的存在。

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

6.7 函数的分文件编写

作用:让代码结构更加清晰。
函数分文件编写一般有四个步骤:

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

下面分步讲解:以一个交换两个数的函数swap为例

  • 1创建.h的头文件
    在这里插入图片描述

  • 2头文件中写声明
    在这里插入图片描述

  • 3创建.cpp的源文件,源文件中写函数定义
    在这里插入图片描述

  • 4主程序中调用头文件,即可使用该函数
    在这里插入图片描述

7 指针

7.1 指针的基本概念

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

7.2 指针变量的定义和使用

  • 指针变量定义语法: 数据类型 * 变量名;
  • 指针的内容是地址
  • 可以通过解引用的办法,得到指针指向地址的内容,解引用的语法:*p

示例:

#include<iostream>
using namespace std;

int main()
{
	//1.指针的定义
	int a = 10;
	int *p;

	//2.指针的使用
	//让指针指向a的地址。
	p = &a;
	cout << "变量a的地址为:" << &a << endl;
	cout << "指针p= " << p << endl;

	//通过解引用的方式来获得指针所指位置的内容
	*p = 1000;
	cout << "a的值为:" << a << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

7.3 指针所占内存空间

注意:在32位的编译环境下,指针(不管是 int *还是double * 还是char *等)都占4个字节。

在64位时,占8个字节。

7.4 空指针和野指针

空指针:指针变量中指向编号为0的空间。
用途:初始化指针变量。
注意:空指针指向的内存是不可访问的。
如:int * p = NULL;

野指针:指针变量指向非法的内存空间。
野指针是不经申请,直接让指针指向了一块内存地址。

空指针和野指针都不是我们申请的内存空间,因此不要访问。

7.5 const修饰指针

const修饰指针有三种情况

  1. const修饰指针——常量指针
  2. const修饰常量——指针常量
  3. const既修饰指针,又修饰常量
  • 常量指针:
    如:const int * p = &a;
    特点:指针的指向可以修改,但是指针指向的值不可以改。
  • 指针常量
    如:int * const p = &a;
    特点:指针的指向不可以改,但是指针指向的值可以改。
  • 既修饰指针,又修饰常量
    如:const int * const p = &a;
    特点:指针的指向和指针指向的值都不可以改。

7.6 指针和数组

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

#include<iostream>
using namespace std;

int main()
{
	//利用指针遍历数组
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int * p = arr; //指针指向数组的首地址
	for (int i = 0; i < 10; i++)
	{
		cout << *p << endl;
		p++;
	}


	
	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

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

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

#include<iostream>
using namespace std;

void swap01(int * p1, int * p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
int main()
{
	//利用指针作为函数的形参(地址传递)
	int a = 10;
	int b = 20;
	swap01(&a, &b); //因为参数是指针,所以应该给的是地址

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

程序运行结果:
在这里插入图片描述

可以对比之前的6.4 值传递,比较二者的不同。

总结:如果不想改变实参,就用值传递;如果想改变实参,就用地址传递。

7.8 指针 数组 函数

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

示例

#include<iostream>
using namespace std;

void bubbleSort(int * p, int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - 1 - i; j++)
		{
			if (p[j] > p[j + 1])
			{
				int temp = p[j];
				p[j] = p[j + 1];
				p[j + 1] = temp;
			}
			
		}
	}
}

int main()
{
	//封装一个函数,实现冒泡排序。
	int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
	int len = sizeof(arr) / sizeof(arr[0]);

	bubbleSort(arr, len);

	for (int k = 0; k < len; k++)
	{
		cout << arr[k] << endl;
	}

	system("pause");
	return 0;
}

总结:当数组名传入到函数作为参数时,被退化为指向首元素的指针

8 结构体

8.1 结构体基本概念

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

8.2 结构体定义和使用

语法struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的方式有三种:

  • struct 结构体名 变量名
  • struct 结构体名 变量名={成员1值,成员2值…}
  • 定义结构体是顺便创建变量

示例

//结构体的定义及应用
#include<iostream>
#include<string>
using namespace std;

//1.结构体的定义
struct Student  //定义一个学生结构体,包括 姓名 年龄 分数
{
	string name;

	int age;

	int score;
}s3;  //顺便定义一个变量
int main()
{
//用结构体来定义一个变量并访问
	//2.1 创建方式1 结构体名+变量名
	Student s1;
		//赋值
	s1.name = "张三"; //用.来访问结构体的每个元素
	s1.age = 18;
	s1.score = 100;

		//输出验证
	cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 分数:" << s1.score << endl;

	//2.2 创建方式2 直接赋值
	Student s2 = { "李四",19,80 };//变量要按照定义时的顺序
	//输出验证
	cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 分数:" << s2.score << endl;

	//2.3 创建方式3,在定义结构体的时候顺便创建,见上面
	Student s3 = { "王五",17,70 };
	cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 分数:" << s3.score << endl;

	system("pause");
	return 0;
}

程序运行结果
在这里插入图片描述

8.3 结构体数组

作用:将自定义的结构体放到数组中方便维护。
语法struct 结构体名 数组名[ ]={ { }, { }, … { } };

把结构体理解成一个数据类型,就是定义一个数据类型为 “结构体” 的数组。

示例

/**************************************************************
名称:结构体数组的定义及应用
***************************************************************/
#include<iostream>
#include<string>
using namespace std;

//1.结构体的定义
struct Student  //定义一个学生结构体,包括 姓名 年龄 分数
{
	string name;

	int age;

	int score;
};

int main()
{
	//2.结构体数组的定义,把结构体看做成一个数据类型
	Student arr[3]=
	{
		{"张三",20,100},
		{"李四",18,90},
		{"王五",19,80}
	};

	//3.给数组赋值,比如说想改变李四的姓名
	arr[1].name = "赵四";  //就是按照数组操作来

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


	system("pause");
	return 0;
}

程序运行结果
在这里插入图片描述

8.4 结构体指针

作用:通过指针访问结构体中的数据。

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

示例

/**************************************************************
名称:结构体指针的定义及应用
***************************************************************/
#include<iostream>
#include<string>
using namespace std;

//1.结构体的定义
struct Student  //定义一个学生结构体,包括 姓名 年龄 分数
{
	string name;

	int age;

	int score;
};

int main()
{
	//2.创建一个结构体变量
	Student s={"张三",20,100};
	

	//3.创建一个指针指向结构体变量
	Student * p = &s;

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

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

注意:如果一个指针指向了一个结构体,那么用p->age(*p).age的效果是一样的。

8.5 结构体嵌套结构体

作用:结构体中的成员可以是另一个结构体。
例如:每个老师辅导一个学员,每个老师的结构体中,都有一个学生的结构体。
示例

/**************************************************************
名称:结构体嵌套结构体
***************************************************************/
#include<iostream>
#include<string>
using namespace std;

//1.定义一个学生结构体
struct Student  //定义一个学生结构体,包括 姓名 年龄 分数
{
	string name;

	int age;

	int score;
};

//2.定义一个老师的结构体并创建一个老师变量
struct Teacher
{
	int id;
	string name;
	int age;
	Student stu; //这里在老师结构体中嵌套了学生结构体
};

int main()
{
	//3.创建一个老师结构体变量
	Teacher t1;
	

	//4.给老师结构体变量赋值
	t1.id = 20180605;
	t1.name = "老王";
	t1.age = 50;
	t1.stu.name = "小王";   //依然是通过.来访问结构体中的数据
	t1.stu.age = 18;
	t1.stu.score = 100;

	//5.通过结构体中的各个成员
	cout << " techer's id= " << t1.name << " teacher's age= " << t1.age << " teacher's name= " << t1.name 
		 <<" 老师辅导的学生的名字="<<t1.stu.name<<" student's age= "<<t1.stu.age<<" student's score= "<<t1.stu.score<< endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

8.6 结构体函数做参数

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

  • 值传递
  • 地址传递
    示例:
/**************************************************************
名称:结构体变量作为函数的参数
***************************************************************/
#include<iostream>
#include<string>
using namespace std;

//创建结构体
struct Student
{
	string name;
	int age;
	int score;
};

void PrintStudent1(Student var)  //通过值传递打印,接受变量的是形参
{
	var.age = 80;       //改变年龄
	cout << "值传递子函数:姓名: " << var.name << " 年龄: " << var.age 
		 << " 分数: " << var.score << endl;

}

void PrintStudent2(Student * p) //通过地址传递打印,接受变量的是一个指针
{
	(*p).age = 80;       //改变年龄
	cout << "值传递子函数:姓名: " << (*p).name << " 年龄: " << (*p).age
		<< " 分数: " << (*p).score << endl;
}
int main()
{
	//创建一个结构体并且赋值
	Student s;
	s.age = 18;
	s.name = "张三";
	s.score = 100;

	PrintStudent1(s);  //执行打印函数1——值传递
	cout<<"经过值传递后,main中变量:姓名: " << s.name << " 年龄: " << s.age 
		<< " 分数: " << s.score << endl;

	PrintStudent2(&s); //执行打印函数2——地址传递
	cout << "经过地址传递后,main中变量:姓名: " << s.name << " 年龄: " << s.age
		<< " 分数: " << s.score << endl;

	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

8.7 结构体中const使用场景

背景:在通过定义函数来完成某个操作时,如果通过值传递,那么就相当于把实参复制了一份给形参,当实参的数据量特别大的时候,就很占用内存空间,这时候推荐使用地址传递。

而使用地址传递,又会容易出现在子函数中把原来变量的值修改了的误操作,这时候,在定义函数变量时加一个const,就可以解决这一问题。

在这里插入图片描述

8.8 结构体案例

8.8.1 结构体案例1

案例描述:

学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下

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

示例:

/**************************************************************
名称:结构体案例1
***************************************************************/
#include<iostream>
#include<string>
using namespace std;
#include<ctime>

//1.创建学生结构体
struct Student
{
	string name;
	int score;
};

//2.创建老师的结构体
struct Teacher
{
	string name;
	Student sArray[5];
};

void DefineTeacher(Teacher tArr[], int len)
{

	for (int i = 0; i < len; i++)
	{
		string nameSeed = "ABCDE";
		tArr[i].name = "Teacher_";
		tArr[i].name += nameSeed[i];//给老师的名字为Teacher_A的形式

		for (int j = 0; j < 5; j++)
		{
			tArr[i].sArray[j].name = "Student_";
			tArr[i].sArray[j].name += nameSeed[j];
			
			tArr[i].sArray[j].score = rand() % 61 + 40;   //给每个学生一个随机值

		}
	}
}

void PrintInformation(Teacher tAr[],int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << tAr[i].name << endl;

		for (int j = 0; j < 5; j++)
		{
			cout << "\t" << tAr[i].sArray[j].name << " " << tAr[i].sArray[j].score << endl;
		}
	}
}
int main()
{
	//3.创建数组有三个老师
	Teacher tArray[3];
	int len = sizeof(tArray) / sizeof(tArray[0]);

	//4.通过定义一个函数来给老师数组来赋值,函数定义见上↑
		//保证产生随机数,添加一个随机数种子
	srand((unsigned int)time(NULL));

	DefineTeacher(tArray, len);

	//5.通过定义一个函数来实现将以上所有信息打印,函数定义见上↑
	PrintInformation(tArray, len);


	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

8.8.2 结构体案例2

案例描述:

设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。

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

		{"刘备",23,"男"},
		{"关羽",22,"男"},
		{"张飞",20,"男"},
		{"赵云",21,"男"},
		{"貂蝉",19,"女"},

示例:

/**************************************************************
名称:结构体案例2
***************************************************************/
#include<iostream>
#include<string>
using namespace std;

//1.创建结构体
struct Hero
{
	string name;
	int age;
	string gender;
};

//3.冒泡排序的子函数
void bubbleSort(Hero ar[], int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (ar[j].age > ar[j + 1].age)
			{
				Hero temp = ar[j];
				ar[j] = ar[j + 1];
				ar[j + 1] = temp;
			}
		}
	}
}

//4.打印结果的子函数
void printResult(Hero ar[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << ar[i].name << " " << ar[i].age << " " << ar[i].gender << endl;
	}
}

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

	cout << "排序前:" << endl;
	printResult(arr, len);
	//3. 冒泡排序
	bubbleSort(arr, len);

	//4.打印输出拍完序后的值
	cout << "排序后:" << endl;
	printResult(arr, len);



	system("pause");
	return 0;
}

程序运行结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dreautumn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值