语法: #define 常量名 常量值
通常在文件上方定义,表示一个常量
语法: const 数据类型 常量名 = 常量值
通常在变量定义前加关键字const,修饰该变量为常量,不可修改
作用: C++规定给标识符(变量、常量)命名时,有一套自己的规则
1.标识符不能是关键字
2.标识符只能由字母、数字、下划线组成
3.第一个字符必须为字母或下划线
4.标识符中字母区分大小写
数据类型存在的意义:给变量分配合适的内存空间
作用: 整型变量表示的是整型类型的数据
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) |
作用:利用sizeof关键字可以统计数据类型所占内存大小
语法: sizeof(数据类型/变量)
示例:
int main()
{
cout << "short 类型所占内存空间为:" << sizeof(short) << endl; //2
cout << "int 类型所占内存空间为:" << sizeof(int) << endl; //4
cout << "long 类型所占内存空间为:" << sizeof(long) << endl; //4
cout << "long long 类型所占内存空间为:" << sizeof(long long) << endl; //8
return 0;
}
作用: 用于表示小数
浮点数变量分为两种:
1.单精度float
2.双精度double
两者的区别在于表示的有效数字范围不同
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4字节 | 7位有效数字 |
double | 8字节 | 15~16位有效数字 |
作用: 字符型变量用于显示单个字符
语法: char ch = ‘a’;
注意:
1. 在显示字符型变量时,用单引号将字符括起来,而不是双引号
2. 单引号内只能由一个字符,不可以是字符串
3. C和C++中字符型变量只占用1个字节
4. 字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放到存储单元中
作用:用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有: \n \\ \t
转义字符 | 含义 | ASCII(十进制) |
---|---|---|
\n | 换行,将当前位置移动到下一行开头 | 010 |
\\ | 代表一个反斜线字符“\” | 092 |
\t | 水平制表(跳到笑一个TAB位置) | 009 |
作用: 用于表示一串字符
两种风格
1. C风格字符串:char 变量名[] = “字符串值”;(C风格的字符串要用双引号括起来)
2. C++风格字符串: string 变量名 = “字符串值”;
作用: 布尔数据类型表示真或假的值
bool类型只有两个值:
true-----真(本质是1)
false----假(本质是0)
bool类型占一个字节大小
作用: 用于从键盘获取数据
关键字: cin
语法: cin >> 变量
作用: 用于执行代码的运算
运算符类型 | 作用 |
---|---|
算术运算符 | 用于处理四则运算 |
赋值运算符 | 用于将表达式的值赋给变量 |
比较运算符 | 用于表达式的比较,并返回一个真值或假值 |
逻辑运算符 | 用于根据表达式的值返回真值或假值 |
作用: 用于处理四则运算
算术运算符包括以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +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; |
作用: 用于将表达式的值赋给变量
赋值运算符包括以下几个符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | a = 2;b = 3; | a = 2;b = 3; |
+= | 加等于 | a = 0;a += 2; | a = 2; |
-= | 减等于 | a = 5;a -= 2; | a = 2; |
*= | 乘等于 | a = 2;a *= 2; | a = 4; |
/= | 除等于 | a = 4;a /= 2; | a = 2; |
%= | 模等于 | a = 3;a %=2; | a = 1; |
作用: 用于表达式的比较,并返回一个真值或假值
比较运算符有以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | 0 |
!= | 不等于 | 4!=3 | 1 |
< | 小于 | 4<3 | 0 |
> | 大于 | 4>3 | 1 |
<= | 小于等于 | 4<=3 | 0 |
>= | 大于等于 | 4>=3 | 1 |
作用: 用于根据表达式的值返回真值或假值
逻辑运算符有以下符号:
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非 | !a | 如果a为假,则!a为真;如果a为真,则!a为假 |
&& | 与 | a&&b | 如果a和b都为真,则结果为真,否则为假 |
|| | 或 | a||b | 如果a和b有一个为真,则结果为真,二者都为假时,结果为假 |
C/C++支持最基本的三种程序运行结构:顺序结构、选择结构和循环结构
顺序结构:程序按顺序执行,不发生跳转
选择结构:依据条件是否满足,有选择的执行相应能力
循环结构:依据条件是否满足,循环多次执行某段代码
作用: 执行满足条件的语句
if语句的三种形式:
单行格式if语句:if(条件){条件满足执行的语句}
多行格式if语句:if(条件){条件满足执行的语句} else{条件不满足执行的语句}
多条件的if语句:if(条件1){满足条件1执行的语句}else if(条件2){满足条件2执行的语句}……else{都不满足执行的语句}
作用: 通过三目运算符实现简单的判断
语法: 表达式1 ? 表达式2 :表达式3
解释:
如果表达式1的值为真,执行表达式2,返回表达式2的结果
如果表达式1的值为假,执行表达式3,返回表达式3的结果
作用: 执行多条件分支语句
语法:
switch(表达式)
{
case 结果1:执行语句;break;
case 结果2:执行语句;break;
...
default:执行语句;break;
}
作用: 满足循环条件,执行循环语句
语法: while(循环语句){循环语句}
解释: 只要循环条件的结果为真,就执行循环条件
作用: 满足循环条件,执行循环语句
语法: do{循环语句}while(循环条件);
注意: 与while的区别在于do…while会先执行一次循环语句,在判断循环条件
作用: 满足循环条件,执行循环语句
语法: for(其实表达式;条件表达式;末尾表达式){循环语句}
作用: 在循环体中在嵌套一层循环,解决一些实际问题
**作用:**用于跳出选择结构或者循环结构
break使用的时机:
a. 出现在switch条件语句中,作用是终止case并跳出switch
b. 出现在循环语句中,作用是跳出当前的循环语句
c. 出现在嵌套循环中,跳出最近的内层循环语句
作用: 在循环语句中,跳出本次循环执行下一次循环
作用: 可以无条件跳转语句
语法: goto 标记;
解释: 如果标记的名称存在,执行到goto语句时,会跳转到标记的位置
所谓数组,就是一个集合,里面存放了相同类型的数据元素
特点:
1.数组中的每个数据元素都是相同的数据类型
2.数组是由连续的内存位置组成的
一维数组有三种定义方式:
a. 数据类型 数组名[数组长度];
b. 数据类型 数组名[数组长度] = {值1,值2,…};
c. 数据类型 数组名[] = {值1,值2,…};
一维数组名称的用途:
a.可以统计整个数组在内存中的长度
b.可以获取数组在内存中的首地址
int main()
{
int arr[10] = {101,2,3,4,5,6,7,8,9};
//获取整个数组所占空间大小sizeof(arr)
cout << "数组arr所占内存空间大小为:" << sizeof(arr) << endl;
//每个元素所占空间大小sizeof(arr[0])
cout << "每个元素所占内存空间大小为:" << sizeof(arr[0]) << endl;
//数组的元素个数为sizeof(arr)/sizeof(arr[0])
cout << "数组中的元素个数为:" << sizeof(arr) / sizeof(arr[0]) << endl;
//数组首地址为(int)arr
cout << "数组中的首地址为:" << (int)arr << endl;
//数组中第一个元素的地址为(int)&arr[0]
cout << "数组中的第一个元素的地址为:" << (int)&arr[0] << endl;
return 0;
}
//冒泡排序
void bubblesort(int arr[])
{
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0;i < len - 1;i++)
{
for (int j = 0;j < len - 1 - i;j++)
{
int temp = 0;
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0;i < len;i++)
{
cout << arr[i] << endl;
}
}
二位数组定义的四种方式:
a. 数据类型 数组名[ 行数 ] [ 列数];
b. 数据类型 数组名[ 行数] [ 列数 ] = {{数据1 ,数据2},{数据3,数据4}};
c. 数据类型 数组名[ 行数 ] [ 列数] = {数据1,数据2,数据3,数据4};
d.数据类型 数组名[ ] [ 列数] = {数据1,数据2,数据3,数据4};
二位数组数组名的用途:
a. 查看二维数组所占内存空间大小
b. 获取二位数组首地址
int main()
{
//二维数组数组名
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 << "二位数组行数:" << sizeof(arr) / sizeof(arr[0]) << endl;
cout << "二维数组列数:" << sizeof(arr[0]) / sizeof([0][0]) << endl;
//地址
cout << "二维数组首地址:" << arr << endl;
cout << "二维数组第一行地址:" << arr[0] << endl;
cout << "二维数组第二行地址:" << arr[1] << endl;
cout << "二维数组第一个元素地址:" << &arr[0][0] << endl;
cout << "二维数组第二个元素地址:" << &arr[0][1] << endl;
return 0;
}
作用: 将一段经常使用的代码封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能
函数的定义一般分为5个步骤:
1. 返回值类型
2. 函数名
3. 参数列表
4. 函数体语句
5. return表达式
语法:
返回值类型 函数名 (参数列表)
{
函数体语句
return 表达式
}
功能: 使用定义好的函数
语法: 函数名(参数);
所谓值传递,就是函数调用时实参将数值传入给形参;值传递时,如果形参发生改变,并不会影响实参。
void test01()
{
cout << "无参无返样式" << endl;
}
void test02(int a)
{
cout << "有参无返样式" << endl;
}
int test03()
{
cout << "无参有返样式" << endl;
return 10;
}
int test04(int a,int b)
{
cout << "有参有返样式" << endl;
int sum = a + b ;
return sum;
}
作用: 告诉编译器函数名称及如何调用。函数的实际主体可以单独定义。
函数的声明可以多次,但是函数的定义只能有一次。
示例:
//声明
int max(int a,int b);
//定义
int max(int a,int b)
{
return a > b ? a : b;
}
作用: 让代码结构更加清晰
函数分文件编写一般有四个步骤:
1. 创建后缀名为.h的头文件
2. 创建后缀名为.cpp的源文件
3. 在头文件中写函数的声明
4. 在源文件中写函数的定义
示例:
//swap.h文件
#include
using namespace std;
//实现两个数字交换的函数声明
void swap(int a,int b);
//swap.cpp文件
#include "swap.h"
void swap(int a,int b)
{
std::swap(a,b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
指针的作用:可以通过指针间接访问内存
a. 内存编号是从0开始记录的,一般用十六进制数字表示
b. 可以利用指针变量保存地址
指针变量定义语法: 数据类型 * 变量名;
在32位操作系统下,指针是占4个字节空间大小,不管是什么数据类型
在64位操作系统下,指针是占8 个字节空间大小
空指针: 指针变量指向内存中编号为0的空间
用途: 初始化指针变量
注意: 空指针指向的内存是不可访问的(0~255之间的内存编号是系统占用的,因此不可访问)
野指针: 指针变量指向非法的内存空间
const修饰指针有三种情况:
1. const修饰指针--------常量指针(指针指向可以改变,指向的值不可以改变)
2. const修饰常量--------指针常量(指针指向不可以改变,指向的值可以改变)
3. const既修饰指针,又修饰常量(指针指向和指向的值都不可以改变)
作用: 利用指针访问数组中元素
int main()
{
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int * p = arr; //指向数组的指针
for(int i = 0; i < 10; i++)
{
//利用指针遍历数组
cout << *p << endl;
p++;
}
return 0;
}
作用: 利用指针作函数参数,可以修改实参的值
如果不想改变实参,就用值传递;如果要改变实参,就使用地址传递
#iclude
using namespace std;
//值传递
void swap1(int a,int b)
{
int temp = a;
a = b;
b = temp;
}
//地址传递
void swap2(int * p1,int * p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
int a = 10;
int b = 20;
swap1(a,b); //值传递不会改变实参
cout << "a = " << a << " b = " << b << endl; //a = 10;b = 20;
swap2(&a,&b); //地址传递会改变实参
cout << "a = " << a << " b = " << b << endl; //a = 20;b = 10;
return 0;
}
案例描述: 封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr[10] = {4,3,6,9,1,2,0,8,7,5};
#include
using namespace std;
//冒泡排序函数
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;
}
}
}
}
int main()
{
int arr[10] = {4,3,6,9,1,2,0,8,7,5};
int len = sizeof(arr) / sizeof(arr[0]);
bubblesort(arr,len);
for(int i = 0; i < len; i++)
{
cout << arr[i] << " " ;
}
return 0;
}
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
语法: struct 结构体名称 {结构体成员列表};
通过结构体创建变量的方式有三种:
1. struct 结构体名 变量名;
2. struct 结构体名 变量名 = {成员1值,成员2值,… };
3. 定义结构体时顺便创建变量
//结构体定义
struct Student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
}stu3; //结构体变量创建方式3
int main()
{
//结构体变量创建方式1
struct Student stu1;
stu1.name = "小明";
stu1.age = 18;
stu1.score = 99;
cout << "姓名:" << stu1.name << " 年龄:" << stu1.age << " 分数:" << stu1.score << endl;
//结构体变量创建方式2
struct Student stu2 = {"小王",19,100};
cout << "姓名:" << stu2.name << " 年龄:" << stu2.age << " 分数:" << stu2.score << endl;
stu3.name = "小李";
stu3.age = 20;
stu3.score = 80;
cout << "姓名:" << stu3.name << " 年龄:" << stu3.age << " 分数:" << stu3.score << endl;
return 0;
}
作用: 将自定义的结构体放入到数组中方便维护
语法: struct 结构体名 数组名[元素个数] = { {} , {} , … };
示例:
//结构体定义
struct Student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
int main()
{
struct Student arr[2] = {
{"张三",17,89},
{"李四",19,90}
};
for(int i = 0; i < 2; i++)
{
cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 分数:" << arr[i].score << endl;
}
return 0;
}
作用: 通过指针访问结构体中的成员
利用操作符**->**可以通过结构体指针访问结构体属性
//结构体定义
struct Student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
int main()
{
struct Student stu = {"张三", 18 , 89};
struct Student * p = &stu;
cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;
return 0;
}
作用: 结构体中的成员可以是另一个结构体
示例: 每名老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
//学生结构体定义
struct Student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
//老师结构体定义
struct Teacher
{
//成员列表
int id; //职工编号
string name; //老师姓名
int age; //老师年龄
struct Student stu; //子结构体 学生
}
作用: 将结构体作为参数向函数中传递
传递方式有两种:值传递和地址传递
//学生结构体定义
struct Student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
//值传递
void PrintStudent1(Student stu)
{
cout << "姓名:" << stu.name << " 年龄:" << stu.age << " 分数:" << stu.score << endl;
}
//地址传递
void PrintStudent2(Student * stu)
{
cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;
}
作用: 用const来防止误操作
示例:
//学生结构体定义
struct Student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
//const使用场景
void PrintStudent(const Student * stu)
{
//stu->age = 100; //操作失败,因为加了const修饰
cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;
}
int main()
{
struct Student stu = {"张三",18,99};
PrintStudent(&stu);
return 0;
}