C++的基础知识学习
1.3变量
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名=初始值;
int a=1;
变量存在的意义:方便管理内存空间
1.4常量
作用:用于记录程序中不可更改的数据
C++定义常量两种方式
1.#define 宏常量:#define 常量名 常量值
通常在文件上方定义,表示一个常量
2.const关键字修饰的变量 const 数据类型 常量名=常量值
通常在变量定义前加关键字const,修饰该变量为常量,不可修改
const int a=1;
1.5关键字
作用:关键字是C++中预先保留的单词
在定义变量或常量时候,不能用关键字
1.6标识符命名规则
作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则
标识符不能是关键字
标识符只能由字母、数字、下划线组成
第一个字符必须为字母或下划线
标识符中字母区分大小写
建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读
2数据类型
2.1整型
C++规定在创建一个变量或者是常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
整型作用:整型变量表示的是整数类型的数据
C++中能够表示整型类型有以下几种方式,区分在于所占内存空间不同
短整型(-32768~32767)
2.2sizeof关键字
作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型/变量)
2.3实型(浮点型)
作用:用于表示小数
浮点型变量分为两种:
1.单精度float
2.双精度double
两者的区别在于表示的有效数字范围不同
float f1=3.14f;如果数字后面没有f系统会默认为双精度
科学计数法
float f2=3e2(3*10^2)
float f3=3e-2(3*0.1^2)
2.4字符型
作用:字符型变量用于显示单个字符
语法:char ch=‘a’ 键盘上每一个键都可以叫一个字符
注意1:在显示字符型变量时,用单引号将字符括起来,不要用双引号
注意2:单引号内只能有一个字符,不可以是字符串
C和C++中字符型变量只占用1个字节
字符型变量并不是把字符本身放在内存中存储,而是将对应的ASCII编码放入到存储单元每个字母对应一个编号,是把编号存在存储空间里
int(a)把字符a强转成int类型
2.5转义字符
作用:用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有:\n \ \ \t
\t占了八个位置,有对齐的效果
2.6字符串型
作用:用于表示一串字符
两种风格
1.C风格字符串:char 变量名[]=“字符串值”
注意:C风格的字符串要用双引号括起来
2.C++风格字符串 string 变量名=“字符串值”
要包含头文件
string str2=“hello world”;
2.7布尔类型bool
作用:布尔数据类型代表真或假的值
bool类型只用两个值
true----真(本质是1)
false—假(本质是0)
bool类型占1个字节大小
2.8数据的输入
作用:用于从键盘获取数据
关键字:cin
语法:cin>>变量
3.运算符
作用:用于执行代码的运算
3.1算术运算符
作用:用于处理四则运算
算术运算符包括以下符号
取模运算本质 :就是取余数
0%20=20 除不过时就是数本身
前置递增 先让变量+1 然后进行表达式运算
后置递增 先进行表达式运算 然后再让变量+1
3.2赋值运算符
作用:用于将表达式的值赋给变量
赋值运算符包括以下几个符号
3.3比较运算符
作用:用于表达式的比较,并返回一个真值或假值
比较运算符有以下符号
3.4逻辑运算符
作用:用于根据表达式的值返回真值或假值
逻辑运算符有以下符号
4.程序流程结构
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构、循环结构
顺序结构:程序按顺序执行,不发生跳转
选择结构:依据条件是否满足,有选择的执行相应功能
循环结构:依据条件是否满足,循环多次执行某段代码
4.1选择结构
4.1.1 if语句
作用:执行满足条件的语句
if语句的三种形式
单行格式if语句
多行格式if语句
多条件的if语句
嵌套if语句:在if语句中,可以嵌套使用if语句,达到更精确的条件判断
4.1.2三目运算符
作用:通过三目运算符实现简单的判断
语法:表达式1?表达式2:表达式3
解释:
如果表达式1的值为真,执行表达式2,并返回表达式2的结果
如果表达式1的值为假,执行表达式3,并返回表达式3的结果
4.1.3 switch语句
作用:执行多条件分支语句
语法
4.2循环结构
4.2.1 while循环语句
作用:满足循环条件,执行循环语句
语法:while(循环条件){循环语句}
解释:只要循环条件的结果为真,就执行循环语句
4.2.2 do…while 循环语句
作用:满足循环条件,执行循环语句
语法:do{循环语句}while{循环条件}
注意:与while的区别在于do…while会先执行一次循环语句,在判断循环条件
案例:水仙花数
4.2.3 for循环语句
作用:满足循环条件,执行循环语句
语法:for(起始表达式;条件表达式;末尾循环体){循环语句}
4.3跳转语句
4.3.1 break语句
作用:用于跳出选择结构或者循环结构
break使用的时机:
出现在switch条件语句中,作用是终止case并跳出switch
出现在循环语句中,作用是跳出当前的循环语句
出现在嵌套循环中,跳出最近的内层循环语句
4.3.2 continue语句
作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环(注意和break的区别)
4.3.3 goto语句(只是了解不推荐使用)
作用:可以无条件跳转语句
语法:goto 标记(标记习惯用大写小写也可以)
解释:如果标记的名称存在,执行到goto语句时,会跳转到标记的位置
5 数组
5.1概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点1:数组中每个数据元素都是相同的数据类型
特点2:数组是由连续的内存位置组成的
5.2一维数组
5.2.1 一维数组定义方式
一维数组定义的三种方式
1.数据类型 数组名[数组长度];
2.数据类型 数组名[数组长度]={值1,值2,…};
如果在初始化数据时候,没有全部填写完,会用0来填补剩余数据
3.数据类型 数组名[]={值1,值2,…};
定义数组的时候,必须有初始长度
下标:我们可以通过下标访问数组中的元素
5.2.2 一维数组数组名
一维数组名称的用途:
1.可以统计整个数组在内存中的长度
2.可以获取数组在内存中的首地址
16进制
强转成10进制
5.3 二维数组
二维数组就是在一维数组上,多加一个维度
5.3.1 二维数组定义方式
二维数组定义的四种方式
1.数据类型 数组名[行数】[列数];
2.数据类型 数组名 【行数][列数]={(数据1,数据2),(数据3,数据4)};
3.数据类型 数组名 【行数][列数]={数据1,数据2,数据3,数据4};
4.数据类型 数组名 【】[列数]={数据1,数据2,数据3,数据4};
建议:以上4种定义方式,利用第二种更加直观,提高代码的可读性
5.3.2 二维数组数组名
查看二维数组所占内存空间
获取二维数组首地址
6.函数
6.1概述
作用:将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能
6.2 函数的定义
函数的定义一般主要有5个步骤
1.返回值类型
2.函数名
3.参数列表
4.函数体语句
5.return 表达式
函数定义的时候,num1和num2并没有真实数据,他只是一个形式上的参数,简称形参
返回值类型:一个函数可以返回一个值,在函数定义中
函数名:给函数起个名称
参数列表:使用该函数时,传入的数据
函数体语句:花括号内的代码,函数内需要执行的语句
return表达式:和返回值类型挂钩,函数执行完后返回相应的数据
6.3 函数的调用
功能:使用定义好的函数
语法:函数名(参数)
a 和 b称为实际参数 简称实参
当调用函数时候,实参的值会传递给形参
6.4 值传递
所谓值传递,就是函数调用时实参将数值传入给形参
值传递时,如果形参发生改变,并不会影响实参
6.5 函数的常见样式
常见的函数样式有4种
1.无参无返
2.有参无返
3.无参有返
4.有参有返
//函数的常见样式
//1.无参无返
void test01()
{
cout<<"this is test01"<<endl;
}
//2.有参无返
void test02(int a)
{
cout<<"this is test 02 a= "<<a<<endl;
}
//3.无参有返
int test03()
{
cout<<"this is test03"<<endl;
return 1000;
}
//4.有参有返
int test04(int a)
{
cout<<"this is test04 a="<<a<<endl;
return a;
}
int main()
{
//test01调用
test01();
//tset02调用
test02(100);
//test03调用
int num1=test03();
cout<<"num1="<<num<<endl;//运行结果是1000
//test04调用
int num2=test04(10000);
cout<<"num2="<<num2<<endl;//**运行结果 a=10000 num2=10000**
}
6.6 函数的声明
作用:告诉编译器函数名称及如何调用函数,函数的实际主体可以单独定义
函数的声明可以多次,但是函数的定义只能是一次
有了函数的声明,函数的定义就可以放main函数后边,反正系统报错
6.7 函数的分文件编写
作用:让代码结构更加清晰
函数分文件编写一般有4个步骤
1.创建后缀名为.h的头文件
2.创建后缀名为.cpp的源文件
3.在头文件中写函数的声明
4.在源文件中写函数的定义
7. 指针
7.1 指针的基本概念
指针的作用:可以通过指针间接访问内存
内存编号是从0开始记录的,一般是用十六进制数字表示
可以利用指针变量保存地址
指针(变量):可以通过指针来保存某个变量地址,通过访问地址就可以找到这个变量
指针就是地址
7.2 指针变量的定义和使用
指针变量定义语法:数据类型 * 变量名
//1.定义指针
int a=10;
int *p;
//让指针记录变量a的地址
p=&a;//指针p记录a的地址
cout<<"a的地址为"<<&a<<endl;
cout<<"指针p="<<endl;//运行结果一样
//2.使用指针
//可以通过解引用的方式来找到指针指向的内存
*p//指针前加一个*代表解引用,找到指针指向的内存中的数据
*p=1000;
cout<<"a="<<a<<endl;
cout<<"*p="<<*p<<endl;//运行结果一样 a=1000 *p=1000
//*p可读取a内存,也可修改a的内存
7.3 指针所含的内存空间
提问:指针也是种数据类型,那么这种数据类型占用了多少内存空间?
不管什么数据类型的指针,在32位操作系统下:占用4个字节空间,64位下占用8个字节
int *p;
p=&a;
可直接写成
int *p=&a;
7.4 空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化指针变量(指针一开始不知道指到哪)
注意:空指针指向的内存是不可以访问的
0~255 之间的内存编号是系统占用的,因此不可以访问
int *p;
*p=100;//运行错位,因为指针不能访问,故也不可修改
野指针:指针变量指向非法的内存空间(就是指过了)
0x1100是十六进制的数,如果想让他变成一个地址,需要强转一下(int)0x1100*
//野指针
int *p=(int *)0x1100;//0x1100的地址并没有申请
cout<<"*p="<<*p<<endl;//访问就会报错
在程序中,尽量避免野指针
总结:空指针和野指针都不是我们申请的空间,因此不要访问
7.5 const 修饰指针
const修饰指针有三种情况
1.const修饰指针------常量指针
2.const修饰常量----指针常量
3.const即修饰指针,又修饰常量
1.常量指针
2.指针常量
3.const即修饰指针,又修饰常量
7.6 指针和数组
作用:利用指针访问数组中的元素
int arr[10]={1,2,3,4,5,6,7,8,9,10};
cout<<"第一个元素:"<<arr[0]<<endl;
int *p=arr;//arr名就是数组的首地址
cout<<"利用指针来访问第一个元素:"<<*p<<endl;//运行结果是1
p++;//向后移了4个字节
cout<<"利用指针访问第二个元素:"<<*p<<endl;//运行结果是2
//*p解引用解出了4个字节
cout<<"利用指针遍历数组:"<<endl;
int *p2=arr;
for(int i=0;i<10;i++)
{
cout<<arr[i]<<endl;//普通遍历
cout<<*p2<<endl;
p2++;//指针遍历
}
7.7 指针和函数
作用:利用指针作函数参数,可以修改实参的值
值传递不会改变实参的值,地址传递会改变实参的值
//实现两个数字进行交换
void swap01(int a,int b)
{
int temp=a;
a=b;
b=temp;
cout<<"swap01 a="<<a<<endl;
cout<<"swap02 b="<<b<<endl;
//运行结果 a=20,b=10
}
void swap02(int *p1,int *p2)
{
int temp=*p1;
*p1=*p2;
*p2=temp;
}
//指针和函数
//1.值传递
int a=10;
int b=20;
swap01(a,b);
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
//运行结果 a=10,b=20;
//2.地址传递:可修改实参的数据
如果是地址传递,可以修饰实参
swap02(&a,&b);//传的是ab的地址,用指针接收
实参ab的值也交换了
8. 结构体
8.1 结构体基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型,可以创建无数个
例如写一个人的数据类型,创建一个人的变量
8.2 结构体定义和使用
语法:struct 结构体名{结构体成员列表};
通过结构体创建变量的方式有三种:
struct 结构体名 变量名
struct 结构体名 变量名={成员1值,成员2值…}
定义结构体时顺便创建变量
struct关键字结构体在创建变量时可以省略,但是在定义时不能省略
结构体变量利用操作符.访问成员
//1.创建学生数据类型:学生包括(姓名、年龄、分数)
//自定义数据类型:一些类型集合组成的一个类型
struct Student//struct不可省略
{
//成员列表
//姓名
string name;//注意要包含string的头文件
//年龄
int age;
//分数
int score;
};
//2.通过学生类型创建具体学生
//2.1 struct Student s1
struct Student s1;//struct可以省略
//给s1属性赋值,通过.来访问结构体变量中的属性
s1.name=“张三”;
s1.age=18;
s1.score=100;
//2.2 struct Student s2={....}
struct Student s2={“李四,19,80};
//2.3 在定义结构体时顺便创建结构体变量
struct Student
{
//成员列表
//姓名
string name;//注意要包含string的头文件
//年龄
int age;
//分数
int score;
};s3//顺便创建结构体变量
s3.name=”王五“;
s3.age=20;
s3.score=80;
8.3 结构体数组
作用:将自定义的结构体放入到数组中方便维护(当成员较多时)
语法:struct 结构体名 数组名[元素个数]={{},{},{},…{}}
#include<iostream>
using namespace std;
#include<string>
//结构体数组
//1.定义结构体
struct Student
{
string name;
int age;
int score;
};
int main()
{
//2.创建结构体数组,初始值
struct Student stuArray[3]={
{"张三",18,100},
{"李四",19,80},
{"王五",17,90}
};
//3.给结构体数组中的元素赋值
stuArray[2].name="赵六";//后期可以修改初始值
stuArray[2].age=80;
stuArray[2].score=100;
//4.遍历结构体数组
for(int i=0;i<3;i++)
{
cout<<"姓名"<<stuArray[i].name<<"年龄:"<<stuArray[i].age
<<"分数:"<<stuArray[i].socre<<endl;
}
8.4 结构体指针
作用:通过指针访问结构体中的成员
利用操作符->可以通过结构体指针访问结构体属性
#include<iostream>
using namespace std;
#include<string>
//结构体指针
//定义学生的结构体
struct Student
{
string name;
int age;
int score;
};
int main()
{//1.创建学生结构体变量
struct student s={"张三",18,90};
//2.通过指针指向结构体变量
int *p=&s//报错,等号左右侧指针不兼容
(struct) student *p=&s;
//3.通过指针访问结构体变量中的数据
cout<<“姓名”<<p->name<<"年龄"<<p->age<<"分数"<<p->score<<endl;
}
8.5 结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
#include<iostream>
using namespace std;
#include<string>
//定义学生的结构体
struct Student
{
string name;
int age;
int score;
};
//定义老师的结构体
struct teacher
{
int id;//教师编号
string name;//教师姓名
int age;//年龄
struct student stu;//辅导的学生。定义学生的结构体要在老师的结构体的上方
};
int main()
{
//创建老师
teacher t;
t.id=1000;
t.name="老王";
t.age=40;
t.stu.name="小王";
t.stu.age=20;
t.stu.score=60;
}
8.6 结构体做函数参数
作用:将结构体作为参数向函数中传递
传递方式有两种:
值传递
地址传递
如果不想修改主函数中的数据,用值传递,反之用地址传递
#include<iostream>
using namespace std;
#include<string>
//定义学生的结构体
struct Student
{
string name;
int age;
int score;
};
//打印学生信息的函数
//1.值传递:形参变,实参不变
void printStudent1(struct student s)
{s.age=100;
cout<<s.name<<s.age<<s.score<<end;//运行结果age=100
}
//2.地址传递:形参变,实参变
void printStudent2(struct student *p)//以指针接收地址
{p—>age=200;
cout<<p->name<<p->age<<p->score<<endl;//运行结果为200
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
struct student s;
s.name="张三";
s.age=19;
s.score=60;
cout<<s.name<<s.age<<s.score<<endl;//值传递改变age,这里的age=20不变
//地址传递中age变为200,这里也变为200
//值传递
printStudent1(s);
//地址传递
printStudent2(&s);
}
8.7 结构体中const使用场景
作用:用const来防止误操作
将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
加入const之后,一旦有修改的操作就会报错,可以防止我们的误操作