ASCII码值、字母大小写转换、'0'~'9'
cpp
//数字转字符:'A'(65)'a'(97)'0'(48)
char A=char(65);
char a=char(97);
char c='a'+2;//'c'='a'+2
char seven='0'+7;//'7'='0'+7;
//字符转数字
int a='a';//a:97
int A='A';//A:65
int t='t'-'a';//可以计算字母间的差值
int seven='7'-'0';
子典序
字典序就是以ASCII码排序。
比如两个字符串 abcd 和 abdd 比较大小。 从第一个字符开始逐位比较,第一个字符不相等,谁的ASCII码值小谁的字典序就小。若第一个相等,继续逐位比较后续字符。比较到字母c < 字母d,所以第一个字符串abcd 字典序较小。
再比如 abcd 和 abcdefg 比较大小。若逐位比较都相等,但其中一个没有后续的字符了,则较短的串 abcd 字典序较小。
使用 sort() 可以对字符串进行字典序排序,字符按ASCII码值由小到大排列。
题目描述
有N个长为工的字符串、S1,S2,...拓拓将以某种顺序连接所有字符串,拼接成一个长字符串。在拼接出的所有长字符串中,找到字典序最小的一个。
输入格式
第一行两个正整数 N 和工.
接下来 N 行每行一个字符串 S1,S2,.SN
输出格式
输出一行,输出拼接出的字典序最小的字符串
样例
输入数据
3 3
dxx
axx
cxx
输出数据
axxcxxdxx
数据范围
1<=N,L<=100
对于每个i(1≤i≤N),Si的长度等于L。
对于每个i(1≤i≤N),Si全部由小写字母组成。
code:
cpp
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
int n,l;
cin>>n>>l;
string s[100];
for(int i=0;i<n;i++) cin>>s[i];
sort(s,s+n);
for(int i=0;i<n;i++) cout<<s[i];
cout<<endl;
return 0;
}
排列字母
小蓝要把一个字符串中的字母按其在字母表中的顺序排列。 例如,LANQIAO 排列后为 AAILNOQ。又如,GOODGOODSTUDYDAYDAYUP 排列后为AADDDDDGGOOOOPSTUUYYY 请问对于以下字符串,排列之后字符串是什么?WHERETHEREISAWILLTHEREISAWAY
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内容将无法得分。
code:
cpp
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string s;
cin>>s;
sort(s.begin(),s.end());
cout<<s<<endl;
return 0;
}
字符串常用函数和reverse
cpp
#include<iostream>
#include<string>
using namespace std;
string s;
int main(){
s.size();//返回字符串的长度
s.length();//返回字符串的长度
s.empty();//判断队列是否为空,为空返回1,否则返回0
s[n];//取s中第n+1个字符
reverse(s.begin(),s.end());//翻转字符串
//查找
s.find("ab");//返回字符串ab在s的位置
s.find("ab",2);//在s[2]~s[n-1]的范围内查找并返回字符串ab在s的位置
s.rfind("ab",2);//在s[0]~s[2]的范围内查找并返回字符串ab在s的位置
//子串
s.substr(3);//返回s[3]及其以后的子串
s.substr(2,4);//返回s[2]~s[2+(4-1)]的子串,即从s[2]开始往后4个字符组成的字符串
s.substring(5,10);//返回s[5]~s[9]的子串(不包含结尾)
//插入
s.insert(2,"ab");//从s[2]位置开始添加字符串"ab",并返回形成的新字符串
s.insert(2,"abcd",3);//从s[2]位置开始添加字符串"abcd"的前3个字符,并返回形成的新字符串
s.insert(2,"abcd",1,3);//从s[2]位置开始添加字符串"abcd"的前s[2]~s[2+(3-1)]个字符,并返回新形成的字符串
//删除
s.erase(3);//删除s[3]以及以后的字符,并返回新形成的字符串
s.erase(3,5);//删除s[3]开始的5个字符,并返回新字符串
//替换
s.replace(2,4,"ab");//返回把s[2]~s[2+(4-1)]的内容替换为"ab"后的新字符串
s.replace(2,4,"abcd",3);//返回把s[2]~s[2+(4-1)]的内容替换为"abcd"的前3个字符后的新字符串
//加串
s=s+"abc";
s.push_back('a');//在s的尾部添加字符'a'
s.append("abc");//在s的尾部添加字符串"abc"
//大小写转换
//法一:
tolower(s[i]);//转换为小写
toupper(s[i]);//转换为大写
//法二:
//通过stl的 transform 算法配合 tolower 和 toupper 实现。
//有4个参数,前2个指定要转换的容器的起止范围,第3个参数是结果存放容器的起始位置,第4个参数是一元运算。
string s;
transform(s.begin(),s.end(),s.begin(), : tolower); //转换小写
transform(s.begin(),s.end(),s.begin(), : toupper); //转换大写
}
string与C语言字符串(C-string)的区别
string是C++的一个类,专门实现字符串的相关操作。具有丰富的操作方法,数据类型为 string ,字符串结尾没有 \0 字符
C-string是C语言中的字符串,用char数组实现,类型为 const char * ,字符串结尾以 \0 结尾
一般来说string向char数组转换会出现一些问题,所以为了能够实现转换,string有一个方法 c_str() 实现string向char数组的转换。
cpp
string s = "xing ma qi";
char s2[] = s.c_str();
字符串编号
题目描述:
小明发明了一种给由全大写字母组成的字符串编码的方法。对于每一个大写字母,小明将它转换成它在 26 个英文字母中序号,即 A→1,B→2,...Z→26。这样一个字符串就能被转成一个数字序列:比如 ABCXYZ→123242526。现在给定一个转换后的数字序列,小明想还原出原本的字符串。当然这样的还原有可能存在多个符合条件的字符串。小明希望找出其中字典序最大的字符串。
输入格式
输入一行一个数字序列。
输出格式
输出一行一个只包含大写字母的字符串,代表答案。
样例
输入数据
123242526
输出数据
LCXYZ
数据范围
对于 20% 的评测用例,输入的长度不超过20。对于所有评测用例,输入的长度不超过200000。
code:
cpp
#include<iostream>
#include<string>
using namespace std;
int main(){
string s;
cin>>s;
int len=s.size();
for(int i=0;i<len;i++){
int a=s[i]-'0',c=stoi(s.substr(i,2));
if(c>26){
cout<<(char)(a+'A'-1);
}
else{
i++;
cout<<(char)(c+'A'-1);
}
}
return 0;
}
子串
题目描述
这是一道模板题。 给定一个字符串 A 和一个字符串 B,求 B 在 A 中的出现次数。A 和 B 中的字符均为英语大写字母或小写字母。 A 中不同位置出现的 B 可重叠。
输入格式
输入共两行,分别是字符串 A 和字符串 B。
输出格式
输出一个整数,表示 B 在 A 中的出现次数。
样例
输入数据
zyzyzyz
zyz
输出数据
3
数据范围
对于 100% 的测试数据满足: A,B 的长度 <=10^6 , A,B 仅包含大小写字母。
code:
cpp
#include<iostream>
#include<string>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
string a,b;
cin>>a>>b;
int s=0;
int t=a.find(b);
while(t!=string::npos){
s++;
t=a.find(b,t+1);
}
cout<<s<<endl;
return 0;
}
删除字符
题目描述
编写一个程序,先输入一个字符串 str(长度不超过20),再输入单独的一个字符 ch,然后程序会把字符串 str 当中出现的所有的 ch 字符都删掉,从而得到一个新的字符串 str2,然后把这个字符串打印出来。
输入格式
输入有两行,第一行是一个字符串(内部可能含空格),第二行是一个字符。
输出格式
经过处理以后的字符串。
样例
输入数据
123-45-678
-
输出数据
12345678
code:
cpp
#include<iostream>
#include<string>
using namespace std;
int main(){
string str;
char ch;
getline(cin,str);
cin>>ch;//ch为字符不可以用getline来读入,getline与cin混用错误原因是cin 会剩一个换行符, getline 会把这个换行符读进来导致直接结束字符串读入。因此可以先使用getline来读入后用cin来读入
int p=str.find(ch);
while(p!=string::npos){
str.erase(p,1);
p=str.find(ch);
}
cout<<str<<endl;
return 0;
}
替换单词
题目背景
最近,谷歌公司做出了一项决定,由于black list(黑名单)这个词语不好听,所以需要将它们修改成block list(屏蔽名单)。
题目描述
给定一个仅仅由小写字母组成的字符串s,请将其中所有的black全部替换成block。
输入格式
单个字符串:表示需要替换的字符串s。
输出格式
单个字符串:表示将black替换成block后的字符串。
样例
输入数据
ablacklistblackmatter
输出数据
ablocklistblockmatter
数据范围
设字符串的长度为|s|,则
对于50%的数据,1<|s|<200;
对于100%的数据,1<|s|<200000.
code:
cpp
#include<iostream>
#include<string>
using namespace std;
int main(){
string s,w,t;
cin>>s;
w="black";
t="block";
int p=s.find(w);
while(p!=string::npos){
s.replace(p,5,t);
p=s.find(w);
}
cout<<s<<endl;
return 0;
}
stringstream
头文件:sstream
stringstream主要是用在字符串分割,可以先用clear()以及str()将字符串读入并进行分割,再用>>把内容输出。
cpp
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main(){
string s;
stringstream ss;
int a,b,c;
getline(cin,s);
ss.clear();
ss.str(s);
ss>>a>>b>>c;
return 0;
}
stringstream详解:
stringstream是C++ 提供的专门用于处理字符串的输入输出流类。
stringstream的用法:
1、构造函数:
stringstream 的构造函数有很多,这里列举最为常用的两个构造函数:
<1>、创建一个对象,向对象输入字符串:
cpp
// 创建一个 string类 对象 s
string s("hello stringstream");
// 创建一个 stringstraeam类 对象 ss
stringstream ss;
// 向对象输入字符串 : "<<" 表示向一个对象中输入
ss << s;
cout << ss.str() << endl;
<2>、在创建对象的时候使用字符串初始化:
cpp
// 创建一个 stringstraeam类 对象 ss
stringstream ss("hello stringstream");
cout << ss.str() << endl;
两种方式都可以创建对象,但创建后的对象用法不一样,详见后面的示例。
2、输出字符串
stringstream 可以将存储于内部的字符串输出,需要调用 str() 函数,不可直接输出:
cpp
std::cout << ss.str() << std::endl;
// std::cout << ss << std::endl; // 错误不可直接输出
注意:cout << ss << endl; 是错误的,不可以直接输出
3、两种构造函数带来的不同
上面阐述了两种构造函数,利用不同的构造函数创建对象,对象具体的操作也不同:
<1>、 第一种构造方式
cpp
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
stringstream ss1;
ss1 << "fre";
ss1 << "gre";
cout << ss1.str() << endl;
return 0;
}
/*
输出:
fregre
*/
可以发现,两个字符串直接拼接在了一起
<2>、第二种构造方式
cpp
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string str("asd");
// 第二种构造
stringstream ss2(str);
cout << ss2.str() << endl;
// 第一种构造
ss2 << "r";
cout << ss2.str() << endl;
ss2 << "13";
cout << ss2.str() << endl;
ss2 << "hy";
cout << ss2.str() << endl;
return 0;
}
/*
输出:
asd
rsd
r13
r13hy
*/
可以发现,利用第一种构造函数创建对象时,输入字符串后直接进行字符串拼接,而第二种构造方式,在进行字符串拼接时,首先把原本的字符串覆盖掉,之后再进行拼接。
<3>、 如果不想原来的字符串被覆盖,则需要换一种构造方式,如下:
cpp
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
ostringstream ss("1 2 3 4 ", std::ios_base::ate); // append 方式追加
cout << ss.str() << endl;
ss << "5 3 4";
cout << ss.str() << endl;
return 0;
}
/*
输出:
1 2 3 4
1 2 3 4 5 3 4
*/
4、修改、清空 stringstream 内容
stringstream 的内容可以通过 str() 函数进行修改、清空:
cpp
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
stringstream ss("hello string");
cout << ss.str() << endl;
// 修改内容
ss.str("hello stringstream");
cout << ss.str() << endl;
// 清空内容
ss.str("");
cout << ss.str() << endl;
return 0;
}
/*
输出:
fghewoo
123456
*/
srtingstream练习
题目描述
输入的第一行有一个数字 N 代表接下來有 N 行数字,每一行有若干个的整数(最多 20 个,每行最多 200个字符),请你输出每一行数字的和。
输入格式
第一行一个整数 N。
接下来输入 N 行,每行若干个整数。
输出格式
输出N行,每行一个整数表示。
样例
输入数据
3
1 2 3
20 17 23 54 77 60
111 222 333 444 555 666 777 888 999
输出数据
6
251
4995
code:
cpp
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main(){
string s;
stringstream ss;
int n,sum,i,a;
cin>>n;
getline(cin,s);
for(int i=1;i<=n;i++){
getline(cin,s);
ss.clear();
ss.str(s);
sum=0;
while(1){
ss>>a;
if(ss.fail()) break;
sum+=a;
}
cout<<sum<<endl;
}
return 0;
}
sprintf
sprintf是一个比较冷门的函数,可以直接把相应的整数拼接组合成我们规定的格式。
sprintf详解
cpp
char str[80];
sprintf(str, "%c", 'A'); // 输出字符 A
sprintf(str, "%d", 123); // 输出十进制整数 123
sprintf(str, "%x", 255); // 输出十六进制整数 ff
sprintf(str, "%f", 3.14); // 输出浮点数 3.140000
sprintf(str, "%s", "Hello"); // 输出字符串 Hello
sprintf(str, "%10d", 123); // 输出宽度为 10 的十进制整数,右对齐,空位用空格填充: 123
sprintf(str, "%-10d", 123); // 输出宽度为 10 的十进制整数,左对齐,空位用空格填充:123
sprintf(str, "%010d", 123); // 输出宽度为 10 的十进制整数,右对齐,空位用 0 填充:0000000123
sprintf(str, "%+d", 123); // 输出带正负号的十进制整数:+123
sprintf(str, "%.3d", 123); // 输出至少 3 位的十进制整数,不足则用 0 填充:123
sprintf(str, "%.3d", 12); // 输出至少 3 位的十进制整数,不足则用 0 填充:012
sprintf(str, "%.3f", 3.14); // 输出保留 3 位小数的浮点数:3.140
sprintf(str, "%.3s", "Hello"); // 输出最多 3 个字符的字符串:Hel
sprintf(str, "%ld", 123456789L); // 输出长整型数:123456789
sprintf(str, "%lf", 3.1415926535897932384626433832795L); // 输出长双精度型数:3.141593
sprintf练习
顺子日期
小明特别喜欢顺子。顺子指的就是连续的三个数字:123、456 等。顺子日期指的就是在日期的 уyyymmdd 表示法中,存在任意连续的三位数是一个顺子的日期。例如 20220123 就是一个顺子日期,因为它出现了一个顺子:123; 而 20221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 2022 年份中,一共有多少个顺子日期。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
code:
cpp
#include<iostream>
char ch[15];
using namespace std;
int main(){
int cnt=0,flag=0,ans=0;
for(int year=2022;year<=2022;year++)
for(int month=1;month<=12;month++)
for(int day=1;day<=31;day++){
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12);
else if(month==2){
if(year%4==0&&year%100!=0||year%400==0){
if(day>29) break;
}
else{
if(day>28) break;
}
}
else{
if(day>30) break;
}
sprintf(ch+1,"%d%02d%02d",year,month,day);//转换格式
for(int k=4;k+2<=8;k++){//k+2<=8处理边界
if(ch[k+2]-ch[k+1]==1&&ch[k+1]-ch[k]==1){
puts(ch+1);
ans++;
break;
}
}
}
cout<<ans;
return 0;
}
回文日期
题目描述
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按"yyyymmdd" 的格式写成一个 8 位数是 20200202, 恰好是一个回文数。我们称这样的日期是回文日期。有人表示20200202是"千年一遇" 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202即 2021 年 12 月 2 日。也有人表示20200202并不仅仅是一个回文日期,还是一个ABABBABA型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个ABABBABA型的回文日期:21211212 即 2121 年 12 月 12 日。算不上"千年一遇",顶多算"千年两遇"。给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。
输入格式
输入包含一个八位整数 N,表示日期。
输出格式
输出两行,每行 1 个八位数。
第一行表示下一个回文日期,第二行表示下一个ABABBABA型的回文日期。
样例
输入数据
20200202
输出数据
20211202
21211212
数据范围
对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 8 位数表示。
code:
cpp
#include<iostream>
#include<string>
using namespace std;
int n;
char ch[15];
int flag=0,flag1=0;
bool check1(string s){
for(int i=0,j=7;i<j;i++,j--){
if(s[i]!=s[j]) return false;
}
return true;
}
bool check2(string s){
if(check1(s)){
if(s[0]!=s[2]||s[1]!=s[3]||s[0]==s[1]) return false;
return true;
}
return false;
}
int main(){
cin>>n;
int year1=n/10000;
int month1=n%10000/100;
int day1=n%100;
for(int year=1000;year<=100000;year++)//题目中给的只是n的范围,并不是最后答案的范围,所以year要开的足够大
for(int month=1;month<=12;month++)
for(int day=1;day<=31;day++){
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12);
else if(month==2){
if((year%4==0&&year%100!=0)||year%400==0){
if(day>29) break;
}
else{
if(day>28) break;
}
}
else{
if(day>30) break;
}
if(flag1==1){
sprintf(ch+1,"%04d%02d%02d",year,month,day);
string s;
for(int i=1;i<=8;i++){
s+=ch[i];
}
if(!flag){
if(check1(s)){
cout<<s<<endl;
flag=1;
}
}
if(check2(s)){
cout<<s<<endl;
return 0;
}
}
if(year==year1&&month==month1&&day==day1){
flag1=1;
}//标记在后面防止遍历到当前日期
}
return 0;
}
日期统计:
题目描述:
小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0 到 9 的范围之内。数组中的元素从左至右如下所示:
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
现在他想要从这个数组中寻找一些满足以下条件的子序列:
1、子序列的长度为 8;
2、这个子序列可以按照下标顺序组成一个 yyyymmdd 格式的日期,并且要求这个日期是 2023 年中的某一天的日期,例如 20230902,20231223。yyyy 表示年份,mm 表示月份,dd 表示天数,当月份或者天数的长度只有一位时需要一个前导零补充。
请你帮小蓝计算下按上述条件一共能找到多少个不同的 2023 年的日期。
对于相同的日期你只需要统计一次即可。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
code:
cpp
#include<iostream>
using namespace std;
int a[110];
int main(){
for(int i=1;i<=100;i++){
cin>>a[i];
}
char s[15];
int cnt=0,flag=0;
for(int year=2023;year<=2023;year++)
for(int month=1;month<=12;month++)
for(int day=1;day<=31;day++){
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12);
else if(month==2){
if(year%4==0&&year%100!=0||year%400==0){
if(day>29) break;
}
else{
if(day>28) break;
}
}
else{
if(day>30) break;
}
sprintf(s,"%04d%02d%02d",year,month,day);
int m=0;
for(int n=1;n<=100;n++){
if(a[n]==(s[m]-'0')){
m++;
if(m==8) break;
}
}
if(m==8) flag=1;
if(flag==1){
cnt++;
flag=0;
}
}
cout<<cnt<<endl;
return 0;
}