c/c++快速入门
[TOC]
变量类型:
整型:
短整型(short)、整型(int)和长整型(long long),其中短整型(short)一般用不到。int 也被称为 long int,long long 也被称为 long long int
- 对于整型 int 来说,一个整数占用 32 bit,即 4Byte,取值为(-2^31~+2^31-1)。一般10^9范围内的整数都可以定义成 int 型。
- long long 占用64bit,即8Byte,取值范围(-2^63~+2^63-1)超过10^9数量级的一般用 long long 进行定义。
- 注意:如果 long long 型赋值大于2^31-1 则需要在初值后面加上 LL
浮点型:
- 单精度 float:浮点数占用32 bit,有6~7位有效精度
- 双精度 double:浮点数占用 64 bit,有效精度15~16位
double 类型的变量在精度方面比 float 类型的高很多,对于一些精度要求比较高的地方,推荐使用 double 类型
字符型:
char c = ‘c’
注意:ASCII 码标准的范围是 0 ~127
0~9对应48~57
A~Z 对应65~90
a~z 对应97~122
小写字母比大写字母的 ASCII 码大32
转义字符
\用来进行转义
字符串常量
- char * s = “Hello, World!”
- char s[] = “Hello, World!”
这两种方法都是定义一个字符串常量,但前者是指针(这个字符串不知道在哪里,是处理参数,且动态分配空间)后者是数组(这个字符串在这里,作为本地变量空间被自动回收)
如果要构造一个字符串——数组
如果要处理一个字符串——指针
字符串字面量即一对双引号括起来的字符序列
字符串字面量的操作:
1 | char ch; |
则 ch 的新值将会是字母 b
布尔型
- 布尔型在 C++中可以直接使用,但是在 C 语言中必须添加 stdbool.h 的头文件才可以使用。
- bool 型变量 它的取值只能是 true 或者 false。
- 整型常量在赋值给布尔型变量时会自动转换为 true(非零)或者 false(零)
- true 和 false 在存储时分别为 1 和 0
1 |
|
1 | 0 1 1 |
强制类型转换
格式:
(新类型名)变量名
宏定义和 const 常量
常量定义方式一:宏定义
1 | define 标识符 常量 |
常量定义方式儿:const 定义
格式:
const 数据类型 变量名 = 常量;
注意:const 也能定义指针变量,如果定义了指针变量则被定义的指针变量的地址不可更改
运算符
注意位运算符:
a<<<x 整数 a 按二进制左移 x 位
a>>>x 整数 a 按二进制右移 x 位
a & b 整数 a 与 b 按二进制对齐,按位进行与运算(除了11得1,其他均为0)
- a | b 整数 a 与 b 按二进制对齐,按位进行或运算(除了0 0 得0,其他均为1)
- a^b 整数 a 与 b 按二进制对齐,按位进行异或运算(相同为0,不同为1)
- ~a 整数 a 二进制得每一位进行0到1,1到0变换操作
scanf 和 printf 的输入/输出
数据类型 | 格式 | 举例 |
---|---|---|
long long | %lld | scanf(“%lld”, &n) |
float | %f | scanf(“%f”, &n) |
double | %lf | scanf(“%lf”, &n) |
char | %c | scanf(“%c”, &n) |
char(字符串即 char 数组) | %s | scanf(“%s”, str) |
注意:在 scanf 中除了 char 数组整个输入不需要加 & 之外,其他变量类型都要加 &,因为数组变量本身就是地址(详见数组与指针的比较)
scanf 除了 %c 外,对其他格式符(如%d)的输入是以空白字符(即空格、tab)为结束判断标志。
1 |
|
1 | 10 20 |
1 | 10 20 |
printf 输出的注意
%md
%md 可以使不足 m 位的 int 型变量以 m 位进行右对齐输出,其中高位用空格补齐;如果本身超过 m 位,则保持不变。
如果需要左对齐,格式为:%-md
%0md
%0md 跟%md 的不同点在于,当变量不足 m 位时,将会用0来补齐前面的不足空位
%.mf
注意这里的%与 m 之间是有 • 点,意思为让浮点数保留 m 位小数输出,这个“保留”使用的是精度的“四舍六入五成双”规则。
如果要用四舍五入需要使用 round 函数
getchar 和 putchar 输入/输出字符
getchar 用来输入单个字符,putchar 用来输出单个字符
举例:
1 |
|
输入:
1 | abcd |
输出:
1 | acd |
这里的‘a’被 c1接受;‘b’虽然被接受,但是没有将它存储在变量中,第三个字符‘c’被 c2接受,第四个‘d’被 c3接受。
getchar 可以识别换行符,即如果输入中存在换行符\n(回车),则输出也会有回车
注释:
- /**/
- //
typedef:
typedef 可以给一个复杂的数据类型起一个别名,这在数据结构中经常用到:
例如可以将 long long 定义为 LL。即:
1 | typedef long long LL; |
注意:结束需要有分号 ( ; ) 而 define 后没有分号
常用的 math 函数
fabs(double x): 取绝对值
floor(double x):向下取整(即向小取整)
ceil(double x):向上取整(即向大取整)
sqrt(double x):返回 double 类型变量的算数平方根
pow(double r, double p):返回 r^p,r 的 p 次方
log(double x):返回 double 类型的自然对数e为底的对数。
需要注意的是,C 语言中没有对任意底数求对数得函数,如果需要则需要用到对数中的“换底公式” 来求任意底数的对数。
sin(double x)、cos(double x) 和 tan(double x):分别返回 double 型变量的正弦、余弦和正切的值。(x 为弧度制)
asin(double x)、acos(double x) 和 atan(double x): 分别返回 double 型变量的反正弦、反余弦和反正切的值。
round(double x):进行四舍五入,返回类型为 double,需要进行取整
示例:
1
2
3
4
5
6
7
int main(){
double db1 = round(3.40);
printf("%d", (int)db1);
return 0;
}
if语句
if (条件 A){
…
}
if(条件 A){
…
}else if(条件 B){
…
}else{
…
}
if语句的嵌套
if(条件 A){
…
if(条件 B){
…
}
}
switch 语句
格式:
1 | switch(表达式){ |
1 |
|
输出结果:
2
注意:
每个 case 下属语句没有使用大括号,是因为 case 本身默认把两个 case 之间的内容全部作为上一个 case 的内容
break 的使用是结束当前语句,不继续向下进行。如果上例子中去掉所有的 break,那么结果将会是:
2
3
Sad Input!
while 与 do … while
while(条件 A){
…
}
do{
…
}while(条件 A)
二者的区别就是 do … while 会至少先执行省略号中的内容一次。而 while 只有当条件满足时才能够进入 while 循环
for 循环
格式:
for(表达式 A; 表达式 B; 表达式 C){
…
}
break 和 continue 在 for 循环中的使用:
break 是终止循环,continue 是跳过 continue 之后的本次循环内容
数组
const int a[] = {1, 2, 3, 4};
这里数组变量已经是 const 指针,const 表明数组的每个单元都是 const int
必须通过初始化进行赋值
memset 对数组中每一个元素赋相同的值
对数组中每一个元素赋相同的值有两种方法:memset 函数和 fill 函数。使用 memset 函数必须在程序开头添加 string.h 头文件,使用 fill 函数需要用到 STL 的 algorithm 头文件
memset 函数的格式:
1 | memset(数组名, 值, sizeof(数组名)) |
下面直介绍对数组赋值0或-1
1 |
|
输出:
1 | 0 0 0 0 0 |
注意:memset 只能用于对数组进行赋0或赋1操作
字符数组
- 字符数组的初始化
1 |
|
输出:
1 | Good story! |
字符串数组直接通过赋值字符串来初始化(仅限于初始化,程序的其他位置不允许这样直接赋值整个字符串)
1 |
|
输出:
1 | Good story! |
- 字符数组的输入输出(有关字符串浅析见:C语言字符串浅析 Character String (C))
scanf 、printf
getchar、putchar:分别用来输入和输出单个字符,之前已详细说明,需要注意的是,getchar 可以识别空格和换行符
gets、puts:get 识别换行符 \n 作为输入结束,(因此,如果使用 scanf 完一个整数后,如果要使用 gets,需要先用 getchar 接受整数后的换行符);puts 用来输出一行字符串,即将一维数组(或二维数组的一维)在界面上输出,并紧跟一个换行。
示例:
1 |
|
sscanf 与 sprintf
sscanf 与 sprintf 的写法:
1
2sscanf(str, "%d", &n);
sprintf(str, "%d", n);sscanf 写法的作用是把字符串数组 str 中的内容以”%d”的格式写到 n 中(从左至右)
sprintf 写法的作用是把 n 以”%d”的格式写到 str 字符数组中(从左至右)
即:一个往后写,一个往前写
示例:
sscanf 示例:
1 |
|
- sprintf 示例:
1 |
|
sscanf 和 sprintf 进阶操作:
使用 sscanf 将字符数组 str 中的内容按 “%d:%lf,%s”的格式写到 int 型变量 n、double 型变量 db、char 型数组 str2中
1 |
|
输出结果:
1 | n = 2048, db = 3.14, str2 = hello |
使用 sprintf 将 int 型 n,double 型 db,char 型 str2,按照”%d:%.2f%s”格式写入字符数组 str 中
1 |
|
输出结果:
1 | str = 2048:3.14,hello |
C/C++ 函数
注意点:
当以数组作为函数参数时:
数组作为参数,在函数中对数组元素的修改等同于对原数组元素的修改(因为数组本身传递的就是指针)
指针
变量的定义
1 | int* p; |
- 星号的位置可以跟随数据类型之后,也可以放在变量名之前
示例:
1 |
|
注解: 只有定义的 p 才是指针,*p 代表指针所指向的存储空间的值
p++
1
2int *p;
p++p+1是指 p 所指的 int 型变量的下一个 int 型变量地址,这个”下一个”是指跨越了一整个 int 型(即4byte)。
malloc
- #include
- void * malloc(size_t size);
- 向 malloc 申请的空间的大小是以字节为单位的
- 返回的结果是 void * 的类型,需要类型转换为自己需要的类型
- (int *)malloc(n*sizeof(int));
数组与指针
C语言中数组名称可以作为数组的首地址使用
示例1:
1 |
|
示例2:
1 |
|
输入:
1 | 1 2 3 4 5 6 7 8 9 10 |
输出:
1 | 1 2 3 4 5 6 7 8 9 10 |
由于指针本身可以进行自增或者自减,因此上面的例子可以使用指针自增或者自减进行枚举
1 |
|
指针的减法:
1 |
|
输出:
1 | 0x7ffee6e9f860 |
注解: 1. 打印出的地址是16进制,p 与 q 之间相差的是20;因为相隔了5个距离的 int;2. 打印出的 q-p 是两个指针之间相差几个 int。
使用指针交换两个数
1 |
|
输出:
1 | before: x = 11, y = 22 |
同时需要注意:
- swap 函数里函数参数的传送方式是单向一次性的,其本身跟普通变量一样只是”值传递”,swap 函数对地址进行修改并不能对 main 函数里的地址进行修改。
- 对地址本身进行修改其实跟之前对传入的普通变量进行交换的函数是一样的作用,都只是副本,没法对数据产生实质性的影响,即相当于 int * 看作一个政体,传入的 a 和 b 都只是地址的副本。
引用:
引用的含义
- 引用不产生副本,而是只是给变量起了一个别名
- 新旧名字都是指同一个东西,对引用变量的操作就是对原变量的操作
- 引用:只需要在函数的参数类型后面加 “&”。
示例:
1 |
|
其中,函数的参数名和实际传入的参数可以不同
指针的引用
示例:
1 |
|
注意:引用是产生变量的别名,因此常量不可使用引用,于是上例中不可写成 swap(&a, &b),而必须使用指针变量p1和p2存放&a 和&b,然后把指针变量的参数写入。
引用作为返回值:
当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。
示例:
1 |
|
1 | previous value: |
结构体
结构体类型的概念:
结构体是一种构造类型,它是由若干成员组成的,其成员可以是一个基本数据类型,也可以是一个构造类型。例如:将“商品”定义为一个类型,则商品具有产品名称、形状、颜色、功能、价格和产地等。商品不能够使用之前学习过的任何一种类型表示,这时要自己定义一种新的类型,将这种自己定义的类型成为“结构体”。
声明结构体:
1 | struct 结构体名 |
e.g.:
1 | struct Product |
结构体变量的定义
先声明结构体类型,再定义结构体变量:
上面定义了 Product 结构体,可以用其进行定义结构体变量:
1
2struct Product product1;
struct Product product2;在声明结构体类型时,同时定义变量:
1
2
3
4struct 结构体名
{
成员列表;
}变量名列表;其中的变量名列表可以定义多个
e.g.:
1
2
3
4
5
6
7
8
9struct Product
{
char name[10];
char shape[20];
char color[20];
char func[20];
int price;
char area[20];
}product1,product2;直接定义结构体类型变量:
1
2
3
4struct
{
成员列表;
}变量名列表;e.g.:
1
2
3
4
5
6
7
8
9struct
{
char name[10];
char shape[20];
char color[20];
char func[20];
int price;
char area[20];
}product1,product2;
注意:
结构体里能够定义除了自己本身之外的任何数据类型,但是能够定义自身类型的指针变量:
1 | struct node{ |
结构体变量的引用
e.g.:
product1.name = “ipad”
结构体类型的初始化
1 | struct Student |
结构体数组
1 | struct Student |
结构体指针
一般形式:
1 | 结构体类型 *指针名 |
使用结构体成员的方法:
- 点运算符引用结构成员:
1 | (*pStruct).成员名 |
例:
1 |
|
- 第二种方法使用指向运算符☝🏻引用结构成员:
e.g.:
1 | pStruct->成员名; |
三种引用结构体成员的方法等价:
假设 student为结构体变量,pStruct 为指向结构体变量的指针,则以下三种方法等价
- student.成员名
- (*pStruct).成员名
- pStruct->成员名
e.g.:
1 |
|
指向结构体数组的指针
概述:结构体指针变量不但可以指向一个结构体变量,还可以指向结构体数组,此时指针变量的值就是结构体数组的首地址
e.g.:
1 | struct Student *pStruct; |
1 |
|
C++ 的 cin 和 cout
cin
cin 的输入不指定格式:
输入示例
1 | int a; |
cout
cout 的输出:
1 | cout << a << b << c << endl; |
其中endl 是换行,与 “\n”作用相同