真题
⭐考试技巧⭐
- 先想暴力做法(时间复杂度较高的做法) --> 拿到部分分数
- 根据数据范围判断正确的时间复杂度,根据时间复杂度确定出这道题的算法范围。
- 暴力做法:模拟题干中的过程。
- 时间复杂度:https://www.acwing.com/blog/content/32/
- 基础算法:
- 前缀和、二分、差分(入门算法)
- DP(蓝桥杯中出现次数很多)
- 搜索(BFS、DFS) --> 通常是打暴力
- 图论(最短路、最小生成树)
- 数据结构
算法、写题技巧
暴力枚举
当数据大小只有几十的时候,大概率是暴力枚举。暴力枚举往往就是正确答案。暴力枚举的方式往往是DFS。
关于日期
模拟日历
#include <iostream>
#include <cstring>
using namespace std;
int ans;
int d[2][13] ={ {0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31} //闰年
};
//判断闰年
bool is_run(int y)
{
if((y%100!=0 && y%4==0) || y%400==0) return true;
else return false;
}
int main()
{
//初始状态
int y = 2000, m = 1, day = 1;
int t = 6; //t表示周几
while(1)
{
if(t==1 || day==1) ans += 2;
else ans ++;
// printf("Y=%d,M=%d,D=%d,t=%d,ans=%d\n",y,m,day,t,ans);
//出口
if(y==2020 && m==10 && day==1)
{
cout << ans << endl;
break;
}
//天数加一
day ++;
int flag = 0;
if(is_run(y)) flag = 1;
// cout << flag << endl;
// break;
//进位
if(day >= d[flag][m]+1)
{
day = 1; //天数重置为1
m += 1; //月份加一
if(m >= 13)
{
m = 1; //月份重置为1
y += 1;
}
}
t = (t + 1) % 7; //星期几
}
return 0;
}
判断闰年
如果年份能被4整除但不能被100整除,那么这一年就是闰年。例如,2004年是闰年,而1900年不是闰年。
对于整百年份,只有那些能被400整除的年份才是闰年。例如,2000年是闰年,而1900年不是。
此外,还可以通过查看2月份的天数来判断。在闰年中,2月份有29天。
//判断闰年
bool is_run(int y)
{
if((y%100!=0 && y%4==0) || y%400==0) return true;
else return false;
}
判断日期合法性
//判断日期合法性
//前提是以数字形式枚举日期
bool is_date(int x)
{
int month = x/100%100;
int day = x%100;
if(month>=1 && month<=12)
{
if(day>=1 && day<=days[month])
return true;
else return false;
}
else return false;
}
/*
题目数据:
5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5
8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6
8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1
0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
答案:235
*/
//正难则反,直接在数组中找满足条件的子序列比较麻烦,还有判重的问题。
//不妨换个思路,枚举2023年每个日期,看能否在100个数中找到对应数字。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 110;
int a[N];
int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int ans;
//判断日期合法性
bool is_date(int x)
{
int month = x/100%100;
int day = x%100;
if(month>=1 && month<=12)
{
if(day>=1 && day<=days[month])
return true;
else return false;
}
else return false;
}
int main()
{
for(int i=0;i<100;i++)
cin >> a[i];
//i后四位即月份 日期
for(int i=20230101;i<=20231231;i++)
{
if(is_date(i)==1)
{
string s = to_string(i);
int k=0;
for(int j=0;j<100;j++)
{
//注意a[j]是int型,s[k]是char型
if(a[j] == s[k]-'0') k++;
}
if(k==8) ans ++;
}
}
cout << ans << endl;
return 0;
}
无穷大设定
INF = 0x3f3f3f3f; //正无穷
memset初始化函数
const int INF = 0x3f3f3f3f, N = 510;
int f[N][N];
//memset函数用法
//第一个参数:要初始化的数组f
//第二个参数:要初始化的值-INF (-INF为负无穷)
//第三个参数:数组的字节,用sizeof计算f数组的字节
memset(f, -INF, sizeof f);
向上向下取整
向下取整
-
整数除法运算符 / 代表向下取整, 常用于计算当中(适用于正数,对于负数计算来说,只是在正数的结果上加了个负号)
例如:
5 / 2 = 2
,-5 / 2 = -2
-
C++
floor()
函数, floor(x)返回一个小于或等于x的最大整数例如:
floor(2.5) = 2
,floor(-2.5) = -3
-
直接舍去小数部分,赋值给整数变量(适用于正数)
例如:
int a = 2.5
,b = int(2.5)
, a, b数值都是2
向上取整
-
C++ ceil()函数, ceil(x)返回一个大于x的最小正数
例如:
ceil(2.5) = 3
,ceil(-2.5) = -2
-
公式
x = (a-1) / b + 1
, 变形一下得x = (a + b - 1) / b
-
直接舍去小数部分,赋值给整数变量(适用于负数)
例如:
int a = -2.5
,b = int(-2.5)
, a, b数值都是-2
四舍五入
round()函数 用于四舍五入
确定整数的上下界
- 2023 C.冶炼金属
- 下取整符号**“⌊ ⌋”**
算法基础
前缀和
类似数列求前n项和。
有一组数:a1,a2,a3,…,an
前缀和 Si = a1 + a2 + … + ai
- 注意:下标要从1开始,因为 S0 = 0
子矩阵的和
//acwing
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int a[N][N];//存入矩阵数据
int s[N][N];//初始化前缀和
int n,m,q;
int main()
{
scanf("%d%d%d",&n,&m,&q);
//存数据
//注意:i,j从1开始,因为有减0操作
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
//初始化前缀和
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
while(q--)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
//求子矩阵的和
int sum = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1];
printf("%d\n",sum);
}
return 0;
}
快速幂
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; //数论的题一般都要开long long,不然会爆int
//求 a^k % p
int qmi(int a,int k,int p)
{
int res = 1;
while(k) //对k进行二进制化,从低位到高位
{
//如果k的二进制表示的最低位(最右边的位)为1,则乘上当前的a
if(k&1) res = (ll)res*a%p;
//k的二进制表示 右移一位
k >>= 1;
//更新a
a = (ll)a*a%p; //取模后的结果
// printf("a = %d, k = %d\n",a,k);
}
return res;
}
int main()
{
int n;
scanf("%d", &n);
while(n--)
{
int a,k,p;
scanf("%d%d%d", &a,&k,&p);
printf("%d\n", qmi(a,k,p));
}
return 0;
}
高精度除法
- 高精度数字用字符串来存储
- vector是动态数组,可以对其元素进行频繁操作
- vector元素操作(插入、删除),主要是对其最后一个元素,所以代码中有很多逆序操作
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
// A / b, r是余数, C是商
vector<int> div(vector<int> &A, int b, int &r) //A 和 r 传的是引用
{
vector<int> C;
r = 0;
for(int i=A.size()-1; i>=0; i--)
{
//下面三行代码是核心
r = r*10 + A[i]; //等式右边的r对应的是i-1,左边的r对应的是i
C.push_back(r / b); // C存每一位的商
r %= b; // 对应第i位的余数
}
//上面的for循环存储的C商数是正序,为了去除前导0操作,逆序一下
reverse(C.begin(), C.end());
while(C.size()>1 && C.back()==0)
C.pop_back();
return C;
}
int main()
{
string a; // 高精度数字用字符串存储
int b; //低精度用int
cin >> a >> b;
vector<int> A;
//将高精度数字逆序存入向量A
for(int i=a.size()-1; i>=0; i--)
A.push_back(a[i] - '0'); //注意减0操作,a[i]是char型,减0后变成int型
int r; //余数
auto C = div(A, b, r);
//输出商数
for(int i=C.size()-1; i>=0; i--)
printf("%d", C[i]);
puts(""); //换行
//输出余数
cout << r << endl;
return 0;
}
图论
树与图的存储
/*
ACwing 846.树的重心
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
*/
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = N*2;
//h[i] 存头指针,i为值
//ne[i] 存next指针,i为指针
//e[i] 存下标为i的值
//idx 是下标,即指针
int h[N],ne[M],e[M],idx;
//头插法:在头节点后a面插入一个节点b ( a-->b )
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int main()
{
int n;
cin >> n;
//初始化头节点指针为-1,即指向空节点
memset(h, -1, sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b;
cin >> a >> b;
add(a,b); //有向图
// add(a,b), add(b,a); //无向图
}
//遍历头节点是2的所有相邻节点
for(int i=h[2]; i!=-1; i=ne[i])
{
cout << e[i] << ' ';
}
return 0;
}
树与图的深搜与宽搜(含重载知识点)
/*
输入:
8 9
1 2
1 3
1 4
2 5
2 6
3 7
4 7
4 8
7 8
输出:
1 2 5 6 3 7 8 4
1 2 3 4 5 6 7 8
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e6 + 10;
int h[N],ne[N],e[N],idx;
bool st[N];
int path[N]; //记录路径写法
int k = 1, k1 = 0;
//定义结构体 存储每条边的起点a,终点b
struct edge{
int a,b;
}edges[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
//重载排列顺序,按照a升序,b降序排列,若a相同,b也降序
bool cmp(edge e1, edge e2)
{
if(e1.a == e2.a) return e1.b > e2.b;
return e1.a < e2.a;
}
//深搜
//u:节点u
void dfs(int u)
{
cout << u << ' ';
st[u] = 1; //节点u已经遍历过,标记一下
//以节点u为头节点,遍历u的邻接点
for(int i=h[u]; i!=-1; i=ne[i])
{
//j是值(节点编号),为u的邻接点
int j = e[i];
{
//如果节点没有被遍历到
if(!st[j])
{
st[j] = 1; //遍历一下,标记一下
dfs(j); //继续以j号节点为头节点开始深搜
}
}
}
}
//宽搜
void bfs()
{
queue<int> q;
st[1] = true;
path[0] = 1;
q.push(1);
while(q.size())
{
int t = q.front(); q.pop();
cout << t << ' '; //边搜边输出写法
for(int i=h[t]; i!=-1; i=ne[i])
{
int j = e[i];
if(!st[j])
{
st[j] = true;
path[k++] = j;
q.push(j);
}
}
}
}
int main()
{
int n,m;
cin >> n >> m;
memset(h, -1, sizeof h);
for(int i=0;i<m;i++)
{
int a,b;
cin >> a >> b;
edges[i] = {a,b}; //存边的起点a 终点b
}
//注意要加上cmp
sort(edges, edges+m, cmp);
//存图
for(int i=0;i<m;i++)
{
add(edges[i].a,edges[i].b);
}
dfs(1);
// for(int i=0;i<k1;i++)
// cout << path[i] << ' ';
puts(""); //换行
//重置一下st状态数组
memset(st, false, sizeof st);
bfs();
// for(int i=0;i<k;i++)
// cout << path[i] << ' ';
return 0;
}
spfa求最短路
st[i]数组用于表示节点i是否在队列里
st[i] = true
表示 i号点在队列里st[i] = false
表示i号点不在队列里
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int h[N],e[N],w[N],ne[N],idx;
//st[i]数组用于表示节点i是否在队列里
bool st[N]; // st[i] = true 表示 i号点在队列里,st[i] = false 表示i号点不在队列里
int dist[N]; //dist[i]存的是i号点到1号点的距离
int n,m;
void add(int a,int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void spfa()
{
//初始化dist,刚开始所有点到1号点的距离都为无穷大
memset(dist, 0x3f, sizeof dist);
//特例,1号点到自身的距离为0
dist[1] = 0;
queue<int> q;
q.push(1);
st[1] = true;
while(q.size())
{
int t = q.front(); q.pop();
st[t] = false; //t号点被删除,不在队列里,st[t] 置为false
for(int i=h[t]; i!=-1; i=ne[i])
{
int j = e[i];
if(dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if(!st[j])
{
q.push(j);
st[j] = true; // j号点入队列,在队列里,st[j] 置为true;
}
}
}
}
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
for(int i=0;i<m;i++)
{
int x,y,z;
cin >> x >> y >> z;
add(x,y,z);
}
spfa();
if(dist[n] == 0x3f3f3f3f) puts("impossible");
else cout << dist[n] << endl;
return 0;
}
秦九韶算法
出自2022年蓝桥杯c++b组E题X进制减法
重载 判断浮点数相等
//斜率、截距确定唯一一条直线
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 2e6;
int n;
//重载小于号
struct Line{
double k,b; //k斜率 b截距
/*
bool operator< (const Line& t) const
{
if(k != t.k) return k > t.k;
return b > t.b;
}
*/
}l[N];
//另一种重载方式
bool cmp(Line l1, Line l2)
{
if(l1.k == l2.k) return l1.b > l2.b;
return l1.k > l2.k;
}
int main()
{
//枚举两个点
for(int x1=0;x1<20;x1++)
for(int y1=0;y1<21;y1++)
for(int x2=0;x2<20;x2++)
for(int y2=0;y2<21;y2++)
//斜率存在
if(x1 != x2)
{
double k = (double)(y2-y1) / (double)(x2-x1);
double b = y1 - k*x1;
l[n++] = {k,b};
}
//注意要加上参数 cmp
sort(l,l+n, cmp);
int res = 1;
//下标从1开始,因为有i-1操作
for(int i=1;i<n;i++)
{
//fabs浮点数绝对值函数 需要导入cmath库,include <cmath>
//判断浮点数相等:fabs(l[i].k-l[i-1].k) < 1e-8 用小于号
//判断浮点数不相等
if(fabs(l[i].k-l[i-1].k)>1e-8 || fabs(l[i].b-l[i-1].b)>1e-8)
res ++ ;
}
//20是斜率不存在的情况,别忘记加
cout << res + 20 << endl;
return 0;
}
c/c++知识点
常用数学函数
- 绝对值函数
fabs()
abs()
函数
#include<cmath>
float x = -2.2342;
// fabs()和abs()效果相同,但这两个函数的返回值只能保留六位有效数字,数字长度超过六位会四舍五入
cout << fabs(x) << endl;
cout << abs(x) << endl;
>>>>2.2342
2.2342
-
数学函数
函数 函数原型 功能 指数函数 exp(x) double exp(double x) 计算e^x的值,返回计算结果 对数函数 log(x) double log(double x) 计算lnx的值,返回计算结果 log10(x) 计算以10(可以是任意正常数)为底,x为指数的对数,返回计算结果。注意:x>0 幂函数 pow(x,y) double pow(double x,double y) 返回以x为底的y次幂,及x^y。注意:该函数要求参数x,y和函数的返回值都是double类型,否则有可能出现数值溢出问题。 开根号 sqrt(x) double sqrt(double x) 计算√x的值,返回计算结果。注意:x>=0 正弦函数 sin(x) double sin(double x) 返回sinx的值。注意:x单位为弧度 余弦函数 cos(x) double cos(double x) 返回cosx的值。注意:x单位为弧度 正切函数 tan(x) double tan(double x) 返回tanx的值。注意:x单位为弧度
数据类型
数据类型 | 占用空间 | 取值范围 | |
---|---|---|---|
short | 短整型 | 2字节 | (-2^15 ~ 2^15-1) |
int | 整型 | 4字节 | (-2^31 ~ 2^31-1) 约=2e9 |
long | 长整型 | Windows为4字节;Linux为4字节(32位)或8字节(64位) | (-2^31~ 2^31-1) |
long long | 长长整型 | 8字节 | (-2^63 ~ 2^63-1) 约=9e18 |
float | 单精度浮点型 | 4字节 | 6~7位有效数字 |
double | 双精度浮点型 | 8字节 | 15~16位有效数字 |
long doube | 高双精度浮点型 | 8字节 | 16位有效数字 |
char | 字符型 | 1字节 | ASCII码范围(0~127) |
bool | 布尔类型 | 1字节 | 0或1 (true or false) |
string | 字符串型 |
注:C++的bool类型中,
true
或任意非0值
均代表“真”;false
或0值
代表“假”。
sizeof关键字
作用:可统计数据类型所占用的内存大小,返回值是数据类型占用的字节个数
语法:
sizeof(数据类型)
或sizeof(变量名)
b,B,KB,MB,GB,TB转换
基本概念
- bit(位,又名“比特”):bit的缩写是b,是计算机中的最小数据单位(属于二进制的范畴,其实就是0或者1)
- Byte(字节):Byte的缩写是B,是计算机文件大小的基本计算单位。比如一个字符就是1Byte,如果是汉字,则是2Byte。
另外,还使用千字节(KB)、兆字节(MB)、吉字节(GB)甚至太字节(TB)。
换算
容量中 b、B、KB、MB、GB 、TB之间的换算关系对照
1B(字节)= 8b(位)
1 KB = 1024 B
1 MB = 1024 KB
1 GB = 1024 MB
1TB = 1024GB
1B = 1个英文字母或1个数字或一个字符
2B = 1个中文汉字
它们之间的换算关系都是1024倍
原文链接:https://blog.csdn.net/joshua317/article/details/120186858
取模运算公式(%)
- 加法分配律
(a + b) % p = (a % p + b % p) % p
- 减法分配律
(a - b) % p = (a % p - b % p) % p
- 乘法分配律
(a * b) % p = (a % p * b % p) % p
- 指数
a ^ b % p = ((a % p)^b) % p
运算符
按位与(&)
c++中k&1是什么意思
在C++中,表达式
k & 1
表示的是对整数k
进行按位与 (&
) 运算,其中1
是二进制的0000000000000001
(具体长度取决于k
的类型)。按位与运算是对两个操作数的每一位执行逻辑与操作:
- 如果两个相应的二进制位都是1,则结果位为1;
- 否则,结果位为0。
在二进制表示下,数字1的最后一位是1,其余所有位都是0。因此,对任何整数
k
进行k & 1
的运算实质上是在检测k
的二进制表示的最低位(最右边的位)是否为1。如果
k
是奇数,则其二进制表示的最低位一定是1,所以k & 1
的结果将是1。
如果k
是偶数,则其二进制表示的最低位一定是0,所以k & 1
的结果将是0。因此,
k & 1
常常被用来判断一个整数k
是否为奇数,如果结果为1则说明k
是奇数,结果为0则说明k
是偶数。
二进制右移运算符(>>)
在C++中k>>=1是什么意思
在C++中,表达式
k >>= 1;
是一个复合赋值运算符,它表示将整数变量k
右移一位,然后将结果存回到k
自身。这里的
>>
是二进制右移运算符,它将k
的二进制表示向右移动指定的位数,在这里移动一位。在右移的过程中,最高位(最左边的位)通常会被丢弃,而最低位(最右边的位)要么填充0(对于无符号整数),要么根据符号位扩展(对于有符号整数,即保留原符号位不变)。所以,当你执行
k >>= 1;
时,实际上你是在完成以下两个步骤:
k = k >> 1;
—— 把k
的值右移一位。- 结果自动赋值回
k
。这个操作常常用于快速实现整数除以2的操作(向下取整),因为在二进制中,每右移一位相当于除以2。例如,如果
k
的值是十进制的8(二进制为1000
),那么k >>= 1;
执行后,k
的值将会变成4(二进制为0100
)。
异或运算符(^)
异或运算符(XOR Operator)是一种二进制位运算符,通常用于比较两个二进制数的对应位。异或运算的规则是:当两个相应的二进制位相同时,该位的结果为0;当两个相应的二进制位不同时,该位的结果为1。
在大多数编程语言中,异或运算符用符号
^
表示。例如,在C++、Java、Python等语言中,都可以使用^
来执行异或运算。异或运算具有一些重要的性质,包括:
- 交换律:
A ^ B
等于B ^ A
。- 结合律:
(A ^ B) ^ C
等于A ^ (B ^ C)
。- 任何数和0做异或运算,结果仍然是原来的数:
A ^ 0
等于A
。- 任何数和其自身做异或运算,结果是0:
A ^ A
等于0
。- 异或运算可以用来交换两个变量的值,而不需要使用临时变量:
A = A ^ B; B = A ^ B; A = A ^ B;
执行后,A 和 B 的值会交换。
#include <iostream>
using namespace std;
int main() {
int a = 5; // 二进制表示为 0101
int b = 3; // 二进制表示为 0011
int result = a ^ b; // 异或运算
cout << "异或结果为: " << result << endl; // 输出应为 0110,即十进制的6
return 0;
}
数据结构
队列queue
//头文件
#include<queue>
typedef pair<int,int> PII;
queue<PII> q; //建立一个队列q,其内部元素类型是pair;
//方法带括号 eg: q.pop()
//属性不带括号 eg: t.first t.second
q.push({1,2}); //将元素{1,2}插入队尾,不是单一元素用花括号{};
q.pop(); //弹出队首元素(也就是删除队首元素)
PII t = q.front(); //查询队首元素,t是pair类型
t.first; //查询t的第一个int值
t.second; //查询t的第二个int值
q.back(); //查询队尾元素
q.size(); //查询q的元素个数
q.empty(); //查询q是否为空,若为空则返回1 表示队列是空的,若不为空则返回0
队列的定义
- 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,即遵循“先进先出/FIFO”的数据结构。
- 注意:只有队头和队尾能被外界访问,因此不允许有遍历行为。
- 队头(front):允许删除的一端,又称队首
- 队尾(rear):允许插入的一端
- 空队列:不包含任何元素的空表
vector
#include<vector>
vector<int> a,b;
//返回a的最后一个元素
a.back();
//返回a的第一个元素
a.front();
//删除a向量的最后一个元素
a.pop_back();
//在a的最后一个向量后插入一个元素,其值为5
a.push_back(5);
//删除a中第一个(从第0个算起)到第二个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)结束
a.erase(a.begin()+1,a.begin()+3);
//返回a中元素的个数
a.size();
//b为向量,将a中的元素和b中的元素整体交换
a.swap(b);
//清空a中的元素
a.clear();
//判断a是否为空,空则返回true,非空则返回false
a.empty();
pair
⭐字符串操作
string s="abcd";
//求字符串长度n,s.length() 与s.size()效果相同
n = s.size();
to_string函数
-
将数字常量转换为字符串,返回值为转换完毕的字符串
-
字符串支持下标索引操作,类似python中的列表
-
c++中字符与字符串敏感:
-
字符:char 单引号
-
字符串:string 双引号
-
string str = "abc"; // 双引号是字符串
// char = 'a'; // 单引号是字符
int num = 20230101;
cout << str[0] << endl;
cout << str + to_string(num) << endl;
>>>> 'a'
>>>> 'abc20230101'
string相关函数
sort
unique
erase
#include <iostream>
#include <cstring>
#include <algorithm>
#include <typeinfo>
using namespace std;
int main()
{
string s;
cin >> s;
//字符串排序
sort(s.begin(),s.end());
cout << s << endl;
//unique函数返回的是迭代器 (可以将迭代器理解为地址,下标)
//unique函数实质上是“伪去重”函数。
//它只是把重复的元素添加到容器末尾,而返回值是去重之后的尾地址(是地址!!)
auto it = unique(s.begin(),s.end());
cout << typeid(it).name() << endl; //输出unique返回值类型
int t = it - s.begin(); //s中不重复的字符个数
cout << t << endl;
s.erase(it,s.end()); //删除重复的字符
cout << s << endl;
return 0;
}
判断变量数据类型
运用函数
#include<typeinfo>
typeid(a).name() // a为变量名
代码实测
#include <iostream>
#include <string>
#include <typeinfo> //必须加上的头文件
using namespace std;
int main(){
int num = 0;
char cha = 'a';
float flo = 1.0;
double dbe = 2.3;
bool boo = false;
string str = "haihong";
cout<< "num的类型是 " << typeid(num).name() <<endl;
cout<< "cha的类型是 " << typeid(cha).name() <<endl;
cout<< "flo的类型是 " << typeid(flo).name() <<endl;
cout<< "dbe的类型是 " << typeid(dbe).name() <<endl;
cout<< "boo的类型是 " << typeid(boo).name() <<endl;
cout<< "str的类型是 " << typeid(str).name() <<endl;
}
减字符‘0’以及单个字符相减解释
c++中单个字符相减,减的是对应的ASCII码
- char类型的数字减char类型’0’得到的是int型的该数字
- eg: ‘9’ - ‘0’ = 9
减去字符0,也就是减去0的ASCII码值48,数字字符减去‘0’就得到了该数字。
把字符串中字母,小写变大写,也是用到字母的ASCII码值
运用函数
#include<typeinfo>
typeid(a).name() // a为变量名
代码实测
#include <iostream>
#include <string>
#include <typeinfo> //必须加上的头文件
using namespace std;
int main(){
int num = 0;
char cha = 'a';
float flo = 1.0;
double dbe = 2.3;
bool boo = false;
string str = "haihong";
cout<< "num的类型是 " << typeid(num).name() <<endl;
cout<< "cha的类型是 " << typeid(cha).name() <<endl;
cout<< "flo的类型是 " << typeid(flo).name() <<endl;
cout<< "dbe的类型是 " << typeid(dbe).name() <<endl;
cout<< "boo的类型是 " << typeid(boo).name() <<endl;
cout<< "str的类型是 " << typeid(str).name() <<endl;
}