字符串进阶-字符串函数
字符串进阶-字符串函数应用
c++提供了大量的字符串函数,供我们在解题时使用。
一、常用函数介绍
1-长度 (有返回值)
a.size() 或 a.length()
2-查找(有返回值)
a.find("hello") //返回子串hello在a中第一次出现时开头字母h的下标
a.find('h') //返回字符h在a中第一次出现时的下标
a.find(b) //返回b在a中第一次出现时的相关下标信息(b可以是字符或字符串)
a.find('h',2)//表示从下标2开始查找字符h第一次出现的位置
关于find函数的返回值判定:
很明显a中存在待找字符(串)时,会返回相关下标值;
不存在的时候,会返回 string :: npos ;
if 条件表达式: a.find("hello") == string::npos 表示找不到
3-插入(无返回值)
a.insert(2,"hello"); //在a中下标2开始插入“Hello",使a的值变化
举例:string a="topscoding";
a.insert(2,"hello");
cout<<a;
运行结果:tohellopscoding
4-删除(无返回值)
a.erase(2,3); //在a中下标2开始,删除3个字符,使a的值变化
举例:string a="topscoding";
a.erase(2,3);
cout<<a;
运行结果:tooding
5-提取(有返回值)
a.substr(2,3);//提取a中下标2开始的3个字符(a本身值不变,这相当于是复制过程)
举例:string a="topscoding";
cout<<a.substr(2,3);
运行结果:psc
6-翻转(无返回值)
reverse(a.begin(),a.end());//将字符串a的内容完全倒置,使a的值变化。
举例:string a="topscoding";
reverse(a.begin(),a.end());
cout<<a;
运行结果:gnidocspot
7-替换(无返回值)
a.replace(2,3,"hello");//将字符串a中,从下标2开始连续删除3个字符,并用”hello"替换(替换内容与待替换内容长度可以不同)
举例:string a="topscoding";
a.replace(2,3,"hello");
cout<<a;
运行结果:tohellooding
replace函数使用过程中,代替换内容可以是字符,但 替换内容 必须是字符串。
8-判空(有返回值)
a.empty() //串空返回1(true),非空返回0(false)。
举例:string a="topscoding";
if(a.empty()==1) cout<<"haha";
else cout<<"wuwu";
运行结果:wuwu
9-清空(无返回值)
a.clear(); //将a的内容清空,变为空串
举例:string a="topscoding";
a.clear();
cout<<a.size();
运行结果:0
10-追加(无返回值)
a.append("hello"); //将a的内容增添一截
举例:string a="topscoding";
a.append("hello");
cout<<a;
运行结果:tposcodinghello
函数相关题目
1、回文密码(点击题目名可转到题目详情页)(reverse()函数应用)
分析:
(1)first of all,这道题一上来要先确定字符串A是否回文,reverse函数可以派上大用场。
(2)奇数位、偶数位的处理,直接控制下标即可。比如奇数位的下标起点就是0,每次下标变化+2即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a;
cin>>a;
string b = a; //b存储a的内容
reverse(b.begin(),b.end()); //b此时就是a翻转后的内容
if(b==a) //翻转前后值一样,那一定是回文串
{
for(int i=1;i<a.size();i+=2)//控制下标依次输出偶数位
{
cout<<a[i];
}
}
else
{
for(int i=0;i<a.size();i+=2)//控制下标依次输出奇数位
{
cout<<a[i];
}
}
return 0;
}
2、调皮的小数点(find()函数应用)
分析:
(1)这道题是典型的关于find函数的应用,整个字符串中只有一个小数点,只有找到小数点的位置,才能得到其后第n位的值。
(2)小数点后第n位可能并不存在,或者说此时的下标已经超出所输入字符串的下标范围,这种情况不能落下。
参考代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n;//t代表t组数据,n代表小数点后第n位
cin>>t;
for(int i=1;i<=t;i++)
{
string a;
cin>>a>>n;
int t=a.find('.');//记录小数点的下标
t=t+n;//记录小数点后第n位的下标
if(t<=a.size()-1) //下标在合法范围内
{
cout<<a[t]<<endl;
}
else
{
cout<<"Error"<<endl;
}
}
return 0;
}
3、字母概率(大小写函数应用)
分析:
(1)概率 = 该字符出现总次数 / 字符总个数 。值得注意的是,这道题里,字母的大小写形式都要纳入讨论。
这里要介绍两个新函数:
tolower() //把字母字符转换成小写,非字母字符不做处理
toupper()//把字母字符转换成大写,非字母字符不做处理
注意:上述两函数的返回值为整型(即返回ASCII码值)而非字符型。
应用这两个函数,可以轻松处理大小写讨论的问题。
(2)字符总个数》a.size()函数即可得到,该字符出现总次数》for循环计数。
参考代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
char a;
string b;
while(cin>>a>>b)//多组测试数据
{
int s=0;// 注意s初始化的位置
for(int i=0;i<b.size();i++)
{
if(b[i]==tolower(a) || b[i]==toupper(a)) //b[i]的值等于a的大写或小写形式都要纳入计数
{
s++;
}
}
cout<<fixed<<setprecision(5)<<s*1.0/b.size()<<endl;
// printf("%.5f\n",s*1.0/b.size());
}
return 0;
}
4、墓碑上的字符(insert()函数 / substr()函数应用)
分析:
(1)插入--》即insert( ) 函数,插入函数格式为:insert(插入起点下标,插入内容);只要找到插入的下标,就可以完成这个工作。
(2)对于任意偶数长度的字符串a,它的中间位置应当是a.size()/2。根据样例可得,插入是从a.size()/2这个位置后开始的。
(3)如果不用插入函数,这道题用substr()函数也完全可以搞定,-》分别提取第一个串的前半段、第二个串、第一个串的后半段,即可以在不改变两个串内容的基础上得到插入的效果。
参考代码:
方案一:insertt()函数
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
string a,b;
cin>>n;
while(n--)
{
cin>>a>>b;
a.insert(a.size()/2,b); //将 b 的内容直接插入a中
cout<<a<<endl; //输出插入后的a
}
return 0;
}
方案二:substr()函数
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
string a,b,c;
cin>>a>>b;
int t=a.size()/2; //记录中间位置下标
c=a.substr(0,t)+b+a.substr(t,t);//分别提取a的前半段,b,a的后半段,并赋值给c
cout<<c<<endl;
}
}
作业题:
二、stringstream流
stringstream是c++标准库提供的字符串流,和之前学过的iostream的操作类似。stringstream可以像cin和cout一样来使用>>、<<进行字符串流的输入输出。
stringstream一般用于将一个字符串分割,以及数据转换。使用stringstream需要加头文件:#include<sstream>。
1、使用格式
stringstream sin; //定义一个stringsteam 类型的变量sin
sin<<变量名1; //向流中传值,把变量1的值输入到流中
sin>>变量名2; //从流中取值,把流中的数据输入到变量2中
cout<<变量1; sin<<变量1;
cin>>变量2; sin>>变量2; //尖头指向谁,就是将东西给谁
2、使用对象
(1)stringstream常用来进行字符串和其他类型之间的相互转换。
【举例一】:将字符串转换为其他类型
#include<bits/stdc++.h>
using namespace std;
int main()
{
//string 转为 int
string s="1234566";
int a=0;
stringstream sin;
sin<<s;
sin>>a;
cout<<"a转换后为:"<<a;
return 0;
}
运行结果: |
---|
a转换后为:1234566 |
【举例二】:将其他类型转换为字符串
#include<bits/stdc++.h>
using namespace std;
int main()
{
//int 转为 string
string s="abc";
int a=12345;
stringstream sin;
sin<<a;
sin>>s;
cout<<"s转换后为:"<<s;
return 0;
}
运行结果: |
---|
s转换后为: 12345 |
(2)stringstream可用于从整行或整段数据中拆分出字符串、整型、浮点型等数据。
【举例三】:读入一行数据,拆分出字符串、整型和浮点型数据并显示。
程序一:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s="Todayis 2020 12.31";
string s1;
int a;
double b;
stringstream sin;
sin<<s;
sin>>s1>>a>>b;
cout<<"s1:"<<s1<<" a:"<<a<<" b:"<<b;
return 0;
}
运行结果:
s1:Todayis a:2020 b:12.31
程序二:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s="Todayis 12.31 2020";
string s1;
int a;
double b;
stringstream sin;
sin<<s;
sin>>s1>>a>>b;
cout<<"s1:"<<s1<<" a:"<<a<<" b:"<<b;
return 0;
}
运行结果:
s1:Todayis a:12 b:0.31
上述两个程序的运行结果完全不同,这是因为:①stringstream读入数据时,以空格作为分隔符。②拆分的顺序会影响转换的结果。