C++入门(二) (算法竞赛)

🌊用有趣的言语来阐述苦涩难懂的代码世界,让每一个技术都充满风趣!
🔭个人主页:散峰而望
🚀学习方向: C/C++等方向
📌专栏系列:
- 📖《C语言:从基础到进阶》
- 📚《编程工具的下载和使用》
- 🚀《C语言刷题》
- ⚖️《算法竞赛从入门到获奖》
💬人生格言:冀以尘雾之微,补益山海,荧烛末光,增辉岁月。
🎬博主简介



文章目录
- 前言
- 3. 数据类型
- 3.1 字符型
- 3.2 整型
- 3.3 浮点型
- 3.4 布尔类型
- signed和unsigned
- 3.6 数据类型长度
- 3.6.1 sizeof操作符
- 3.6.2 各种数据类型长度
- 3.7 各类取值范围
- 3.8 typedef
- 3.9 练习
- 4. 变量与常量
- 4.1 变量的创建
- 4.2 变量的初始化
- 4.3 变量的分类
- 4.3.1 全局和局部
- 4.3.2 未初始化状态下的全局变量和局部变量
- 4.4 常量
- 4.4.1 字面常量
- 4.4.2 #define定义常量
- 4.4.3 const定义常量
- 4.5 练习
- 结语
前言
前面我们已经对C++程序有着初步的了解,接下来让我们进一步去探讨数据类型和变量与常量吧。
3. 数据类型
因为电脑识别的是二进制,所以我们输入的数据一般要转换为二进制后识别,再转换从屏幕上输出。在这个过程中有一些数据,转换为二进制数据后,会有数据重叠。故需要一些定义来将此区分开来,因此数据类型应运而生。
C++提供了丰富的数据类型来描述生活中的各种数据。比如:使用整型类型来描述整数,用字符类型来描述字符,用浮点数类型来描述小数。
所谓类型,就是相似的数据拥有的共同特征,编译器只有知道了数据类型,才知道怎么操作数据。
3.1 字符型
char //character的缩写
在键盘上可以敲出各种字符,如:啊a,g,$,@等,这些符号被称为字符。字符是单括号括起来的,如:‘c’,‘h’,‘&’。为了描述这些字符,定义出一种类型,就是字符型,C语言与C++中就是char。
ASCII编码
我们都知道计算机中数据都是以二进制的形式储存,那么这些字符在内存中分别以什么样的二进制储存呢?为了方便相互通信,美国ANSI出台了一个标准ASCII编码,C语言中字符就遵循ASCII编码的方式。参考:https://zh.cppreference.com/w/cpp/language/ascii

我们不需要记住所有的ASCII码表中的数字,使用时查看就行。不过我们最好掌握几组比较重要的:
- 字符A ~ Z的ASCII码值从65 ~ 90
- 字符a ~ z的ASCII码值从97 ~1 22
- 对应的大小写字符(a和A)的ASCII码值相差32
- 数字字符0 ~ 9的ASCII码值从48 ~ 57
- 换行\n的ASCII值是:10
- ASCII码值从0 ~ 31这32个字符是不可打印字符,无法打印在屏幕上观察
从某一方面来说ASCII码值本质上字符
代码如下:
#include <iostream>
using namespace std;int main()
{char ch1 = 'a';cout << ch1 << endl;char ch2 = 97;cout << ch2 << endl;return 0;}

3.2 整型
整型类型是对所有整数的抽象,为了能对整数形成统一的类型标识,就诞生了整型。在C语言和C++整型中分为四大类:short,int,long,long long。
(int可以省略,除了表示整型时)
short [int] //单精度浮点型
int //整型
long [int] //长整型
long long [int] //长长整型
3.3 浮点型
浮点型是对所有实数(小数)的抽象,为了能对实数形成统一的类型标识,就诞生了浮点型。浮点型有三类
float //单精度浮点型
double //双精度浮点型
long double //更长的双精度浮点型
代码演示:
int main()
{char ch = 'a';short s1 = 8;short int s2 = -2;long r1 = 10;long int r2 = 100;long w1 = 1000;long int w2 = 1010;float f = 5.2f;double b = 8.8;long double ld = 9.9;return 0;
}
注意:
在C/C++中小数的书写形式:
5.20; //编译器会默认为double类型
3.14f; //编译器会默认为float类型
1e5; //科学计数法的形式,意思1.0*10^5
1e5+10; //1*10^5+10=100010

3.4 布尔类型
C++有一种类型叫:bool(布尔类型),布尔类型的变量的值可以是true或false,这种类型的变量专门用来表示真或假的。当然在C和C++中,0表示假,非0表示真,有时候不使用bool类型也能表达相同的逻辑。
bool
代码示例:
int main()
{bool a = true;if (a)cout << "haha" <<endl;return 0;
}

int main()
{bool a = 0;if (a)cout << "haha" <<endl;return 0;
}

signed和unsigned
signed和unsigned关键字修饰字符型和整型类型。
signed关键字,表示一个类型带有正负号,包含负值;比如:温度。
unsigned关键字,表示该类型不带有正负号,只能表示零和正整数,比如:年龄。
有了signed 和 unsigned 的修饰,字符和整型类型其实更加丰富,可以有以下这些:
//字符型
char
signed char //有符号的字符类型
unsigned char //无符号的字符类型 //短整型
short [int]
[signed] short [int] //有符号的短整型
unsigned short [int] //无符号的短整型 //整型
int
[signed] int //有符号的整型
unsigned [int] //无符号的整型//长整型
long [int]
[signed] long [int] //有符号的长整型
unsigned long [int] //无符号的长整型 //更长的整型
long long [int]
[signed] long long [int] //有符号的
unsigned long long [int] //无符号的
对于int类型,默认是带有正负号的,也就是说int等同于signed int。
由于这是默认情况,关键字signed一般都省略不写,但是写了也不算错。
signed int a; //等同于int a,一般不写signed
int类型也可以不带正负号,只表示非负整数。这时就必须使用关键字unsigned声明变量。
unsigned int a; // unsigned int:无符号整数类型
变量声明为unsigned的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。
比如,16位的signed short int的取值范围是:-32768~32767,最大是32767;而
unsigned short int的取值范围是:0~65535,最大值增大到了65535。32位的signed
int的取值范围可以参看climits中给出的定义。
下面的定义是Dev-C++环境中,climits中相关定义,其实如果仔细看climits中也是包含的limits.h。
#define SHRT_MIN (-32768) //有符号16位整型的最小值
#define SHRT_MAX 32767 //有符号16位整型的最大值
#define USHRT_MAX 0xffffU //无符号16位整型的最大值
#define INT_MIN (-2147483647 - 1) //有符号整型的最小值
#define INT_MAX 2147483647 //有符号整型的最大值
同时,unsigned int里面的int可以省略,所以上面的变量声明也可以写成如下:
unsigned a;
字符类型char也有signed和unsigned。
signed char c; // 范围为 -128 到 127
unsigned char c; // 范围为 0 到 255
注意:
char类型是signed char 还是 unsigned char,由编译器决定。大部
分的编译器上char就是signed char。所以一般情况下最好标明是否有正负号
3.6 数据类型长度
每⼀种数据类型都有自己的长度,使用不同的数据类型,能够创建出⻓度不同的变量,变量长度的不同,存储的数据范围就有所差异。
3.6.1 sizeof操作符
sizeof 是⼀个关键字,也是操作符,专门是用来计算特定数据类型的长度的,单位是字节。
sizeof 操作符的操作数可以是类型,也可是变量名或者表达式, sizeof 的操作数如果不是类型,是表达式的时候,可以省略掉后边的括号的。
sizeof( 类型 )
sizeof 表达式
sizeof 的计算结果是 size_t 类型的, size_t 指的是⽆符号整数(该类型包含了所有可能的unsigned int , unsigned long , unsigned long long 等类型,具体是取决于编译器的)。
代码演示:
#include <iostream>
using namespace std;int main()
{int a = 10;cout << sizeof(a) << endl;cout << sizeof a << endl; //a是变量的名字,可以省略掉sizeof后边的(),但不建议去掉 cout << sizeof(int) << endl;return 0;}
3.6.2 各种数据类型长度
在Dev-C++下输出:
#include <iostream>
using namespace std;int main()
{cout << sizeof(char) << endl;cout << sizeof(bool) << endl;cout << sizeof(short) << endl;cout << sizeof(int) << endl;cout << sizeof(long) << endl;cout << sizeof(long long) << endl;cout << sizeof(float) << endl;cout << sizeof(double) << endl;cout << sizeof(long double) << endl;return 0;
}

这些数据类型的长度意思是,向内存申请空间(创建变量),不同的数据类型申请的空间是不一样的,相当于不同的人住着不同大小的房子。下面这张图可以让你更好的理解数据类型的长度:

3.7 各类取值范围
前面我们已经了解了C++的各种数据类型,不同的数据类型长度是有差异的。而长度差异决定了该变量能存储值的大小。
为了使变量与存储的值相匹配,我们就需要在不同的情况下选择不同的类型。
下面是不同数据类型的取值:
| 类型 | 取值范围 | 速记最小值 | 速记最大值 |
|---|---|---|---|
| char | -128~127 | -2^7 | 2^7-1 |
| unsigned char | 0~255 | 0 | 2^8-1 |
| short | -32768~32767 | -2^15 | 2^15-1 |
| unsigned short | 0~65535 | 0 | 2^16-1 |
| int | -2147483648~2147483647 | -2^31 | 2^31-1 |
| unsigned int | 0~4294967295 | 0 | 2^32-1 |
| long | -2147483648~2147483647 | -2^31 | 2^31-1 |
| unsigned long | 0~4294967295 | 0 | 2^32-1 |
| long long | -9223372036854775808~9223372036854775807 | -2^63 | 2^63-1 |
| unsigned long | 0~18446744073709551615 | 0 | 2^64-1 |
为了代码的可移植性,和方便记忆,需要知道某种整数类型的极限值时,经常使用这些速记的符号。
limits.h文件中说明了整型类型的取值范围。(C++中头文件的名字是< climits >)
float.h这个头文件中说明浮点型类型的取值范围。(C++中头文件的名字是< cfloat >)
3.8 typedef
C++中有⼀个关键字是和类型有关的,是用来给类型重命名的。当有⼀个类型⽐较复杂的时候,可以简化类型。 typedef 在竞赛中经常使用,可以提升编码速度。typedef使用的基本语法形式:
typedef 旧类型名 新类型名;
比如:
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
上面的代码意思是将unsigned int类型重命名为ui,使用ui和使用unsigned int是一样的,其他几个一样。
3.9 练习
了解完数据类型,那么来几道题趁火打铁一并练习一下吧!练习题后面会详细的进行讲解。
整数
打印字符
倒序
整型数据类型存储空间大小
4. 变量与常量
4.1 变量的创建
前面我们细致的对类型进行讲解,那么类型是用来干什么的呢?类型是用来创建变量的。
变量的语法形式如下:
data_type name;| || |
数据类型 变量名
int age; //整型变量
char ch; //字符变量
double weight; //浮点型变量
变量的命名规则:
• 变量名只能由字母、数字和下划线组成,且必须以字母或下划线开头。
• 变量名不能以纯数字开头,也不能包含特殊字符,如空格、连字符等。
• 变量名不能使用语言的关键字,如int、char、if等。
• 变量名应具有意义,有助于理解变量的含义和用途。
• 变量名应简短明了,避免使用过⻓的名称。
• 变量名应区分大小写,例如myVariable和myvariable被视为两个不同的变量。
4.2 变量的初始化
变量只有在创建时给一个初始值,才叫初始化。
int age = 18;
char ch = 'x';
double v = 3.14;
但是像下面这样的并不是初始化,并没有在创建时给初始值:
int n;
n = 10;
4.3 变量的分类
4.3.1 全局和局部
-
全局变量:
在大括号外部定义的变量就是全局变量。全局变量的使用范围更广,整个工程中想使用,都是有办法使用的。 -
局部变量:
-
在大括号内部定义的变量就是局部变量。局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的
int a = 2025; //全局变量
int main()
{int n = 2; //局部变量 cout << a << endl;cout << n << endl;return 0;
}

如果局部和全局变量,名字相同呢?
int n = 2025; //全局变量
int main()
{int n = 2; //局部变量 cout << a << endl;cout << n << endl;return 0;
}

可以看到局部变量和全局变量同名的时候,局部变量优先使用。
4.3.2 未初始化状态下的全局变量和局部变量
- 未初始化的局部变量
int main()
{//局部变量int a;char c;float f;double d;cout << "int:" << a << endl;cout << "char:" << c << endl;cout << "float:" << f << endl;cout << "double:" << d << endl;return 0;
}

- 未初始化的全局变量
int a;char c;float f;double d;
int main()
{cout << "int:" << a << endl;cout << "char:" << c << endl;cout << "float:" << f <<
endl;cout << "double:" << d <<
endl;return 0;}

上面是在Dev-C++上面实施,如果在vs2022编辑器上面运行会出现什么效果:
- 局部变量直接报错

- 全局变量没有问题

这些差异取决于不同的编译器,不同的编译器对未初始化的全局和局部变量有所不同。特别是使用未初始化的局部变量可能会导致不可预测的行为或运行时错
误,因此局部变量建议初始化。
提示
如果一个题目既可以使用全局变量,又可以使用局部变量,那怎么选择呢?
如果是在竞赛中:
能使用全局变量,一般会直接是全局变量,这样的好处是:
- 变量不需要初始化,因为默认会初始化为0,这样写会比较快
- 很多时候,会避免传参,因为全局变量到处都可以使用。(后面会讲)
所以在在竞赛中其实哪种方便就使用哪种,全局变量的使用很常⻅。
但是在企业里软件开发的工程实践中一般建议:能使用局部变量的,尽量少使用全局变量。
因为企业级的开发,代码量比较大,全局变量在任意地方都可以使用,这样就变得不可控。
4.4 常量
常量就是不能被改变的值,通常我们会使用三种常量:
• 字面常量
• #define定义的常量
• const定义的常量
下面分别介绍一下。
4.4.1 字面常量
整型常量:100,-5,0,0x123整型常量一般可以写成10进制、8进制、16进制。
10进制数字,如:6、17、22、123
8进制数字,一般是数字0开头的,比如:012,016
16进制数字,一般是0x开头的数字,比如:0x123,0xFF
字符常量:‘a’
浮点型常量:3.14,1E6(科学计数法的形式)
4.4.2 #define定义常量
define定义常量语法形式:
#define 常量名 内容
代码举例:
#define M 100
#define CH 'x'
#define PI 3.14159
int main()
{cout << M << endl;cout << CH << endl;cout << PI << endl;return 0;
}

这里定义的M、CH、PAI都是常量,可以直接使用,但是不能被修改。比如:
#define M 100
#define CH 'x'
#define PI 3.14159
int main()
{M = 20;cout << M << endl;cout << CH << endl;cout << PI << endl;return 0;
}

使用#define 定义常量的时候是不关注类型的,只关注常量的名字叫啥,常量的值是啥,编译在处理这种常量的时候就是直接替换,在出现常量名字的地方,通通替换成常量的内容。
4.4.3 const定义常量
除了上面的方式之外,C++中还可以使用const来定义常量,这种常量会有具体的类型。比#define定义常量更加严谨。语法形式如下:
const 类型 常量名字 = 常量值;
比如:
const double PI = 3.14159;
使用一下:
const double PI = 3.14159;
int main()
{int r = 0;cin >> r;cout << "周⻓:" << 2 * PI * r << endl;cout << "面积:" << PI * r * r << endl; //PI = 3.14;//这种写法是错误的,常量不能被修改 return 0;
}

习惯上,这种常量的名字一般会写成大写,而普通变量的名字不会全大写,这样就可以做一个区分。
使用const定义的常量的好处:
• 增加了程序的可读性,PI比3.14159更加容易理解和书写、使用。
• 增加了程序的可维护性,如果改变常量的值,只要在定义的部分修改,使用的地方也就随之改变了,做到了"一改全改"的效果。
• 常量是不能修改的,当然const定义的常量自然也不能修改。

未来会经常使用const定义常量,后期我们慢慢观察。
4.5 练习
了解完变量和常量,那么来几道题趁火打铁一并练习一下吧!练习题后面会详细的进行讲解。
买票
A+B问题
结语
希望这篇文章可以助各位敲开算法竞赛的大门,初识C++的奥秘,去探寻算法世界的精妙。同时愿诸君能一起共渡重重浪,终见缛彩遥分地,繁光远缀天。


