c++
main函数
- 入口函数,执行程序会从main函数开始
- 一个程序只能有一个main函数
- main函数一般返回整数,记录程序异常退出码,或无异常返回 0
- void main(){ *** } void函数无返回值,但不建议使用
- c语言关键字必须
#include <iostream>
之后使用,不需要名称空间 - 格式:
int main()
{
printf("hello world\n");
system("pause");
return 0;
}
基本组成
预处理编译指令:
# include <filename>
导入头文件- 通常用
<filename>
来导入标准头文件,"filename"
来导入自定义头文件
- 通常用
主函数:
int main(int argc, char* argv[])
一个项目中必须有且只能有一个int main函数,
main函数为程序入口,执行时会从main函数开始执行
int定义返回值类型, int argc定义输入值数据类型
不需要返回值是定义类型 void
using namespace std
相当于 from std import * , 不推荐使用,using std::cout
相当于 from std import cout, 对于函数的单独调用,防止多余的函数散落在全局域中c++中标准库的名称空间都是std
强制类型转换
int a = 10; int *ip = a; char *cp = (char *)ip;
编译过程
预处理
- 处理#开头的语句
- 将``#include`关联的文件复制到当前文本里(头文件展开)
if (0){code1}
/* */
//
- 删除注释
- 条件编译等
- 生成 .i 文件
- 处理#开头的语句
编译
- 语法检查,转换成汇编代码
- 生成 .s 文件
汇编
- 汇编后转换成二进制
- 生成 .o 文件
链接
- 将依赖库链接到exe中
- 生成启动代码调用 main 函数
- 生成exe
常用关键字
system:执行CMD的命令
输入 scanf,碰到换行、Tab、换行会结束
gets_s(s1, 128)
(_s后缀代表安全的)碰到换行或给定参数(这里是128)停止
输出 printf
对于int、char、double等,使用scanf需要取地址
变量(标识符)
定义域
跨文件引用变量,先用
extern
声明static
限制在当前文件内使用的变量变量使用前必须定义类型,可同时赋值,如:int num = 5;
声明变量并赋值的方法
int a = 12;
int a = { 12 };
int a(12);
int a{12};
连续赋值语句顺序从右向左依次执行, a = b = 5;相当于b=5;a=b;
c++标准为首次使用变量时声明,c标准则将所有变量声明放在开头
定义常量
#define
宏常量定义,全局,写在开头,属于c语言遗留语法const
常量限定符,将一个变量定义为常量 :const int Months = 12;
char 字符
- 只占一个字节
- 存储10进制的ASCII码
- 0 - 9 < A - Z < a - z
- 48 - 57 < 65 - 90 < 97 - 122
- \n 010 \t 009 \\ 092
- \0为终止符,字符串中, \0后面的部分会忽略掉
字符串
以 ‘\0’ 结尾的字符数组
字符串长度
- strlen,需要导入<string.h>
size_z len = strlen(s1)
- 如果一个字符串末尾没有’\0’,调用strlen会导致内存溢出
- sizeof ,计算结果需要建议,因为末尾的 \0是不显示的,正常不应算入长度
- strlen,需要导入<string.h>
字符串拷贝
- strcpy_s: 完整拷贝整个字符串,目标字符串必须必源字符串长
- strncpy: 拷贝指定长度的部分
字符串追加
- strcat
- strncat
格式化字符串
- %s 输入字符串
- %f 输入浮点数
- %llu
- %d
常量
定义常量
#define 宏常量定义,全局,写在开头
const 常量修饰符,将一个变量定义为变量
运算符
三目运算符
<表达式1> ?<表达式2> :<表达式3>
如果表达式1为真,返回表达式2的结果,如果为假则返回表达式3的结果
三目运算符返回的是变量本身,可以继续赋值
int a=10; int b=2; a>b?a:b == 100 // Result:a=100, b=2
除法与取模
- 两个整数的除法运算结果仍为整数
- 取模运算只能在整数间运算
或:|| 与:&& 非:!
前置递增(递减)与后置递增(递减)
逻辑机构
- switch(表达式){case 结果 : break;}
- 当case 语句执行后,后面如果没有break打断,则后面的case不再判断,直接执行
- 为防止执行多个结果,每个case下都应有break打断循环
- default默认结果
- while{} 与do()while{}
- for 循环
- for each
- for(int i=0; i<100;i++){}
- goto FLAG FLAG:
- 跳转到对应行数运行,不推荐使用,降低可读性
数组
定义方式
- 数据类型 数组名[数组长度];
- 数据类型 数组名[数组长度] = {值1, 值2 … };未赋值的元素会用0或空字符填充
- 数据类型 数组名[ ] = {值1, 值2 … };
特点
- 放在连续的内存空间中
数组元素类型相同
定义后未赋值的元素用随机数填充
数组名用处
统计数组在内存中的长度
sizeof(arr)
求数组长度
sizeof(arr) / sizeof(0)
获取数组在内存中的首地址 , 直接打印数组名,返回内存首地址,默认返回16进制.
也可以去首元素地址, 取址
&arr[0]
数组名一个常量,不可赋值
函数传参传入数组名,函数的形参会转换成数组第一个元素的指针(内存地址)
二维数组
- 定义方法同一维数组,定义元素数先行后列
- 定义二维数组时赋值可以是平摊的元素,系统会根据行元素的元素数量分割
- 行数可以省略,列数不可省略
- 取值方式
arr[行][列]
functions
-
指针
定义方式:
<数据类型> * <指针名> = &<变量名>
指针占用内存,4个字节,32位
使用方式:
*<指针名>
; 数组需要用大括号括起来:int arr_new[] = { *P };
P为一个数组的指针- ```c++
int a = 10;
int* ip = &a;
char* cp = (char *)ip; // 指针类型转换
cout << *cp; // 返回指针的值- 空指针:初始化指针变量,空指针指向的内存是不可访问的 - int * P = NULL 如果初始化时不指向NULL,指向的内存地址是不确定的 - 0-255之间的内存地址是系统占用的,因此不可访问 - 常量指针:const int *p = &a; - 特点:指针的指向可以修改,但是指针指向的值不可以修改 - 指针常量:int * const p = &a; - 特点:指针的指向不可以修改,但是指针指向的值(*p)可以修改 - 无论指针常量还是常量指针都不影响指向同一内存地址的**变量**修改内存中的内容 - 指针移动 p + 1 ,代表向后移动一个单位地址(根据数据类型移动字节数不同 ) ## 指针与数组 - 数组名是一个不可修改的指针,记录内存地址, - 将一个数组名作为参数传递给函数式,会被编译器转换为指针,指向数组的第一个值 - 定义函数时,形参用参数 void print_array(int arr[]) - \*(arr[0] + 1) 通过指针获取数组的元素,指针后加的数值代表后移多少个元素* - ```c++ int a[] = {0,1,2,3,4,5,6}; const int * p = a; cout << *p << endl << *(p+2) << endl;
- ```c++
引用
&在此不是求地址运算,而是起标识作用。
类型标识符是指目标变量的类型。
声明引用时,必须同时对其进行初始化。
引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。
结构体创建
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
定义
struct 数据结构名 {结构体成员列表};
创建结构体变量
#include <iostream> #include string using namespace std; struct student { string name; int age; int score; }; int main() { student s = { "张三", 20, 120 }; student * p = &s; cout << p->name << endl; }
嵌套结构体
#include <iostream> #include <string> #include <vector> using namespace std; typedef struct Student { public: string name; int age; int score; }student; typedef struct Teacher { public: string name; student students[3]; int num; }teacher; int main(void) { teacher _teacher = {.name = "aa", .students = { [0] = {.name = "a", .age = 12, .score = 1}, [1] = {.name = "b", .age = 12, .score = 1}, [2] = {.name = "c", .age = 12, .score = 1} }, .num = 3 }; cout << _teacher.students[0].age << endl; }
数据类型
C++对基本类型进行分类,形成了若干个族。类型
signed char
、short
、int
和long
统称为符
号整型;它们的无符号版本统称为无符号整型;C++11新增了long long
。bool
、char
、wchar_t
、符号整数
和无符号整型
统称为整型;C++11新增了char16_t
和char32_t
。float
、double
和long double
统称为浮点型。整数和浮点型统称算术(arithmetic)类型。内存的基本单位是位(bit), bit可以看做开关有0、1两种表示
通常一个字节有8
bit
(不同的系统里也有可能是16/24/32/64),则一个字节可以表示0-255判断数据类型的方法
#include <iostream> #include <typeinfo> int main(){ using namespace std; int v1 = 1; cout << typeid(v1).name() << endl; return 0; }
bool
布尔变量的值可以是true或false,在c++中与0/1可互换
十进制
30
, 8进制027
, 16进制0x27
, 不同进制数字只是方便输入,在系统中存储都会转换为2进制,而cout
时都是输出10进制整型
- short 2字节(至少16位)
- int 2字节
- long 4字节
- long long 4字节
- 可以使用
sizeof
来获取占用字节数,climits
类中定义常量CHAR_BIT来记录每个字节的位数 - 可使用unsigned来定义无符号类型,
- 数值超出范围不会报错,但会返回意料之外的结果,导致程序bug,要慎重选择数据类型
- 当有大型整型数组或明确有节省内存的需求时才有必要使用short
- 代码中的整数常量除非是数值过大不能存储为int或者使用后缀指定类型,否则在编译过程中都将会存储为int类型,后缀U表示无符号,L表示long,大小写与顺序不限
- 十六进制由于常会用来表示内存地址,所以系统会优先尝试保存为unsigned int
浮点数
指数表示法:
d.dddE+n
指的是将小数点向右移n位,而d.dddE-n
指的是将小数点向左移n位。之所以称为“浮点”,就是因为小数点可移动- float 至少允许32位有效数字
- double 至少允许48位有效数字,且不少于float
- long double 和double一致
- 指数范围在+-37, 可以从头文件
cfloat
或float.h
中找到系统的限制 cout.setf(ios_base::fixed, ios_base::floatfield);
使用这条命令可以打印小数点后多余的0- 常数默认存储为double类型
- 浮点数相比整数而言,精度更低,运算更慢,但是表示的数值范围更大
char 字符
- 只占一个字节
- 存储10进制的ASCII码
- 0 - 9 < A - Z < a - z
- 48 - 57 < 65 - 90 < 97 - 122
- \n 010 \t 009 \\ 092
- 可以使用
cout.put()
将一个整数输出为对应的字符 - 对于中文等其他ASCII码无法表示的字符可以用
wchar_t
,char16_t
,char32_t
等表示
强制类型转换
int a = 10; float a = (float)a int *ip = a; char *cp = (char *)ip;
运算符
三目运算符
int a = <表达式1> ?<表达式2> :<表达式3>
如果表达式1为真,返回表达式2的结果,如果为假则返回表达式3的结果
三目运算符返回的是变量本身,可以继续赋值
int a=10; int b=2; a>b?a:b == 100 // (bool ? true_v : false_v) //x = true_v if bool else false_v // Result:a=100, b=2
除法与取模
- 两个整数的除法运算结果仍为整数
- 取模运算只能在整数间运算
或:|| 与:&& 非:!
前置递增(递减)与后置递增(递减)
& 获取变量指针
位运算
整型提升:
- 如果有一个操作数的类型是long double,则将另一个操作数
转换为long double。 - 否则,如果有一个操作数的类型是double,则将另一个操作
数转换为double。 - 否则,如果有一个操作数的类型是float,则将另一个操作数
转换为float。 - 否则,说明操作数都是整型,因此执行整型提升。
- 在这种情况下,如果两个操作数都是有符号或无符号的,且
其中一个操作数的级别比另一个低,则转换为级别高的类型。 - 如果一个操作数为有符号的,另一个操作数为无符号的,且
无符号操作数的级别比有符号操作数高,则将有符号操作数转换为无符
号操作数所属的类型。 - 否则,如果有符号类型可表示无符号类型的所有可能取值,
则将无符号操作数转换为有符号操作数所属的类型。 - 否则,将两个操作数都转换为有符号类型的无符号版本。
- 如果有一个操作数的类型是long double,则将另一个操作数
逻辑机构
- switch(表达式){case 结果 : break;}
- 当case 语句执行后,后面如果没有break打断,则后面的case不再判断,直接执行
- 为防止执行多个结果,每个case下都应有break打断循环
- default默认结果
- while{} 与do()while{}
- for 循环
- for each
- for(int i=0; i<100;i++){}
- goto FLAG FLAG:
- 跳转到对应行数运行,不推荐使用,降低可读性
格式化字符串
%s 字符串
%d 整数
函数
- c++中不可以嵌套定义函数
- 函数传参
- 值传递
- 地址传递
分文件的编写
- 头文件(.h)中声明函数
- .cpp文件中定义函数
- 源文件中调用
#include "***.h"
c语言关键字
关键字 | 说明 |
---|---|
auto | 声明自动变量 |
break | 跳出当前循环 |
case | 开关语句分支 |
char | 声明字符型变量或函数返回值类型 |
const | 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变 |
continue | 结束当前循环,开始下一轮循环 |
default | 开关语句中的”其它”分支 |
do | 循环语句的循环体 |
double | 声明双精度浮点型变量或函数返回值类型 |
else | 条件语句否定分支(与 if 连用) |
enum | 声明枚举类型 |
extern | 声明变量或函数是在其它文件或本文件的其他位置定义 |
float | 声明浮点型变量或函数返回值类型 |
for | 一种循环语句 |
goto | 无条件跳转语句 |
if | 条件语句 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数返回值类型 |
register | 声明寄存器变量 |
return | 子程序返回语句(可以带参数,也可不带参数) |
short | 声明短整型变量或函数 |
signed | 声明有符号类型变量或函数 |
sizeof | 计算数据类型或变量长度(即所占字节数) |
static | 声明静态变量 |
struct | 声明结构体类型 |
switch | 用于开关语句 |
typedef | 用以给数据类型取别名 |
unsigned | 声明无符号类型变量或函数 |
union | 声明共用体类型 |
void | 声明函数无返回值或无参数,声明无类型指针 |
volatile | 说明变量在程序执行中可被隐含地改变 |
while | 循环语句的循环条件 |
常用库
c++标准库不像C语言一样需要带有后缀
iostream
, c语言对应stdio.h
+ctype.h
输入输出,字符类cout <<
插入到标准输出流对象, 可以连续使用<<插入, 建议分行书写同一条命令cin >>
将数据输入到程序中cin.get()
获取输入,按回车结束获取cin >> x >> y
将数据输入到两个变量中endl
换行; 强制刷新数据流
string
字符串类cstring
,c语言对应string.h
字符串处理函数cmath
, c语言对应math.h`数学函数cstdlib
, c语言对应stdlib.h
内存动态分配函数- std,标准库名称空间
跳转语句
goto Flag
跳转到 Flag:
- 使用冒号定义标记