C++基础
VS快捷键
Ctrl +或- 跳转到上次鼠标焦点位置
Ctrl K F 按住Ctrl 然后按K 然后按F
Ctrl J 代码提示
变量
声明方式:数据类型 变量名 = 变量初始值
#include <iostream>
using namespace std;
int main()
{
int a = 1;
char b = 'b';
}
常量
#define 宏常量
声明方式:#define 常量名 常量值
通常在文件上方定义
#include <iostream>
using namespace std;
#define day 7
int main()
{
cout << "一周有" << day <<"天" << endl;
}
const修饰的变量
声明方式:const 数据类型 变量名 = 变量值
#include <iostream>
using namespace std;
int main()
{
const int day = 7;
cout << "一周有" << day <<"天" << endl;
}
命名规则
- 标识符不能是关键字
- 标识符只能有字母,数字,下划线
- 第一个字符必须为字母或下划线
- 区分大小写
数据类型
整型
- short 2字节
- int 4字节
- long windows 4字节 Linux32位 4字节 Linux64位 8字节
- long long 8字节
sizeof关键字
- 用来获取数据类型所占用内存大小
- 语法: sizeof( 数据类型 / 变量 )
#include <iostream>
using namespace std;
int main()
{
int a = 1;
long b = 1;
long long c = 1;
cout << "int类型占用:" << sizeof(int) << endl;
cout << "int变量占用:" << sizeof(a) << endl;
cout << "long类型占用:" << sizeof(long) << endl;
cout << "long变量占用:" << sizeof(b) << endl;
cout << "long long类型占用:" << sizeof(long long) << endl;
cout << "long long变量占用:" << sizeof(c) << endl;
}
输出结果(我使用的是windows 所以long类型也是4字节大小):
int类型占用:4
int变量占用:4
long类型占用:4
long变量占用:4
long long类型占用:8
long long变量占用:8
浮点型
- double 8字节 有效数字范围15-16位
- float 4字节 有效数字范围7位
需要注意的一点是:当我们声明一个float类型的带小数的变量时,编辑器会默认认为是double类型,准确指出类型需要在变量值最后加F
#include <iostream>
using namespace std;
int main()
{
float a = 1.1F;
float b = 1.1;
}
上面两种都可
字符型
语法: char c='a'
- 字符类型只能使用单引号,而不是双引号
- 只能是单个字符,不能是字符串
- c/c++中字符类型只占用
1字节
- 字符类型并不是把字符本身放到内存中存储,而是转换为对应的ASCll码存放
#include <iostream>
using namespace std;
int main()
{
char a = 'h';
char b = 'e';
cout << "变量a:" << a << endl;
cout << "变量b:" << b << endl;
}
输出char类型变量的ascll码
强转为int类型输出即可
#include <iostream>
using namespace std;
int main()
{
char a = 'h';
char b = 'e';
cout << "变量a:" << (int)a << endl;
cout << "变量b:" << (int)b << endl;
}
转义字符
就写几个常用的
- \n 换号
- \t 一个table的位置
- \\ 代表一个\
字符串类型
C风格字符串
声明方式: char 变量名[] = "字符串值"
#include <iostream>
using namespace std;
int main()
{
char s[] = "hello world";
cout << s << endl;
}
C++风格字符串
声明方式:string 变量名="字符串值"
如果使用不了string 需要导入头文件
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "hello world";
cout << s << endl;
}
Bool类型
表示真和假,只有两个值
- false 0
- true 1
bool类型只占用一个字节大小
#include <iostream>
#include <string>
using namespace std;
int main()
{
bool b = true;
cout << b << endl;
}
数据的输入
用于获取键盘的输入
关键词:cin
语法: cin>>变量
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 1;
cin >> a;
cout << a << endl;
}
运算符
- 算数运算符 处理四则运算
- 赋值运算符 将表达式赋值给变量
- 比较运算符 表达式的比较并返回一个bool值
- 逻辑运算符 用于根据表达式的值返回true或false
算数运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +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 |
tips: 两数相除,除数不能为0
两数取余,第二个数也不能为0;
两个小数是不能做取余操作
int main()
{
int a = 2;
int b = a++;
//其他操作也基本类似,就不粘代码了
cout << a << endl;
cout << b << endl;
}
赋值运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | a=2; | a=2; |
+= | 加等于 | a=2; a+=1; | a=3; |
-= | 减等于 | a=2;a-=1; | a=1; |
*= | 乘等于 | a=2;a*=2; | a=4; |
/= | 除等于 | a=4;a/=2; | a=2; |
%= | 模等于 | a=3;a%=2; | a=1; |
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 1;
a += 1;
// a = a + 1; 等同于这段代码 其他操作类似
cout << a << endl;
}
比较运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 相等于 | 1==1 | 1 (true) |
!= | 不等于 | 1!=1 | 0 (false) |
< | 小于 | 1<1 | 0 (false) |
<= | 小于等于 | 1<=1 | 1 (true) |
> | 大于 | 1>1 | 0 (false) |
>= | 大于等于 | 1>=1 | 1 (true) |
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << (1<=1) << endl;
}
逻辑运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非(取反) | !a | 如果a为假,则!a为真 反之亦然 |
&& | 与 (并且) | a&&b | 如果ab都为真,则结果为真,其中一个为假,则整体为假 |
|| | 或 (或者) | a||b | 只要其中一个为真,则结果为真,都为假则结果为假 |
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 10;
cout << !a << endl;
/*
结果为0 因为逻辑运算符会把变量当成bool类型来操作,bool中只有0和非0
那么10作为非0的数值被当成true,取反为false, 而false的int类型数值为0
所以结果为0
*/
cout << !!a << endl;
/*
结果为1 原因如上,当第一个!走完后结果已经为0了,而bool值只有0和非0
非零默认值是1,所以两次取反后结果为1
*/
//加几个!没有限制,可以无限加
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 10;
int b = 0;
cout << (a && b) << endl;
/*
结果为0 (false)
*/
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 10;
int b = 0;
cout << (a|| b) << endl;
/*
结果为1 (true)
*/
}
程序流程结构
选择结构
if
#include <iostream>
#include <string>
using namespace std;
int main(){
int a = 10;
int b = 0;
if (a) {
cout << "a" << endl;
}
else if (b){
cout <<"b" << endl;
}
else {
cout << "else" << endl;
}
}
三目运算符
语法:条件?为true返回的:否则返回的
例如a=1;b=2;
a>b?a:b
a大于b吗?是的返回a,否则返回b
#include <iostream>
#include <string>
using namespace std;
int main() {
int a = 10;
int b = 0;
int c = a > b ? a : b;
cout << c << endl;
/*
结果10
*/
}
#include <iostream>
#include <string>
using namespace std;
int main() {
int a = 10;
int b = 0;
//返回变量并赋值
( a > b ? a : b)=50;
cout << a << endl;
cout << b << endl;
/*
结果a=50
b=0;
*/
}
不仅可以返回变量,也可以在三目中进行赋值操作等
#include <iostream>
#include <string>
using namespace std;
int main() {
int a = 10;
int b = 0;
int c;
a > b ? c = 10 : c = 20;
cout << c << endl;
//结果c=10;
}
switch
#include <iostream>
#include <string>
using namespace std;
int main() {
char a = 's';
switch (a)
{
case 's':
cout << "s" << endl;
break;
case 'h':
cout << "h" << endl;
break;
default:
cout << "default" << endl;
break;
}
//结果 s
}
#include <iostream>
#include <string>
using namespace std;
int main() {
int a = 3;
switch (a)
{
case 1:
cout << "1" << endl;
break;
case 2:
cout << "2" << endl;
break;
default:
cout << "default" << endl;
break;
}
//结果 default
}
tips : 如果一个case没有break,则会继续执行下面的case直到结束 default也会执行
循环结构
while
语法:while(条件){循环语句}
#include <iostream>
#include <string>
using namespace std;
int main() {
int a = 1;
while (a < 10) {
cout << ++a << endl;
}
//一直循环到10结束
}
do..while
语法: do{循环语句} while(条件)
#include <iostream>
#include <string>
using namespace std;
int main() {
bool eat = false;
do {
cout << "吃个汉堡,还要吃吗?"<< endl;
cin >> eat;
} while (eat);
/*
结果:
吃个汉堡,还要吃吗?
1
吃个汉堡,还要吃吗?
1
吃个汉堡,还要吃吗?
0
程序结束
*/
}
for
语法:for(起始变量;循环条件;循环结束执行代码){循环语句}
#include <iostream>
#include <string>
using namespace std;
int main() {
char my_name[] = "jame";
for (int i = 0; i < sizeof(my_name); i++)
{
cout << my_name[i] << endl;
}
/*
sizeof可以获取到占用的内存大小,就是char的个数 一个char占一字节 那么sizeof(my_name)结果就是4
每次循环输出具体下标的内容就可以完成遍历了
结果:
j
a
m
e
*/
}
小练习:打印乘法表
#include <iostream>
#include <string>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= i; j++)
{
cout << i << "*" << j << "=" << (i*j) << " ";
}
cout << "\n";
}
}
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
跳转语句
语法: break
使用的时机:
- 在switch中,终止case并跳出switch
- 循环中跳出当前循环
上面的乘法表中使用
#include <iostream>
#include <string>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= i; j++)
{
if (j == i)
{
break;
}
cout << i << "*" << j << "=" << (i*j) << " ";
}
cout << "\n";
}
}
2*1=2
3*1=3 3*2=6
4*1=4 4*2=8 4*3=12
5*1=5 5*2=10 5*3=15 5*4=20
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72
当i==j的时候直接跳出循环了,所以看不到1乘1,2乘2这样类似的输出
contiune
当在循环中出现contiune时,直接进行下次循环
#include <iostream>
#include <string>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++)
{
if (i % 2 == 0)
{
continue;
}
cout << i;
}
}
//结果133579
goto
无条件跳转
语法:goto 标记
如果标记的位置存在,则执行到goto时会直接跳转到标记的位置
#include <iostream>
#include <string>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++)
{
if (i == 8)
{
goto END;
}
cout << i;
}
END:
cout << "结束啦";
}
不光是往下面跳,还能往上跳
#include <iostream>
#include <string>
using namespace std;
int main() {
int b = 0;
RESTART:
if (b > 0) {
cout << "b!" << endl;
}
for (int i = 1; i <= 9; i++)
{
if (i == 8 && b == 0)
{
b = 10;
goto RESTART;
}
cout << i ;
}
}
/*
结果
1234567b!
123456789
*/
使用goto向上面跳时一定要注意结束的判断,避免死循环
数组
特点1:同个数组内的每个元素都相同类型的
特点2:数组是内存中一块连续内存地址组成的
定义数组
int main() {
int a[10];
int b[10] = { 1,2,3 }; //如果标记长度为10,但是只初始化3个值,那么剩下的默认值都是0
int c[] = { 1,2,3 };
}
三种定义数组的方式
访问数组
int main() {
int a[10];
a[1] = 1;
a[2] = 100;
}
数组名用途
- 可以获取整个数组在内存中的长度
- 可以获取内存中数组的首地址
#include <iostream>
#include <string>
using namespace std;
int main() {
int a[10] = { 1,2,3 };
cout << "数组占用总大小" << sizeof(a) << endl;
cout << "每个元素占用大小" << sizeof(a[0]) << endl;
cout << "数组中有多少个元素" << sizeof(a)/sizeof(a[0]) << endl;
}
数组占用总大小40
每个元素占用大小4
数组中有多少个元素10
tips: 数组中有多少个元素 这里使用a[0] 而不是其他a[1],a[2]...的原因 首先数组的特性1,每个元素都是相同类型的,也就是所有的元素大小都是一样的,使用那个都可以
那么也可以使用a[1],a[2]... 但是需要注意的是下标不能超过定义的最大长度
int main() {
int a[10] = { 1,2,3 };
cout << "数组首地址"<< a << endl;
cout << "数组第一个元素的首地址"<< &a[0] << endl;
}
tips: &在变量前是获取元素的地址
二维数组
定义:
#include <iostream>
#include <string>
using namespace std;
int main() {
int a[3][3]; //声明一个三行三列的数组
int b[3][3] = { {1,2,3},{4,5,6},{7,8,9} }; //声明三行三列,同时赋初始值
int c[3][3] = { 1,2,3,4,5,6,7,8,9 }; //声明三行三列 同时全部赋值 三个为一行
int d[][3] = { 1,2,3,4,5,6 }; //声明一个两行三列 同时赋值
}
数组名称
#include <iostream>
#include <string>
using namespace std;
int main() {
int b[3][3] = { {1,2,3},{4,5,6},{7,8,9} }; //声明三行三列,同时赋初始值
cout << "二维数组首地址:" << b << endl;
cout << "二维数组一行大小:" << sizeof(b[0]) << endl;
cout << "二维数组元素大小:" << sizeof(b[0][0]) << endl;
}
二维数组遍历
#include <iostream>
#include <string>
using namespace std;
int main() {
int b[3][3] = { {1,2,3},{4,5,6},{7,8,9} }; //声明三行三列,同时赋初始值
for (int i = 0; i < (sizeof(b)/sizeof(b[0])); i++)
{
for (int j = 0; j < (sizeof(b[0])/sizeof(b[0][0])); j++)
{
cout << b[i][j];
}
}
}
函数(方法)
一个函数包含以下内容:
- 返回值类型
- 函数名称
- 参数列表
- 函数体
- return
//返回值类型和函数名称,参数为空
int main() {
//函数体
cout << "hello world";
//return值
return 0;
}
函数的调用
int sum(int number1, int number2) {
return number1 + number2;
}
int main() {
cout << sum(1,2);
return 0;
}
tips: C++和JAVA不一样,被调用的函数必须在调用函数的方法前声明
值传递
值传递是指当实参传递给形参后,当形参发生改变,实参并不会发生变化
int test(int number1) {
number1 += 1;
return 0 ;
}
int main() {
int a = 1;
test(a);
cout << a;
return 0;
}
当调用完test函数后a的值输出还是1,或者我们输出number1
和a
的地址,也会发现不同,说明test的参数只是值传递
int test(int number1)
{
number1 += 1;
cout << &number1 << endl;
return 0 ;
}
int main()
{
int a = 1;
test(a);
cout << &a<<endl;
return 0;
}
/*
000000FF976FF550
000000FF976FF574
*/
函数常见样式
-
有参有返
int sum(int a,int b) { return a+b; }
-
有参无返
void print_number(int number) { cout << number; }
-
无参有返
int get_one() { return 1; }
-
无参无返
void print_hello(){ cout << "hello"; }
函数的声明
在函数的开始篇有个tips 说使用的被调用的函数必须声明在调用的函数前,而函数声明就可以让被调用的函数声明在调用的函数之后
#include <iostream>
#include <string>
using namespace std;
int main() {
int a = 1;
print(a);
return 0;
}
void print(int a) {
cout << a;
}
我们这么写编译是没有问题,但是当运行起来后就会报错:print找不到标识符
调换个位置就可以正常运行
void print(int a) {
cout << a;
}
int main() {
int a = 1;
print(a);
return 0;
}
而函数的声明就是提前声明我有这个函数
语法:返回类型 函数名(参数);
一个函数可以被声明多次,但是只能定义一次
#include <iostream>
#include <string>
using namespace std;
void print(int a); //提前声明存在print函数
int main() {
int a = 1;
print(a);
return 0;
}
void print(int a) {
cout << a;
}
函数分文件编写
将相同功能的函数单独放在一个文件中,使结构更加清晰
- 创建后缀为
.h
的头文件 - 创建后缀为
.cpp
的源文件 - 在头文件中写函数声明
- 在源文件中写函数实现
myHead.h
#include <iostream>
using namespace std;
void print(int a);
myHead.cpp
#include "myHead.h";
void print(int a) {
cout << a;
}
主文件
#include "myHead.h";
int main() {
int a = 1;
print(a);
return 0;
}
我们在.h头文件中引入了iostream
也使用了std
那么只要导入myHead.h
文件的都可以使用
咋说呢,有点像java的接口?哈哈哈
指针
指针的作用:可以通过指针直接访问内存
- 内存编号从0开始,一般为16进制数字表示
- 可以使用
指针变量
保存地址
指针的定义和使用
语法:数据类型* 变量名
int main() {
int a = 1;
int* a_pointer = &a;//将a的地址存放到指针中
*a_pointer = 100;//将100赋值给指针指向的地址中 指针前加*代表解引用 找到指针指向内存中的数据
cout << a << endl;
cout << "a的地址" << &a<<endl;
cout << "a指针的数据"<<a_pointer << endl;
}
指针占用的内存
int main() {
cout << sizeof(int *) << endl;
cout << sizeof(short *) << endl;
cout << sizeof(float *) << endl;
cout << sizeof(double *) << endl;
cout << sizeof(long *) << endl;
cout << sizeof(long long *) << endl;
}
32位中都是4字节 64位中都是8字节
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途: 初始化指针
注意: 空指针的内存是不可访问的
int main() {
int* a = NULL;
cout << *a << endl;
//*a = 100; 或者这段代码
}
//都会报一个访问权限的异常
野指针:指针变量指向非法的内存空间
int main() {
int* a = (int*)0x10000; //(int * 强制转换为指针类型)
*a = 100;
}
//也会报一个访问权限的异常
tips: 空指针和野指针都不是我们申请的空间,因此不要访问
const修饰指针
const有三种情况
- 修饰指针:常量指针
- 修饰常量:指针常量
- 即修饰指针,又修饰常量
常量指针
int main() {
int a = 10;
int b = 20;
/*
* 常量指针
* 指针指向的值不可修改,但是可以修改指向
*/
const int* p = &a;
//*p = 10; 修改指向的值 错误
p = &b;//修改指向 可以
}
指针常量
int main() {
int a = 10;
int b = 20;
/*
* 指针常量
* 指针指向的值不可修改,但是可以修改指向
*/
int* const p = &a;
*p = 10; //修改指向的值 可以
//p = &b;//修改指向 错误
}
即修饰指针,又修饰常量
int main() {
int a = 10;
int b = 20;
/*
* 即修饰指针,也修饰常量
* 指针指向的值不可修改,但是可以修改指向
*/
const int* const p = &a;
//*p = 10; //修改指向的值 错误
//p = &b;//修改指向 错误
}
指针和数组
利用指针访数组中的元素
int main() {
int a[5] = { 1,2,3,4,5 };
int* p = a;
cout << *p;
p++;
cout << *p;
}
tips: 指针类型++ 加的是sizeof(指针类型) 的值, int加4字节正好是下个元素的地址 然后*p解引用取值也就是下个元素的值
指针和函数
利用指针作为函数的参数,从而修改实参的值,也就是常说的值传递和引用传递,而当使用指针作为参数传递时,就是引用传递
void add(int* num1) {
(*num1)++;
}
int main() {
int a = 10;
add(&a);
cout << a;
}
当执行完后a的值为11
tips: 括号标明是先去获取指针指向的值,然后自增1,如果不加可能以为是指针值++然后取值
指针数组和函数
小练习 冒泡
int* arr接收数组的地址,可以当做数组使用
void golugolu(int* arr ,int lenght)
{
for (int i = 0; i < lenght; i++)
{
for (int j = 0; j < lenght - i- 1; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j]=arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int a[5] = { 2,3,1,4,5 };
golugolu(a,5);
for (int i = 0; i < 5; i++)
{
cout << a[i];
}
}
结构体
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
语法: struct 结构体名 {结构体成员列表}
;
tpis:
注意! 结构体结束}后面需要加一个;结尾
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名={成员1值,成员2值}
- 定义结构体时同时设置变量
方式1
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
};
int main()
{
struct Student student; //struct可以省略
student.age = 10;
student.name = "张三";
student.score = 90;
cout << student.age << endl;
}
方式2
#include <iostream>
#include <string> //如果string类型报错则导入该头文件
using namespace std;
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
};
int main()
{
struct Student student = { "张三",90,18 }; //struct可以省略
cout << student.name << endl;
}
类似于有参构造,每个变量的顺序就是在结构体中声明的顺序
方式3
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
} oldStudnet; //标明一个结构体
int main()
{
//可以使用上面两种来进行填充数据
oldStudnet = { "we",1,1 };
oldStudnet.age = 199;
cout << oldStudnet.name << endl;
cout << oldStudnet.age << endl;
}
结构体数组
语法:struct 结构体名 数组名[个数]={{},{},{},...{}
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
};
int main()
{
struct Student arr[3] =
{
{"张三",1,1},
{"李四",2,2},
{"王五",3,3}
};
//整个数组长度除以每个元素长度获取到多少个元素
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
//在循环中就可以将arr[i]当成具体的struct
arr[i].age = 10;
cout << arr[i].name;
}
}
结构体指针
语法: 可以通过->
来访问结构体中的属性
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
};
int main()
{
//创建结构体变量
struct Student studnet = { "张三",1,1 };
//创建指针变量,同时指向student变量
struct Student* p = &studnet;
//使用-> 操作符操作变量age
p->age = 100;
cout << p->age;
}
结构体嵌套结构体
struct Dog {
string name;
int age;
};
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
struct Dog dog;
};
int main()
{
struct Dog dog = { "旺财",4 };
//将dog设置到student中
struct Student student = { "小明",90,10,dog };
//先获取学生的指针
struct Student* student_p = &student;
//之后通过指针在获取到学生内部的狗的地址赋值给狗指针
struct Dog* dog_p = &student_p->dog;
//通过狗指针获取狗age
cout << dog_p->age;
}
结构体做函数参数
有两种:值传递和引用传递
struct Dog {
string name;
int age;
};
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
struct Dog dog;
};
//值传递
void set_value(struct Student s1) {
s1.age = 100;
s1.dog.age = 10;
}
//引用传递
void set_value2(struct Student* s1) {
//设置学生年龄
s1->age = 100;
//设置狗的年龄
s1->dog.age = 10;
//这种也可以,通过指针操作
//struct Dog* dog_p = &(s1->dog);
//dog_p->age = 10;
}
int main()
{
struct Dog dog = { "旺财",4 };
struct Student student = { "小明",90,18,dog };
set_value2(&student);
cout << student.dog.age << endl;
cout << student.age << endl;
}
结构体中使用const
struct Dog {
string name;
int age;
};
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
struct Dog dog;
};
struct Dog dog = { "旺财",4 };
void print(const struct Student* s) {
struct Student student = { "老明",90,18,dog };
s = &student;
//s->name = "2";报错
cout << s->name;
}
int main()
{
struct Student student = { "小明",90,18,dog };
print(&student);
}
tpis: 形参接收struct 例如 void print(const struct Student* s)
你这个Student拼写错了是不会报错的,需要注意拼写,或者直接省略
struct
关键字
//定义结构体
struct Student
{
//声明结构体中的成员
string name;
int score;
int age;
struct Dog dog;
};
struct Dog dog = { "旺财",4 };
void print(struct Student* const s) {
struct Student student = { "老明",90,18,dog };
//s = &student; 报错
s->name = "王哈哈";
cout << s->name;
}
int main()
{
struct Student student = { "小明",90,18,dog };
print(&student);
}
结构体const和修饰普通的指针一样
const struct Student* s
形参里面的值不能改变 但是指向的地址可以改变
struct Student* const s
形参里面值可以改变,但是指向不能改变
const struct Student* const s
两个都不能变