前言
配套视频:B站黑马程序员
C++从入门到精通https://www.bilibili.com/video/BV1et411b73Z
为方便大家学习,在此发布C++基础入门部分配套讲义,原作者为黑马程序
《基础笔记一》
本阶段主要是初识C++的编程语法规范,主要难点内容为:数组、函数、指针、结构体。
1 C++初识
1.1 变量
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;
示例:
#include<iostream>
using namespace std;
int main()
{
cout << "hello c++" << endl; //打印hello c++ 并换一行
int a = 10; //创建变量
cout << "a=" << a << endl;
system("pause");
return 0;
}
hello c++
a=10
请按任意键继续. . .
注意:C++在创建变量时,必须给变量一个初始值,否则会报错
1.2 常量
作用:用于记录程序中不可更改的数据
C++定义常量两种方式
#define 宏常量: #define 常量名 常量值
通常在文件上方定义,表示一个常量
const修饰的变量 const 数据类型 常量名 = 常量值
通常在变量定义前加关键字const,修饰该变量为常量,不可修改
示例
#include<iostream>
using namespace std;
//宏常量
#define Day 7
int main()
{
cout << "一周总共有:" << Day << "天" << endl;
const int month = 12; //const修饰的变量,在之后就不可以在修改值,只能为常量了
cout << "一年总共有:" << month << "月份" << endl;
system("pause");
return 0;
}
一周总共有:7天
一年总共有:12月份
请按任意键继续. . .
1.3 关键字
在定义变量或者常量时候,不要用关键字
C++关键字如下:
asm | do | if | return | typedef |
---|---|---|---|---|
auto | double | inline | short | typeid |
bool | dynamic_cast | int | signed | typename |
break | else | long | sizeof | union |
case | enum | mutable | static | unsigned |
catch | explicit | namespace | static_cast | using |
char | export | new | struct | virtual |
class | extern | operator | switch | void |
const | false | private | template | volatile |
const_cast | float | protected | this | wchar_t |
continue | for | public | throw | while |
default | friend | register | true | delete |
goto | reinterpret_cast | try |
示例
#include<iostream>
using namespace std;
int main()
{
/*
标识符不可以是关键字
标识符由 字母、数字、下划线组成
标识符开头不能为数字
*/
int num1 = 1, num2 = 2,sum;
sum = num1 + num2;
cout << sum << endl;
system("pause");
return 0;
}
3
请按任意键继续. . .
2 数据类型
C++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
2.1 整型
short短整型 2字节
int整形 4字节
long长整形 4字节
long long 长长整型 8字节
2.2 浮点型(实型)
单精度float 4字节
双精度double 8字节
2.3 字符型
注意1:在显示字符型变量时,用单引号将字符括起来,不要用双引号
注意2:单引号内只能有一个字符,不可以是字符串
char ch = ‘a’; 1字节
2.4 字符串型
作用:用于表示一串字符
两种风格
C风格字符串: char 变量名[] = “字符串值”
C++风格字符串: string 变量名 = “字符串值”
2.5 转义字符
**作用:**用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有:\n \ \t
| | |
\n | 换行(LF) ,将当前位置移到下一行开头 |
---|---|
\t | 水平制表(HT) (跳到下一个TAB位置) |
\v | 垂直制表(VT) |
\\ | 代表一个反斜线字符"" |
2.6 布尔类型 bool
**作用:**布尔数据类型代表真或假的值
bool类型只有两个值:
true — 真(本质是1)
false — 假(本质是0)
bool类型占1个字节大小
2.7 sizeof关键字
**作用:**利用sizeof关键字可以统计数据类型所占内存大小
语法: sizeof( 数据类型 / 变量)
2.8 数据的输入
作用:用于从键盘获取数据
**关键字:**cin
语法: cin >> 变量
3 运算符
**作用:**用于执行代码的运算
本章我们主要讲解以下几类运算符:
运算符类型 | 作用 |
---|---|
算术运算符 | 用于处理四则运算 |
赋值运算符 | 用于将表达式的值赋给变量 |
比较运算符 | 用于表达式的比较,并返回一个真值或假值 |
逻辑运算符 | 用于根据表达式的值返回真值或假值 |
3.1 算术运算符
作用:用于处理四则运算
算术运算符包括以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | -3 | -3 |
+ | 加 | 10 + 5 | 15 |
- | 减 | 10 - 5 | 5 |
* | 乘 | 10 * 5 | 50 |
/ | 除 | 10 / 5 | 2 |
% | 取模(取余) | 10 % 3 | 1 |
++ | 前置递增 | a=2; b=++a; | a=3; b=3; |
++ | 后置递增 | a=2; b=a++; | a=3; b=2; |
- | 前置递减 | a=2; b=-a; | a=1; b=1; |
- | 后置递减 | a=2; b=a-; | a=1; b=2; |
总结:
在除法运算中,除数不能为0
只有整型变量可以进行取模运算
前置递增先对变量进行++,再计算表达式,后置递增相反
5 数组
5.1 概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
**特点1:**数组中的每个数据元素都是相同的数据类型
**特点2:**数组是由连续的内存位置组成的
5.2 一维数组
5.2.1 一维数组定义方式
一维数组定义的三种方式:
数据类型 数组名[ 数组长度 ];
数据类型 数组名[ 数组长度 ] = { 值1,值2 …}; //没有全部填写完时,会用0来填补剩余数据
数据类型 数组名[ ] = { 值1,值2 …};
示例
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//int arr[5]; //第一种表达方式
//arr[0] = 10;
//arr[1] = 20;
//arr[2] = 30;
//arr[3] = 40;
//cout << arr[3] << endl;
int arr2[] = { 10,20,30,40 }; //第二种表达方式
for (int i = 0; i < 4; i++)
{
cout << arr2[i] << endl;
}
system("pause"); //暂停结果显示
return 0;
}
10
20
30
40
请按任意键继续. . .
5.2.2 一维数组数组名
一维数组名称的用途:
可以统计整个数组在内存中的长度
可以获取数组在内存中的首地址
示例:
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//可以统计整个数组在内存中的长度
//可以获取在内存中的首地址
int arr1[9] = {13,34,54,23,454,6,6,776,444};
cout << sizeof(arr1) << endl; //9个数,每个数占用4个字节
cout << sizeof(arr1) / sizeof(arr1[0]) << endl; //统计数组的元素个数,总长度/索引为0的长度
cout << arr1 << endl; //16进制表示地址位置
cout << "数组中第一个元素地址为: " << &arr1[0] << endl;
cout << (int)arr1 << endl; //10进制表示地址位置
system("pause"); //暂停结果显示
return 0;
}
36
9
0039FC70
数组中第一个元素地址为: 0039FC70
3800176
请按任意键继续. . .
**注意:**数组名是常量,不可以赋值
总结1:直接打印数组名,可以查看数组所占内存的首地址
总结2:对数组名进行sizeof,可以获取整个数组占内存空间的大小
5.2.3 冒泡排序
作用: 最常用的排序算法,对数组内元素进行排序
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
重复以上的步骤,每次比较次数-1,直到不需要比较
示例:
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
int arr[] = { 3,45,6,65,23,64,1,4,7 };
cout << "排序前:" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
//开始冒泡排序
for (int i = 0; i < 9-1; i++) //总共排序轮数
{
//内层循环对比
for (int j = 0; j < 9-i-1; j++)//第一次需要交换8次,第二次交换7次,第三次交换6次...
{
//如果第一个数字比第二个数字大,则交换两个数字
//交换完后,第2个数与第3个数进行对比
//把最大的数逐渐放到最右边
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] << " ";
}
system("pause"); //暂停结果显示
return 0;
}
排序前:
3 45 6 65 23 64 1 4 7 排序后:
1 3 4 6 7 23 45 64 65 请按任意键继续. . .
5.3 二维数组
二维数组就是在一维数组上,多加一个维度。
5.3.1 二维数组定义方式
二维数组定义的四种方式:
数据类型 数组名[ 行数 ][ 列数 ];
数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 }};
数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};
数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};
建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性
示例:
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
int arr[2][3] =
{
{ 1,2,3 } ,
{4, 5, 6}
};
for (int i = 0; i < 2; i++) //外层循环打印行数
{
for (int j = 0; j < 3; j++) //内层循环打印列数
{
cout << arr[i][j] << " ";
}
cout << endl;
}
system("pause"); //暂停结果显示
return 0;
}
1 2 3
4 5 6
请按任意键继续. . .
5.3.2 二维数组数组名
查看二维数组所占内存空间
获取二维数组首地址
示例:
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//可以查看占用内存空间大小
//可以查看二维数组的首地址
int arr[2][3]=
{
{1,2,3},
{4,5,6}
};
cout << "二维数组占用空间为: " << sizeof(arr) << endl; //4x6=24
cout << "二维数组首地址为:" << arr << endl;
cout << "二维数组第一个元素首地址:" << &arr[0][0] << endl;
system("pause"); //暂停结果显示
return 0;
}
二维数组占用空间为: 24
二维数组首地址为:00D5FD58
二维数组第一个元素首地址:00D5FD58
请按任意键继续. . .
6 函数
6.1 概述
**作用:将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。
6.2 函数的定义
函数的定义一般主要有5个步骤:
1、返回值类型
2、函数名
3、参数表列
4、函数体语句
5、return 表达式
语法:
返回值类型 函数名 (参数列表)
{
函数体语句
return表达式
}
返回值类型 :一个函数可以返回一个值。在函数定义中 函数名:给函数起个名称 参数列表:使用该函数时,传入的数据
函数体语句:花括号内的代码,函数内需要执行的语句 return表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据
**示例:**定义一个加法函数,实现两个数相加
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
6.3 函数的调用
功能:使用定义好的函数
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int add(int num1, int num2) //加法函数 num1和num2为形参
{
int sum = num1 + num2;
return sum;
}
int main()
{
int a, b;
a = 10;
b = 20;
int c=add(a, b); //a和b为实参
cout << "c= " << c << endl;
system("pause"); //暂停结果显示
return 0;
}
c= 30
请按任意键继续. . .
6.4 值传递
所谓值传递,就是函数调用时实参将数值传入给形参
值传递时,如果形参发生,并不会影响实参
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//定义函数,实现两个数字进行交换
//如果函数不需要返回值,声明的时候可以写void,后面也不需要写return
void swap(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
cout << "在形参函数中交换后" << endl;
cout << num1 << endl;
cout << num2 << endl;
}
int main()
{
int a = 10, b = 20;
cout << "交换前,未调用交换函数" << endl;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
swap(a, b);
cout << "即使调用了函数之后,在main函数中值未改变" << endl;
cout << "a= " << a << endl; //这样写是错误的,因为并没有交换
cout << "b= " << b<< endl; //函数的形参发生改变,并不会影响实参 传值不传址
//在swap中,实现了互换,但实参中的a b并没有互换
system("pause"); //暂停结果显示
return 0;
}
交换前,未调用交换函数
a= 10
b= 20
在形参函数中交换后
20
10
即使调用了函数之后,在main函数中值未改变
a= 10
b= 20
请按任意键继续. . .
总结: 值传递时,形参是修饰不了实参的
6.5 函数的常见样式
常见的函数样式有4种:
无参无返
有参无返
无参有返
有参有返
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//函数常见样式
//1、无参无返 相当于goto语句 插入一段代码而已
void test01()
{
cout << "第一个test案例" << endl;
}
//2、无参有返 纯粹的把值 给调用代码
int test02()
{
cout << "第二个test案例" << endl;
return 1000;
}
//3、有参无返 相当于goto语句 插入一段代码,并且此代码需要给定数值才会运行
void test03(int a)
{
cout << "第三个test案例" << "a=" << a << endl;
}
//4、有参有返
int test04(int a)
{
cout << "第四个test案例" << "a=" << a << endl;
return a;
}
int main()
{
test01(); //1、无参无返
int num1=test02(); //2、无参有返
cout << num1 << endl;
test03(1000); //3有参无返
test04(10000);
system("pause"); //暂停结果显示
return 0;
}
第一个test案例
第二个test案例
1000
第三个test案例a=1000
第四个test案例a=10000
请按任意键继续. . .
6.6 函数的声明
作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数的声明可以多次,但是函数的定义只能有一次
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int max(int a, int b); //函数的声明 告诉编译器我有定义函数,只是把他放在了后面
int main()
{
int a = 39, b = 34;
cout << max(a, b) << endl;
system("pause"); //暂停结果显示
return 0;
}
//函数的声明
//比较函数,返回较大的值
int max(int a, int b)
{
return a > b ? a : b;
}
39
请按任意键继续. . .
6.7 函数的分文件编写
作用:让代码结构更加清晰
函数分文件编写一般有4个步骤
创建后缀名为.h的头文件
创建后缀名为.cpp的源文件
在头文件中写函数的声明
在源文件中写函数的定义
#源文件main并且加入头文件 #include"swap.h"
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
#include"swap.h"
函数的分文件编写
实现两个数字交换的函数
//
函数的声明
//void swap(int a, int b);
函数的定义
//void swap(int a, int b)
//{
// int temp = a;
// a = b;
// b = temp;
//
// cout << "a= " << a << endl;
// cout << "b= " << b << endl;
//}
int main()
{
int a = 10;
int b = 20;
swap(a,b);
system("pause"); //暂停结果显示
return 0;
}
#头文件 swap.h 声明
#include<iostream>
using namespace std;
//函数的声明
void swap(int a, int b);
# swap.cpp的定义
#include "swap.h"
//函数的定义
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
}
7 指针
7.1 指针的基本概念
指针的作用: 可以通过指针间接访问内存
内存编号是从0开始记录的,一般用十六进制数字表示
可以利用指针变量保存地址
7.2 指针变量的定义和使用
指针变量定义语法: 数据类型 * 变量名;
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//1、定义指针
int a = 10;
int *p;//创建了一个指针,但未指向内存中的某块地址,野指针
p = &a; //初始化指针p地址,指向a地址。&取址符号
cout << "a的地址为: " << &a << endl;
cout << "p的地址为: "<<p << endl;
//2、使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加 *代表解引用,就可以找到指针所指向的内存中的数据
*p = 1000; //p操作该地址的数据,解引用
cout << "a=" << a << endl;
cout << "*p=" << *p << endl;
a = 1;
cout << "a=" << a << endl;
system("pause"); //暂停结果显示
return 0;
}
a的地址为: 0022FB5C
p的地址为: 0022FB5C
a=1000
*p=1000
a=1
请按任意键继续. . .
7.3 指针所占内存空间
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//指针所占用内存的空间 在32位操作系统指针都是占4个字节,64位占用8位
int a = 10;
int *p=&a;
cout << "sizeof(p)=" << sizeof(p) << endl;
system("pause"); //暂停结果显示
return 0;
}
sizeof(p)=4
请按任意键继续. . .
7.4 空指针和野指针
空指针:指针变量指向内存中编号为0的空间
**用途:**初始化指针变量
**注意:**空指针指向的内存是不可以访问的
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//空指针
//1、空指针用于给指针变量进行初始化
int *p =NULL; //0~255之间的内存编号是系统占用的,因此不可以访问
//2、空指针是不可以进行访问的
cout << p << endl;
system("pause"); //暂停结果显示
return 0;
}
00000000
请按任意键继续. . .
> 野指针:指针变量指向非法的内存空间
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//野指针 随便指向地址 实际开发中,避免出现野指针
int *p = (int *)3234324;
cout << *p << endl;
system("pause"); //暂停结果显示
return 0;
}
> 总结:空指针和野指针都不是我们申请的空间,因此不要访问。
7.5 const修饰指针
> const修饰指针有三种情况
const修饰指针 — 常量指针
const修饰常量 — 指针常量
const即修饰指针,又修饰常量
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//const修饰指针——常量指针 const int *p=&a;
//指针指向的值不能变,指向可变
int a = 10;
int b = 20;
const int *p = &a;
p = &b;
//const修饰常量——指针常量 int * const p2=&a;
//指向不可变,指针指向的值能变
int * const p2 = &a;
*p2 = 100;
//const修饰指针和常量—— const int * const p3=&a;
//什么都不能变
const int * const p3 = &a;
//*p3 = 100; //错误,不可以改值
//p3 = &b; //错误,不可以改指向
system("pause"); //暂停结果显示
return 0;
}
7.6 指针和数组
**> **作用:利用指针访问数组中元素
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
int main()
{
//利用指针访问数组中的元素
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int * p = arr; //指向数组
cout << "利用指针访问第一个元素:" << *p << endl;
p++; //利用指针向后偏移
cout << "利用指针访问第二个元素: " << *p << endl;
//利用指针遍历数组
int *p2 = arr;
for (int i = 0; i < 10; i++)
{
cout << *p2 << endl;
p2++;
}
system("pause"); //暂停结果显示
return 0;
}
利用指针访问第一个元素:1
利用指针访问第二个元素: 2
1
2
3
4
5
6
7
8
9
10
请按任意键继续. . .
7.7 指针和函数
**作用:**利用指针作函数参数,可以修改实参的值
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//值传递
void swap1(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()
{
//指针和函数
//1、值传递与地址传递 的区别
//值传递不会改变实参 地址传递会改变实参 按项目要求自己决定
int a = 10, b = 20;
swap02(&a,&b);
cout <<"a="<< a << endl;
cout <<"b="<< b << endl;
system("pause"); //暂停结果显示
return 0;
}
a=20
b=10
请按任意键继续. . .
**总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递**
7.8 指针、数组、函数
**案例描述:**封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//参数1 数组的首地址 参数2 数组长度
void bubblesort(int *arr,int len)//传数组的首地址 数组的长度 ,int * arr 也可以写为int arr[]
{
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];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
//打印函数
void printArray(int *arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
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); //arr后什么也不写就代表数组的首地址
printArray(arr,len);
system("pause"); //暂停结果显示
return 0;
}
1
2
3
4
5
6
7
8
9
10
请按任意键继续. . .
8 结构体
8.1 结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
8.2 结构体定义和使用
> 语法:struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的方式有三种:
struct 结构体名 变量名
struct 结构体名 变量名 = { 成员1值 , 成员2值…}
定义结构体时顺便创建变量
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//1、创建学生的数据类型
struct Student
{
//成员列表
string name;
//姓名
int age;
//分数
int score;
}s3;
int main()
{
//2、通过学生类型创建具体学生
// 第一种方式使用结构体 struct Student s1
struct Student s1;
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout << "姓名: " << s1.name << " 年龄: " << s1.age << " 分数: " << s1.score << endl;
// 第二种方式使用结构体 struct Student s2={....}
struct Student s2 = { "李四",19,80 };
cout << "姓名: " << s2.name << " 年龄: " << s2.age << " 分数: " << s2.score << endl;
// 第三种方式使用结构体 在定义结构体时顺便创建结构体变量
s3.name = "王五";
s3.age = 20;
s3.score = 60;
cout << "姓名: " << s3.name << " 年龄: " << s3.age << " 分数: " << s3.score << endl;
system("pause"); //暂停结果显示
return 0;
}
姓名: 张三 年龄: 18 分数: 100
姓名: 李四 年龄: 19 分数: 80
姓名: 王五 年龄: 20 分数: 60
请按任意键继续. . .
总结1:定义结构体时的关键字是struct,不可省略
总结2:创建结构体变量时,关键字struct可以省略
总结3:结构体变量利用操作符 ‘’.’’ 访问成员
8.3 结构体数组
**作用:**将自定义的结构体放入到数组中方便维护
语法:struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//结构体数组
//1、定义一个结构体
struct Student
{
string name;
int age;
int score;
};
int main()
{
//2、创建结构体数组
struct Student stuArray[3] =
{
{"张三",100},{"李四",28,70},{"王五",25,99} //不赋值的化默认为0
};
//3、给结构体数组中的元素赋值
stuArray[2].name = "赵六";
stuArray[2].age = 15;
//4、遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名: " << stuArray[i].name << " 年龄:" << stuArray[i].age << " 分数:" << stuArray[i].score << endl;
}
system("pause"); //暂停结果显示
return 0;
}
姓名: 张三 年龄:100 分数:0
姓名: 李四 年龄:28 分数:70
姓名: 赵六 年龄:15 分数:99
请按任意键继续. . .
8.4 结构体指针
**作用:**通过指针访问结构体中的成员
利用操作符 ->可以通过结构体指针访问结构体属性
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
struct Student
{
string name;
int age;
int score;
};
int main()
{
//创建学生的结构体变量
struct Student s = { "张三",18,100 };
//通过创建结构体指针 指向结构体变量
struct Student *p = &s;
//通过指针访问结构体变量中的数据
cout << "姓名:" << p->name<<" 年龄:" << p->age << " 分数:" << p->score << endl;
system("pause"); //暂停结果显示
return 0;
}
姓名:张三 年龄:18 分数:100
请按任意键继续. . .
总结:结构体指针可以通过 -> 操作符 来访问结构体中的成员
8.5 结构体嵌套结构体
作用: 结构体中的成员可以是另一个结构体
**例如:**每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//定义学生的结构体
struct student
{
string name;//姓名
int age; //年龄
int score; //分数
};
//定义老师结构体
struct teacher
{
int id;
string name;
int age;
struct student s;
};
int main()
{
//结构体嵌套结构体
//创建老师
teacher t1;
t1.id = 223;
t1.age = 33;
t1.name = "阿达";
t1.s.name = "小王";
t1.s.age = 13;
t1.s.score = 100;
cout << "老师的姓名: " << t1.name << " 老师的编号: " << t1.id << " 老师的年龄: "<<t1.age
<< " 老师辅导的学生姓名: " << t1.s.name << " 学生的年龄: " << t1.s.age << " 学生的分数: " << t1.s.score << endl;
system("pause"); //暂停结果显示
return 0;
}
老师的姓名: 阿达 老师的编号: 223 老师的年龄: 33 老师辅导的学生姓名: 小王 学生的年龄: 13 学生的分数: 100
请按任意键继续. . .
**总结:在结构体中可以定义另一个结构体作为成员,用来解决实际问题
8.6 结构体做函数参数
作用:将结构体作为参数向函数中传递
传递方式有两种:
值传递
地址传递
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//定义学生结构体
struct student
{
string name;
int age;
int score;
};
//打印学生信息函数
void printStudent(struct student s)
{
cout << " 姓名:" <<s.name<< " 年龄: " << s.age << " 分数:" << s.score << endl;
s.age = 500;
}
void printStudent2(struct student *p)
{
cout << " 姓名:" << p->name << " 年龄: " << p->age << " 分数:" << p->score << endl;
p->age = 100; //把年龄改为100
}
int main()
{
struct student s;
s.name = "张三";
s.age = 20;
s.score = 85;
printStudent(s); //值传递
cout << " 年龄: " << s.age << endl;
printStudent2(&s);//地址传递
cout << " 年龄: " << s.age << endl;
system("pause"); //暂停结果显示
return 0;
}
姓名:张三 年龄: 20 分数:85
年龄: 20
姓名:张三 年龄: 20 分数:85
年龄: 100
请按任意键继续. . .
总结:如果不想修改主函数中的数据,用值传递,反之用地址传递
8.7 结构体中const使用场景
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
struct student
{
string name;
int age;
int score;
};
//将函数中的形参改为指针,可以减少内存空间,不会复制新的副本出来
//并且加了const不可以改形参的值,常量指针,保持外部实参的值,以防止函数内将其误操作
void printstudent( const student *s) //有const之后,就不能修改s.中的值了,会报错
{
cout << "姓名:" << s->name << " 年龄:" << s->age << " 得分" << s->score << endl;
}
int main()
{
//创建结构体变量
struct student s = { "张三",15,70 };
//通过函数来打印学生信息
printstudent(&s);
system("pause"); //暂停结果显示
return 0;
}
姓名:张三 年龄:15 得分70
请按任意键继续. . .
8.8 结构体案例一
案例描述:
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据。
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
#include<ctime>
//3个老师,分别带5个学生
//学生的结构定义
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~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()
{
//随机数种子
srand((unsigned int)time(NULL));
//创建3名老师的数组
struct Teacher tArray[3];
int len = sizeof(tArray) / sizeof(tArray[0]);
//通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
allocateSpace(tArray, len);
//打印所有老师及所带的学生信息
printInfo(tArray,len);
system("pause"); //暂停结果显示
return 0;
}
老师姓名: Teacher_A
学生姓名: Student_A 考试分数: 42
学生姓名: Student_B 考试分数: 42
学生姓名: Student_C 考试分数: 58
学生姓名: Student_D 考试分数: 94
学生姓名: Student_E 考试分数: 62
老师姓名: Teacher_B
学生姓名: Student_A 考试分数: 75
学生姓名: Student_B 考试分数: 50
学生姓名: Student_C 考试分数: 57
学生姓名: Student_D 考试分数: 77
学生姓名: Student_E 考试分数: 44
老师姓名: Teacher_C
学生姓名: Student_A 考试分数: 42
学生姓名: Student_B 考试分数: 70
学生姓名: Student_C 考试分数: 69
学生姓名: Student_D 考试分数: 81
学生姓名: Student_E 考试分数: 64
请按任意键继续. . .
8.9 结构体案例二
设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
五名英雄信息如下:
{“刘备”,23,“男”},
{“关羽”,22,“男”},
{“张飞”,20,“男”},
{“赵云”,21,“男”},
{“貂蝉”,19,“女”},
#include<iostream> //c++中的头文件,调用c++系统程序
using namespace std; //c++命名空间(调用关键字的命名含义)
#include<string> //引用字符串
//英雄的结构体定义
struct Hero
{
string name;
int age;
string sex;
};
//冒泡排序
void bubbleSort(struct Hero heroarray[], int len)
{
for (int i = 0; i < len; 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()
{
//1、英雄的结构体
//2、创建数组存放5名英雄
//3、对数组进行排序,按照年龄进行排序
//4、将排序后的结果打印输出
struct Hero heroarray[5] =
{
{"赵云",23,"男"},
{"关羽",22,"男"},
{"张飞",24,"男"},
{"黄忠",20,"男"},
{"貂蝉",21,"女"},
};
int len = sizeof(heroarray) / sizeof(heroarray[1]);
cout << "排序前的打印结果 " << endl;
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroarray[i].name << " 年龄:" << heroarray[i].age << " 性别:" << heroarray[i].sex << endl;
}
bubbleSort(heroarray, len);
cout << "排序后的打印结果 " << endl;
printHero(heroarray,len);
system("pause"); //暂停结果显示
return 0;
}
排序前的打印结果
姓名:赵云 年龄:23 性别:男
姓名:关羽 年龄:22 性别:男
姓名:张飞 年龄:24 性别:男
姓名:黄忠 年龄:20 性别:男
姓名:貂蝉 年龄:21 性别:女
排序后的打印结果
姓名:黄忠 年龄:20 性别:男
姓名:貂蝉 年龄:21 性别:女
姓名:关羽 年龄:22 性别:男
姓名:赵云 年龄:23 性别:男
姓名:张飞 年龄:24 性别:男
请按任意键继续. . .
后记
进步始于交流,收获源于分享。希望一起走过的日子里,我们能够更多地交流心得,共同进步 - You are not alone。