目录
c++基础入门
一、C++初识
1、第一个c++程序
#include <iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
system("pause");
return 0;
}
2、变量
3、常量
c++定义常量的两种方式
(1)#define 宏常量 #define 常量名 常量值 通常在文件上方定义,表示一个常量
(2)const 修饰的变量 const 数据类型 常量名 常量值
#include <iostream>
using namespace std;
#define day 365
int main()
{
const int month = 12;
cout << "一年总共有:"<<month<<"月,也就是"<<day<<"天" << endl;
system("pause");
return 0;
}
4、关键字(标识符)
在定义变量或者常量的时候不要用关键字
5、标识符命名规则
1.标识符不能是关键字
2.标识符只能由字母、数字、下划线组成
3.第一个字符必须为下划线
4.标志符中字母区分大小写
二、数据类型
1.整型
2.sizeof关键字
3.实型(浮点型)
(1)单精度 float 4字节 7位有效数字 float f1 = 3.14f;
(2)双精度 double 8字节 15-16位有效数字 double f1 = 3.14;
(3)科学计数法 float f = 3e2;//3*10^2 float f = 3e-2; //3*0.1^2
4.字符型
char ch = 'a'; 1字节
5.转义字符
#include <iostream>
using namespace std;
//
//#define day 365
int main()
{
//换行符\n
cout << "hello world\n";
//反斜杠 \\
cout << "\\" << endl;
//水平制表符/t 前面内容+/t带来的空格总共占8个位置,作用:可以整齐输出数据
cout << "aaa\thello world" << endl;
cout << "aaaaa\thello world" << endl;
cout << "a\thello world" << endl;
cout << "aaaa\thello world" << endl;
system("pause");
return 0;
}
6.字符串型
两种风格:
1.c风格字符串 char 变量名[] = "字符串值"
2.c++风格字符串 string 变量名 = “字符串值”
#include <iostream>
using namespace std;
int main()
{
char str1[] = "hello world";
cout << str1 << endl;
string str2 = "hello world";
cout << str2 << endl;
system("pause");
return 0;
}
7.布尔类型
只有两个值: true(真)——1 false(假)——0 1字节
8.数据的输入
cin cin>>变量
#include <iostream>
using namespace std;
int main()
{
//1.整型
int a = 0;
cout << "请给整型变量a赋值:" << endl;
cin >> a;
cout << "整型变量a = " << a << endl;
//2.浮点型
float f = 3.14f;
cout << "请给浮点型变量f赋值:" << endl;
cin >> f;
cout << "浮点型变量f = " << f << endl;
//3.字符型
char ch = 'a';
cout << "请给字符型变量ch赋值:" << endl;
cin >> ch;
cout << "字符型变量ch = " << ch<< endl;
//4.字符串型
string str= "abcd";
cout << "请给字符串型变量str赋值:" << endl;
cin >> str;
cout << "字符型串变量str = " << str<< endl;
//5.布尔类型
bool flag = true;
cout << "请给布尔型变量flag赋值:" << endl;
cin >> flag;
cout << "布尔型变量flag = " << flag << endl;
system("pause");
return 0;
}
三、运算符
1.算术运算符
+、-、*、/、%(只有两个整型变量可以做取模运算)、前置递增递减、后置递增递减、前置和后置区别
#include <iostream>
using namespace std;
int main()
{
//1.前置递增
int a = 10;
++a;
cout << "a = " << a << endl;
//2.后置递增
int b = 10;
b++;
cout << "b = " << b << endl;
//2.前置和后置的区别
//前置递增 先让变量+1,然后进行表达式的运算
int a2 = 10;
int b2 = ++a2 * 10;
cout << "a2 = " << a2 << endl;
cout << "b2 = " << b2 << endl;
//后置递增 先进行表达式的运算,后让变量+1
int a3 = 10;
int b3 = a3++ * 10;
cout << "a3 = " << a3 << endl;
cout << "b3= " << b3 << endl;
system("pause");
return 0;
}
2.赋值运算符(=、+=、-=、*=、/=、%=)
3.比较运算符(==、!=、<、>、<=、>=)
4.逻辑运算符(!、&&、||)
4、程序流程结构(顺序结构、选择结构、循环结构)
4.1选择结构
4.1.1if语句
1.if语句 单行格式、多行格式、多条件的if语句、嵌套if语句
2.选择结构案例:三只小猪称体重
#include <iostream>
using namespace std;
int main()
{
//三只小猪称体重,判断谁最重
//1.创建三只小猪体重变量
int num1 = 0;
int num2 = 0;
int num3 = 0;
//2.让用户输入三只小猪的重量
cout << "请输入小猪A的体重:" << endl;
cin >> num1;
cout << "请输入小猪B的体重:" << endl;
cin >> num2;
cout << "请输入小猪C的体重:" << endl;
cin >> num3;
cout << "小猪A的体重为:" << num1 << endl;
cout << "小猪B的体重为:" << num2 << endl;
cout << "小猪C的体重为:" << num3 << endl;
//3.判断那只最重
//先判断A和B的重量
if (num1 > num2) //A比B重
{
if (num1 > num3) //A比C重
{
cout << "小猪A最重" << endl;
}
else //C比A重
{
cout << "小猪C最重" << endl;
}
}
else //B比A重
{
if (num2 > num3)
{
cout << "小猪B最重" << endl;
}
else
{
cout << "小猪C最重" << endl;
}
}
system("pause");
return 0;
}
4.1.2三目运算符
1.语法:表达式1?表达式2:表达式3
2.三目运算结果可以作为右值赋值给变量;也可以作为变量,继续被赋值
4.1.3switch语句
优点:结构清晰,执行效率高
缺点:判断时只能是整形或字符型,不可以是一个区间
#include <iostream>
using namespace std;
int main()
{
//switch语句
//给电影打分
//10-9 经典
//9-8 非常好
//6-5 一般
//5以下 烂片
//1.提示用户给电影评分
cout << "请给电影打分:" << endl;
//2.用户开始进行评分
int score = 0;
cin >> score;
cout << "您打的分数为:" << score << endl;
//3.根据用户的分数提示用户最后的结果
switch (score)
{
case 10:
cout << "您认为该电影是经典电影!" << endl;
break;
case 9:
cout << "您认为该电影是经典电影!" << endl;
break;
case 8:
cout << "您认为该电影非常好!" << endl;
break;
case 7:
cout << "您认为该电影非常好!" << endl;
break;
case 6:
cout << "您认为该电影是一般电影!" << endl;
break;
case 5:
cout << "您认为该电影是一般电影!" << endl;
break;
default:
cout << "您认为该电影是烂片!" << endl;
break;
}
system("pause");
return 0;
}
4.2循环结构
4.2.1while循环语句
案例练习:猜数字
// 添加随机数种子,作用利用当前的系统时间生成随机数,防止每次随机数都一样
srand((unsigned int)time(NULL));
//1.系统生成随机数
int num = rand() % 100+1; //rand() % 100+1,生成一个0+1-99+1的随机数
#include <iostream>
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 val = 0; //玩家输入的数据
while (1)
{
cin >> val;
//3.判断玩家的猜测
//猜错 提示猜的结果过大或者过小,重新返回第二步
if (val > num)
{
cout << "猜测过大!" << endl;
}
else if (val < num)
{
cout << "猜测过小!" << endl;
}
else //猜对,退出游戏
{
cout << "猜对了!" << endl;
break;
}
}
system("pause");
return 0;
}
4.2.2 do while循环语句
练习案例:水仙花数
#include <iostream>
using namespace std;
int main()
{
//1.先打印所有的三位数字
int num = 100;
do
{
//2.从所有的三位数中找到水仙花数
int a = 0;
int b = 0;
int c = 0;
a = num % 10; //获取num的个位
b = num / 10 % 10; //获取数字的十位
c = num / 100; //获取数字的百位
if (a*a*a + b*b*b + c*c*c == num) //如果是水仙花数,打印
{
cout << num << endl;
}
num++;
} while (num < 1000);
system("pause");
return 0;
}
4.2.3for循环语句
案例:敲桌子
#include <iostream>
using namespace std;
int main()
{
//敲桌子
//1.先输出1-100数字
for (int i = 1; i <= 100; i++)
{
//2.从100个数字中找到特殊数字,打印“敲桌子”
//如果是7的倍数、个位有7或者十位有7,打印敲桌子
if (i%7 == 0 || i%10 == 7 ||i /10 == 7)
{
cout << "敲桌子" << endl;
}
else
{
cout << i << endl;
}
}
system("pause");
return 0;
}
4.2.4嵌套循环
案例:乘法口诀表
#include <iostream>
using namespace std;
int main()
{
//乘法口诀表
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
cout << j << "*" << i << "=" << j * i<<" ";
}
cout << endl;
}
system("pause");
return 0;
}
4.3跳转语句
4.3.1break语句
break使用的时机:
1.出现在switch条件语句中,作用是终止case并跳出switch
2.出现在循环语句中,作用是跳出当前的循环语句
3.出现在嵌套循环中,跳出最近的内层循环语句
#include <iostream>
using namespace std;
int main()
{
//break的使用时机
//1.出现在switch语句中
/*cout << "请选择副本的难度:" << endl;
cout << "1.普通" << endl;
cout <<"2.中等"<<endl;
cout <<"3.困难" << endl;
int select = 0;
cin >> select;
switch (select)
{
case 1:
cout << "您选择的是普通难度" << endl;
break;
case 2:
cout << "您选择的是中等难度" << endl;
break;
case 3:
cout << "您选择的是困难难度" << endl;
break;
default:
break;
}*/
//2.出现在循环语句中
//for (int i = 0; i < 10; i++)
//{
// //如果i= =5,退出循环,不再打印
// if (i == 5)
// {
// break;
// }
// cout << i << endl;
//}
//3.出现在嵌套循环语句中
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (j == 5)
{
break;
}
cout << "*" ;
}
cout << endl;
}
system("pause");
return 0;
}
4.3.2continue语句
在循环语句中,跳过本次循环中尚未执行的语句,继续执行下一次循环
4.3.3goto语句
语法:goto标记;
#include <iostream>
using namespace std;
int main()
{
//goto语句
cout << "1.XXXXXXXXX" << endl;
cout << "2.XXXXXXXXX" << endl;
cout << "3.XXXXXXXXX" << endl;
goto FLAG;
cout << "4.XXXXXXXXX" << endl;
cout << "5.XXXXXXXXX" << endl;
FLAG:
cout << "6.XXXXXXXXX" << endl;
system("pause");
return 0;
}
5.数组
5.1一维数组
5.1.1一维数组定义方式
一维数组定义的三种方式:
1.数组类型 数组名[数组长度];
2.数组类型 数组名[数组长度] = {值1,值2,值3......};
3.数组类型 数组名[ ] = {值1,值2,值3......}
5.1.2一维数组的数组名
一维数组名称的用途:
1.可以统计整个数组在内存中的长度,单位为字节
2.可以获取数组在内存中的首地址
#include <iostream>
using namespace std;
int main()
{
//一维数组名称用途
//1.可以统计整个数组在内存中的长度 sizeof(数组名称)
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 << "数组的首地址为:" << arr << endl;
cout << "数组中第一个元素的地址为:" << &arr[0] << endl;
//数组名是常量,因此不可以赋值
system("pause");
return 0;
}
5.1.3一维数组案例(五只小猪称体重、数组元素逆置)
1.五只小猪称体重
#include <iostream>
using namespace std;
int main()
{
//1.创建五只小猪体重的数组
int arr[5] = { 300,350,200,400,250 };
//2.从数组中找到最大值
int max = 0;//先认定一个最大值为0
for (int i = 0; i < 5; i++)
{
if (arr[i] > max)
max = arr[i];
}
//3.打印最大值
cout << "最重的小猪体重为:" << max << endl;
system("pause");
return 0;
}
2.数组元素逆置
#include <iostream>
using namespace std;
int main()
{
//实现数组元素的逆置
//1.创建数组
int arr[5] = { 1,3,2,5,4 };
cout<< "数组逆置前:" << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << endl;
}
//2.实现逆置
//2.1记录起始下标位置
//2.2记录结束下标位置
//2.3起始下标与结束下标的元素互换
//2.4起始位置++ 结束位置--
//2.5循环执行2.1的操作,直到起始位置>=结束位置
int start = 0; //起始下标
int end = sizeof(arr) / sizeof(arr[0])-1; //结束下标
while (start < end)
{
//元素互换
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
//下标更新
start++;
end--;
}
//3、打印逆置后的数组
cout << "数组元素逆置后:" << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << endl;
}
system("pause");
return 0;
}
5.1.4冒泡排序
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个;
2.对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值;
3.重复以上步骤,每次比较次数-1,直到不需要比较;
示例:将数组{4,2,8,0,5,7,1,3,9}进行升序排序
#include <iostream>
using namespace std;
int main()
{
//利用冒泡排序实现升序排列
int arr[9] = { 4,2,8,0,5,7,1,3,9 };
cout << "排序前:" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//开始冒泡排序
//总共排序轮数 = 元素个数-1
for (int i = 0; i < 9 - 1; i++)
{
//内层循环对比 次数 = 元素个数-当前轮数-1
for (int j = 0; j < 9 - i - 1; j++)
{
//如果第一个数字比第二个数字大,交换两个数字
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
//排序后结果
cout << "排序后:" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
5.2二维数组
5.2.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.数据类型 数组名[行数][列数];
int arr[2][3];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j]<<" ";
}
cout << endl;
}
//2.数据类型 数组名[行数][列数] = { {数据1,数据2},{数据3,数据4} };
int arr1[2][3] = { {1,2,3} ,{4,5,6} };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr1[i][j] << " ";
}
cout << endl;
}
//3.数据类型 数组名[行数][列数] = { 数据1,数据2,数据3,数据4 };
int arr2[2][3] = { 1,2,3,4,5,6 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr2[i][j] << " ";
}
cout << endl;
}
//4.数据类型 数组名[][列数] = { 数据1,数据2,数据3,数据4 };
int arr3[][3] = { 1,2,3,4,5,6 };
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr3[i][j] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
5.2.2二维数组数组名
查看二维数组所占内存空间
获取二维数组首地址
5.2.3二维数组应用举例
#include <iostream>
using namespace std;
int main()
{
//二维数组案例—考试成绩统计
//1.创建二维数组
int scores[3][3] =
{ {100,100,100},
{90,50,100},
{60,70,80}
};
string names[3] = { "张三","李四","王五" };
//2.统计每个人分数总和
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += scores[i][j];
}
cout << names[i]<< "的总分为:" << sum << endl;
}
system("pause");
return 0;
}
6.函数
6.1函数的定义
函数的定义一般主要有5个步骤:
1.返回值类型
2.函数名
3.参数列表
4.函数体语句
5.return表达式
语法:
返回值类型 函数名(参数列表)
{
函数体语句;
return 表达式;
}
6.2函数的调用
6.3值传递
所谓值传递,就是函数调用时实参将数值传入给形参
值传递时,如果形参发生改变,并不会影响实参
#include <iostream>
using namespace std;
//值传递
//定义一个函数,实现两个数字进行交换
//如果函数不需要返回值,声明的时候可以写void
void swap(int num1, int num2)
{
cout << "交换前:" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交换后:" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
return; //返回值不需要的时候,可以不写return
}
int main()
{
int a = 10;
int b = 20;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
//值传递时,如果形参发生改变,并不会影响实参
swap(a, b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}
6.4函数的常见样式
常见的函数样式有四种:1.有参无返 2.无参无返 3.无参有返 4.有参有返
#include <iostream>
using namespace std;
//函数常见样式
//1.无参无返
void test01()
{
cout << "this is test01" << endl;
}
//2.有参无返
void test02(int a)
{
cout << "this is test 02 a = " << a << endl;
return;
}
//3.无参有返
int test03()
{
cout << "this is test 03" << endl;
return 1000;
}
//4.有参有返
int test04(int a)
{
cout << "this is test04 a = " << a << endl;
return a;
}
int main()
{
//无参无返函数调用
test01();
//有参无返函数调用
test02(10);
//无参有返函数调用
int num1 = test03();
cout << "num1 = " << num1 << endl;
//有参有返函数调用
int num2 = test04(10000);
cout << "num2 = " << num2 << endl;
system("pause");
return 0;
}
6.5函数的声明
#include <iostream>
using namespace std;
//函数声明
//比较函数,两个整型数字进行比较,返回较大的值
//函数的声明。提前告诉函数的存在。
int max(int a, int b);
int main(void)
{
int a = 10;
int b = 20;
int result = max(a, b);
cout << "最大值是:" << result << endl;
system("pause");
return 0;
}
int max(int a, int b)
{
return a > b ? a : b;
}
6.6函数的分文件编写
四个步骤:
1.创建后缀名为.h的头文件
2.创建后缀名为.cpp的源文件
3.在头文件中写函数的声明
4.在源文件中写函数的定义
7.指针
7.1指针的基本概念
指针的作用:可以通过指针间接访问内存
可以利用指针变量记录保存地址
7.2 指针变量的定义和使用
语法:数据类型 *数据名;
#include<iostream>
using namespace std;
int main(void)
{
//1.定义指针
int a = 10;
//指针定义语法 数据类型 *指针变量名;
int* p;
//让指针记录变量a的地址
p = &a;
cout << "a的地址为:" << p << endl;
//2.使用指针
//可以使用通过解引用的方式找到指针指向的内存
//指针前加*代表解应用,找到指针指向的内存中的数据
*p = 1000;
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
system("pause");
return 0;
}
7.3指针所占内存空间
在32位操作系统下,占用4个字节空间,64位下占8个字节空间。不管是什么数据类型。
7.4空指针和野指针
空指针:指针变量指向内存中编号为0的空间。
用途:初始化指针变量
注意:空指针指向的内存是不可以访问的
#include<iostream>
using namespace std;
int main(void)
{
//空指针
//1.空指针用于给指针变量进行初始化
int* p = NULL;
//2.空指针是不可以进行访问的
//0~255之间的内存编号是系统占用的,因此不可以访问
cout << *p << endl;
system("pause");
return 0;
}
程序崩溃
野指针:指针变量指向非法的内存空间 ,在程序中,应该避免出现野指针。
#include<iostream>
using namespace std;
int main(void)
{
//野指针
int* p = (int *)0x1100;
cout << *p << endl;
system("pause");
return 0;
}
程序崩溃
总结:空指针和野指针都不是我们申请的空间,因此不要访问。
7.5const修饰指针
const修饰指针有三种情况:
1.const修饰指针——常量指针
特点:指针的指向可以修改,但是指针指向的值不可以改。
const int *p = &a;
*p = 20; 错误,指针指向的值不可以改
p = &b;正确,指针指向可以改
2.const修饰常量——指针常量
特点:指针的指向不可以修改,但是指针指向的值可以改。
int *const p = &a;
*p = 20; 正确,指针指向的值可以改
p = &b;错误,指针指向不可以改
3.const既修饰指针又修饰常量
特点:指针的指向和指针指向的值都不可以改。
const int* const p = &a;
*p = 20; 错误,指针指向的值不可以改
p = &b;错误,指针指向不可以改
#include<iostream>
using namespace std;
int main(void)
{
//1.const修饰指针 常量指针
int a = 10;
int b = 10;
const int* p = &a;
//指针指向的值不可以改,指针的指向可以改
//*p = 20;
p = &b;
//2.const修饰常量 指针常量
//指针的指向不可以改,指针指向的值可以改
int* const p2 = &a;
*p2 = 100;//正确的
//p2 = &b;错误,指针的指向不可以改
//3.const修饰指针和常量
const int* const p3 = &a;
//指针的指向和指针指向的值都不可以改
//*p3 = 100;
//p = &b;
}
技巧:看const右侧紧跟的是指针还是常量,是指针就是常量指针,是常量就是指针常量。
看完书后补充:
- 对于int age = 39;const int *pt = &age;(常量指针)pt的声明并不意味着它指向的值实际上就是一个常量,而只意味着对于pt而言,这个值是常量。例如, *pt = 20; //❌但age=20;//✔因为age不是const变量。
7.6指针和数组
作用:利用指针访问数组中元素。
#include<iostream>
using namespace std;
int main(void)
{
//指针和数组
//利用指针访问数组中的元素
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;//arr就是数组的首地址
cout << "利用指针访问第一个元素:" << *p << endl;
p++;//p++然指针向后偏移4个字节
cout << "利用指针访问第二个元素:" << *p << endl;
cout << "利用指针遍历数组:"<<endl;
int* p2 = arr;
for (int i = 0; i < 10; i++)
{
cout << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
7.7指针和函数
作用:利用指针作为函数参数,可以修改实参的值
#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(void)
{
//指针和函数
//1.值传递
int a = 10;
int b = 20;
swap01(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//2.地址传递
//如果是地址传递,可以修改实参
swap02(&a, &b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
7.8指针、数组、函数
案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序。
例如,数组int arr[10] = {4,3,6,9,1,2,10,8,7,5}
#include<iostream>
using namespace std;
//冒泡排序函数 参数1 数组的首地址 参数2 数组的长度
void bubbleSort(int* arr,int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j > j+1,交换两个值
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return;
}
//打印数组
void printArray(int *arr,int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
int main(void)
{
//1.创建一个数组
int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
int len = sizeof(arr) / sizeof(arr[0]);
//2.创建一个函数实现冒泡排序
bubbleSort(arr, len);
//3.打印排序后的数组
printArray(arr, len);
system("pause");
return 0;
}
8.结构体
8.1结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
8.2结构体定义和使用
语法:struct 结构体名 {结构体成员列表};
(struct关键字创建的时候可以省略,定义的时候不可以省略)
通过结构体创建变量的方式有三种:
1.struct 结构体名 变量名;
2.struct 结构体名 变量名 = {成员1值,成员2值......};
3.定义结构体时,顺便创建变量;
#include<iostream>
using namespace std;
//1.创建一个学生的数据类型:学生包括(姓名,年龄,分数)
//自定义数据类型,一些类型集合组成的的一个类型
//语法 struct 类型名称{成员列表};
struct student //struct不可以省略
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3;
int main(void)
{
//2.通过学生类型创建具体学生
//2.1 struct student s1;
struct student s1; //struct可以省略
//给s1 属性赋值,通过.访问结构体变量中的属性
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout << "姓名: " << s1.name << endl;
cout << "年龄: " << s1.age<< endl;
cout << "分数: " << s1.score << endl;
//2.2 struct student s2 = {...};
struct student s2 = { "李四",19,82 };
cout << "姓名: " << s2.name << endl;
cout << "年龄: " << s2.age << endl;
cout << "分数: " << s2.score << endl;
//2.3 在定义结构体时,顺便创建结构体变量
struct student s3 = { "王五",20,60 };
cout << "姓名: " << s3.name << endl;
cout << "年龄: " << s3.age << endl;
cout << "分数: " << s3.score << endl;
system("pause");
return 0;
}
8.3结构体数组
作用:将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名 元素个数{{},{},{}....{}};
#include<iostream>
using namespace std;
// 结构体数组
//1.定义一个结构体
struct student
{
string name;
int age;
int score;
};
int main(void)
{
//2.创建结构体数组并赋值
struct student stuArray[3]
{
{"张三",18,100},
{"李四",19,80},
{"王五",20,60}
};
//3.给结构体数组中的元素赋值
stuArray[2].name = "赵六";
stuArray[2].age = 22;
stuArray[2].score = 90;
//4.遍历输出结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名 " << stuArray[i].name << " 年龄 " << stuArray[i].age << " 分数 " << stuArray[i].score << endl;
}
system("pause");
return 0;
}
8.4结构体指针
作用:通过指针访问结构体中的成员
利用操作符->可以通过结构体指针访问结构体属性
#include<iostream>
using namespace std;
// 结构体指针
//1.定义一个结构体
struct student
{
string name;
int age;
int score;
};
int main(void)
{
//2.创建结构体变量
struct student s ={"张三",18,100};
//3.通过指针指向结构体变量
struct student* p = &s;
//4.通过指针访问结构体变量的数据
cout << "姓名: " << p->name << " 年龄: " << p->age << " 分数: " << p->score << endl;
system("pause");
return 0;
}
8.5结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
#include<iostream> using namespace std; // 结构体嵌套结构体 //定义学生结构体 struct student { string name; int age; int score; }; //定义老师结构体 struct teacher { int id; //教师编号 string name; //tercher name int age; //teacher age struct student stu; //student }; int main(void) { //创建一个老师 teacher t; t.id = 10000; t.name = "老王"; t.age = 50; t.stu = { "张三",19,100 }; cout << "老师的姓名:" << t.id << " 老师编号:" << t.id << " 老师年龄:" << t.age<<endl << "老师辅导的学生为:" << t.stu.name << " 学生的年龄为:" << t.stu.age << " 学生的考试分数为:" << t.stu.score << endl; system("pause"); return 0; }
8.6结构体做函数参数
作用:将结构体作为参数向函数中传递
传递的方式有两种:
1.值传递
2.地址传递
#include<iostream>
using namespace std;
//定义结构体
struct student
{
string name;
int age;
int score;
};
//打印学生信息的函数
//1.值传递
void printstudent1(struct student s)
{
s.age = 100;
cout<<"值传递子函数中:"<<endl <<"姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.age << endl;
}
//2.地址传递
void printstudent2(struct student *p)
{
p->age = 100;
cout << "地址传递子函数中:" << endl << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" <<p->age << endl;
}
int main(void)
{
//结构体做函数参数
//将学生传入一个参数中,打印学生身上的所有属性
//创建一个结构体变量
struct student s = { "张三",20,90 };
cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.age << endl;
printstudent1(s);
cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.age << endl;
cout << "******************************************" << endl;
printstudent2(&s);
cout << "姓名:" << s.name << " 年龄:" << s.age << " 分数:" << s.age << endl;
system("pause");
return 0;
}
总结:如果不想修改主函数中的数据,用值传递。反之,用地址传递。
8.7结构体中const使用场景
作用:用const来防止误操作
#include<iostream>
using namespace std;
//const的使用场景
struct student
{
string name;
int age;
int score;
};
//将函数的形参改为指针,可以减少内存空间,而且不会复制新的副本出来,一个指针只占4个字节
void printstudent(const student *s)
{
s->age = 150; //错误,因为加入const之后一旦有修改的操作就会报错,可以防止我们的误操作
cout << "姓名:" << s->name << " 年龄:" << s->age << " 分数:" << s->score << endl;
}
int main(void)
{
//创建结构体变量
struct student s = { "张三",15,70};
//通过函数来打印结构体变量的信息
printstudent(s);
system("pause");
return 0;
}
8.8结构体案例
8.8.1案例1
案例描述:学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员,学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值,最终打印出老师数据以及老师所带学生的数据。
#include<iostream>
#include <ctime>
using namespace std;
//学生的结构体
struct student
{
string sname;
int score;
};
//老师的结构体
struct Teacher
{
//姓名
string tName;
//学生数组
struct student sArray[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].sArray[j].sname = "Student_";
tArray[i].sArray[j].sname += nameSeed[j];
int random = rand() % 61 + 40; //0+40~60+40
tArray[i].sArray[j].score = random;
}
}
}
//打印所有信息
void printInfo(struct Teacher tArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "老师姓名:" << tArray[i].tName << endl;
for (int j = 0; j < 5; j++)
{
cout << "\t学生姓名:" << tArray[i].sArray[j].sname<<
" 考试分数:" << tArray[i].sArray[j].score << endl;
}
}
}
int main(void)
{
//随机数种子
srand((unsigned int)time(NULL));
//1.创建3名老师的数组
struct Teacher tArray[3];
//2.通过函数给3名老师的信息赋值,并给老师带的学生的信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);
allocateSpace(tArray, len);
//3.打印所有老师以及所带的学生的信息
printInfo(tArray, len);
system("pause");
return 0;
}
8.8.2案例2
案例描述:设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排列,最终打印最后的结果。
五名英雄信息:{“刘备”,23,“男”}{“关羽”,22,“男”}{“张飞”,“20”,“男”}{“赵云”,21,“男”}{“貂蝉”,19,“女”}
#include<iostream>
#include <ctime>
using namespace std;
//1.设计一个英雄的结构体
struct Hero
{
string name;
int age;
string sex;
};
//冒泡排序实现年龄的升序排列
void bubbleSort(struct Hero heroArray[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j下标元素年龄大于j+1的元素年龄,就交换这两个元素
if (heroArray[j].age > heroArray[j + 1].age)
{
struct Hero temp = heroArray[j];
heroArray[j] = heroArray[j + 1];
heroArray[j+1] = temp;
}
}
}
}
//打印排序后数组信息
void printHero(struct Hero heroArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "姓名: " << heroArray[i].name << " 年龄:"
<< heroArray[i].age << " 性别: " << heroArray[i].sex << endl;
}
}
int main(void)
{
//2.创建一个数组存放5名英雄
struct Hero heroArray[5] =
{
{"刘备",23,"男" },
{"关羽",22,"男"} ,
{"张飞",20,"男"},
{"赵云",21,"男"} ,
{"貂蝉",19,"女"}
};
int len = sizeof(heroArray) / sizeof(heroArray[0]);
for (int i = 0; i < len; i++)
{
cout << "姓名: " << heroArray[i].name << " 年龄:"
<< heroArray[i].age << " 性别: " << heroArray[i].sex << endl;
}
//3.对数组进行排序,按照年龄进行升序排列
bubbleSort(heroArray, len);
cout << "排序后的打印为:" << endl;
//4.将排序后的结果打印输出
printHero(heroArray, len);
system("pause");
return 0;
}
万能头文件:#include<bits/stdc++.h>