【C++】string类(简介,接口,oj 包学包会)

news2024/11/15 7:54:19

🍅之前学习过类和对象,明确了C++是面向对象编程,那不得不提常见对象——字符串

目录

☃️1.基本介绍

☃️2.string中金典常见接口

 🐝2.1  reserve()和resize()(capacity()和size())

🐝2.2   迭代器和反向迭代器(iterator(),begin(),end(),rbegin(),rend())

🐝2.3   c_str()

🐝2.4   substr()

🐝2.5   at()

🐝2.6   insert()和erase()

🐝2.7   find()和find_first_of()系列

🐝2.8   swap()

🐝2.9   reverse()

☃️3.用string接口写模拟oj

 🐝3.1把字符串转换成整数

 🐝3.2 字符串相加

 🐝3.3 仅仅反转字母

 🐝3.4 字符串中的第一个唯一出现一次的字符

🐝3.5  字符串最后一个单词的长度

🐝3.6验证回文串

🐝3.7反转字符串

🐝3.8反转字符串中的单词

🐝3.9字符串相乘

🐝3.10 找出字符串中第一个只出现一次的字符 


 ☃️1.基本介绍

在C语言中我们也做过很多字符串的题目吗,但是真的有些题好麻烦,C++为了更方便操作提供了一系列在string库里的接口,string类是使用char(作为它的字符类型,使用它的默认char_traits和分配器类型
string类basic_string模板类的一个实例使用char来实例化basic_string模板类并用char_traits
和allocator作为basic_string的默认参数
注意:这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作

使用接口函数一定要包含头文件

 

☃️2.string中金典常见接口

 🐝2.1  reverse()和resize()(capacity()和size())

最最金典的就是这个老生常谈的问题

首先字面意思,capacity指string类的容量,不同编译器初始化时设置的capacity不同,返回值是size_t,调用方式如下

string s("hello world");
size_t a=s.capacity();

size()是字符串长度,不包括'\0',size()接口和length()接口功能 用法完全一样,返回值是size_t

string s("hello world");
size_t a=s.size();

 reserve()和resize()就是围绕上面两个参数(容量,长度)展开

一言蔽之:

reserve() 只修改容量,当调整的容量小于当前空间容量时,容量不减少

resize() 只修改长度

看下实例 

很奇怪,为什么两个reserve(100)之后的修改值不一样

这个就是设计者的设计,可能是函数里面的数字n,也可能是更大,但是我们做题都是默认n,不会考虑特殊情况(在没有说明的情况下),

此外,第一次reserve(100)  下面reserve(50)不会再修改容量值

 

resize(n)的结果和想象的一样,不做解释

🐝2.2   迭代器和反向迭代器(iterator(),begin(),end(),rbegin(),rend())

 首先看一下begin() 和 end() 两个接口,字面意思就是指向头尾的指针,注意类型是迭代器   类似于指针

关于迭代器这里不做详细描述,以后会写一篇博客,具体谈一谈迭代器的多种玩法

先来看一个很简单的正向迭代器,他往往就是和begin()  end() 配合使用的,在oj中begin()和end()也是常用的 

 

 


有正向就有反向 ,rbegin() 和 rend() 就是从字符串结尾开始匹配

反向迭代器指针,当然要搭配反向迭代器

当然还有const类型的迭代器

普通版本的可读可写

特殊版本 

string::const _iterator begin() const;

 在begin()接口,就能看到是有一个const迭代器的

 可以验证 确实是不可以修改的

当然还有const的反向迭代器,举一反三

🐝2.3   c_str()

这个接口的返回值是const char *类型 指针,存储字符串位置的地址

这个函数是十分不可靠的,因为使用c_str()进行字符串赋值之后,如果对string中的char* 改变,那么c_str()中的值就很不可靠

 

储存字符串位置的指针 解引用找到的就是整个字符串

但是想打印地址的时候需要强转一下

🐝2.4   substr()

 子串,从pos位置取len长度的子串

 若len不指定/为负/为空/大于size() 都是取到字符串结束

默认从左开始数pos位置

🐝2.5   at()

访问pos位置的元素 

字符串当然可以用[ ]访问,越界时直接报错 断言

但是使用at(),越界时抛异常,而异常可以被捕获(以后细讲),格式如下

 

实际中很少使用at(),因为和下标[ ]访问没什么区别 

🐝2.6   insert()和erase()

种类真的是.......

总结一下就是死一个参数一般是要插入的位置,第二个参数是数字代表要插入的个数,是字符代表要插入的字符,是字符串同理,第三个参数是字符或者字符串

位置pos 代表你想在pos之前插入

 注意插入空格的时候一定要插入字符的形式,不可以插入空串

 erase

 

第一个参数是数字代表要删除的位置,第二个参数是数字代表要删除的长度

参数也可以是迭代器,就是删除迭代器位置的字符 

🐝2.7   find()和find_first_of()系列

第一个参数一般是要寻找的字符或者字符串,第二个参数是开始寻找的位置,默认缺省值是0位置 

返回值:出现的位置/ string::npos

 npos是size_t的最大值,一般寻找失败都是返回npos

当然还有rfind,就是倒着找字符

其实这个很好用,可以看一道笔试题

替换空格 

解法一:

既然是替换,string也提供了替换的相应函数

 

 可以看到效率十分低

class Solution {
public:
    string replaceSpace(string s) {
size_t pos=s.find(' ');
while(pos!=string::npos)
{
    s.replace(pos,1,"%20");
    pos=s.find(' ');
}
return s;
    }
};

解法二:

把replace的原理自己写一下(自己扩容,然后创建新串,以空间换时间) 

class Solution {
public:
    string replaceSpace(string s) {
size_t num=0; //提前计算好空格的数量方便扩大capacity
for(auto ch:s)
{
    if(ch==' ')num++;
}
s.reserve(num*2+s.size());
string newstr;
for(auto ch:s)
{
    if(ch != ' ')
        newstr+=ch;
    else
    newstr+="%20";
}
return newstr;
    }
};

 find_first_of(const string&str,size_t pos=0)

从字符串中找 在str中出现的字符,出现了就停一下

返回值:出现的位置/string::npos

 

 把每一个出现a的位置都替换成*

还有他的好多兄弟

基本上望文生义,大家可以去网站上自己搜索cplusplus.com 

🐝2.8   swap()

之前我们说std库函数已经有swap()

但是这个string类的函数,可以直接交换两个字符串的指针,对于字符串来说效率更高 

🐝2.9   reverse()

revers()函数并不是string类的接口函数  ,但是他很常用

参数一般是迭代区间

string.reverse(迭代器起始,迭代器末尾);

☃️3.用string接口写模拟oj

 🐝3.1把字符串转换成整数

首先要处理前面的加减号,并且让遍历数字的时候可以从下标1开始

第一个数字的权重要10倍增长 

class Solution {
public:
    int StrToInt(string str) {
        int flag=1;
        int i=0;
         if(str[i]=='-' || str[0]=='+')
        {
            if(str[0]=='-')
            flag=-1;
            i++;
        }
        
int ans=0;
for(;i<str.size();i++)
{
    
   
    if(str[i]<'0'||str[i]>'9')
    return 0;
    ans=ans*10+str[i]-'0';
}
      return flag*ans; 
    }
};

 🐝3.2 字符串相加

注意要进位,并且最后如果进位数字不是0,还需要把最后一位加上 

class Solution {
public:
    string addStrings(string num1, string num2) {
int end1=num1.size()-1,end2=num2.size()-1;
string ans("");
int tmp=0;//进位
while(end1>=0 &&end2>=0)
{
    int a=num1[end1]-'0',b=num2[end2]-'0';
    if(a+b+tmp<10)
    {
        ans+=a+b+tmp+'0';
        tmp=0;
    }
    else
    {
        ans+=(a+b+tmp)%10+'0';
        tmp=(a+b+tmp)/10;
    }
   end1--;end2--;
}
while(end1>=0) 
{
    if(num1[end1]-'0'+tmp<10)
    {
        ans+=num1[end1]+tmp;
        tmp=0;
    }
    else
    {
        ans+=(num1[end1]-'0'+tmp)%10+'0';
        tmp=(num1[end1]-'0'+tmp)/10;
    }
    end1--;
}
while(end2>=0) 
{
    if(num2[end2]-'0'+tmp<10)
    {
        ans+=num2[end2]+tmp;
        tmp=0;
    }
    else
    {
        ans+=(num2[end2]-'0'+tmp)%10+'0';
        tmp=(num2[end2]-'0'+tmp)/10;
    }
    end2--;
}
if(tmp)
{
    ans+=tmp+'0';
}
int begin=0,end=ans.size()-1;
while(begin<end)
{
    swap(ans[begin++],ans[end--]);

}
return ans;
    }
};

 

 🐝3.3 仅仅反转字母

先判断一下是不是字符(有库函数) 

 

class Solution {
public:

    string reverseOnlyLetters(string s) {
     size_t begin =0,end=s.size()-1;
     while(begin<end)
     {
         while(begin<end && !isalpha(s[begin]))
         begin++;
         while(begin<end && !isalpha(s[end]))
         end--;
         swap(s[begin++],s[end--]);

     }
      return s;
    }
};

 

 🐝3.4 字符串中的第一个唯一出现一次的字符

还是传统的映射

class Solution {
public:
    int firstUniqChar(string s) {
int a[26]={0};
for(auto ch:s)
{
    a[ch-'a']++;
}
for(int i=0;i<s.size();i++)
{
    if(a[s[i]-'a']==1) return i;
}
return -1;
    }
};

 

🐝3.5 字符串最后一个单词的长度

从后往前找空格,然后处理空格到结尾这段子串 

#include <iostream>
#include <string>
using namespace std;

int main() {
   string str;
   getline(cin,str);
   size_t a=str.rfind(' ');
   if(a!=string::npos)
   {
       cout<<str.size()-a-1<<endl;
   }
   else {
   cout<<str.size()<<endl;
   }
   return 0;
  
}

 

🐝3.6验证回文串

去掉非字母数字的字符,然后把干净的字符串逆置看是否相等 

class Solution {
public:
    bool isPalindrome(string s) {
    string a;
    for(auto ch:s )
    {
        if(isalnum(ch))
        a+=tolower(ch);
    }
    string rev(a.rbegin(),a.rend());
    return rev==a;
    }
};

🐝3.7反转字符串二

class Solution {
public:
    string reverseStr(string s, int k) {
int n=s.size();
for(int i=0;i<n;i+=2*k)
{
    reverse(s.begin()+i,s.begin()+min(n,i+k)); 
    //更小的是n(全翻转),代表i+k>n,n-i<k(剩余量<k)
    //更小的是i+k(翻转前k),代表i+k<n,n-i>k,剩余量>k
}
return s;
    }
};

 

🐝3.8反转字符串中的单词 III

以空格为分割,把握好结束条件

class Solution {
public:
 string reverseWords(string s) {
    int begin = 0;
    int space = s.find(' ');
    while (begin < s.size())
    {
        int i = begin;
        int ret = space - 1;
        for (; i < ret; i++)
        {
            swap(s[i], s[ret--]);
        }
        begin = space + 1;
        space = s.find(' ', space + 1);
        if (space == string::npos && begin < s.size())
        {
            space = s.size();
        }
        else if (space == string::npos && begin >= s.size())
            return s;
       
    }
    return s;
}
};

🐝3.9字符串相乘

和相加差不多思路 

class Solution {
public:
    string multiply(string num1, string num2) {
if(num1=="0" || num2=="0")
return "0";
int end1=num1.size(),end2=num2.size();
auto a=vector< int>(end1+end2+1);
for(int i=end1-1;i>=0;i--)
{
    int tmp1=num1.at(i)-'0';
    for(int j=end2-1;j>=0;j--)
    {
        int tmp2=num2.at(j)-'0';
        a[i+j+1]+=tmp1*tmp2;
    }
}
for(int i=end2+end1-1;i>0;i--)
{
a[i-1]+=a[i]/10;
a[i]%=10;
}
int index=a[0]==0?1:0;
string ans;
 while (index < end1+end2) {
            ans.push_back(a[index]);
            index++;
        }
        for (auto &c: ans) {
            c += '0';
        }
        return ans;
    }
};

 

🐝3.10找出字符串中第一个只出现一次的字符

一定要注意,是原串里第一个出现的,而不是传统的映射关系  

#include <iostream>
#include <string>
#include <type_traits>

using namespace std;

int main(){
    string s;
    int flag = -1;
    while(getline(cin, s)){
        for(int i = 0; i < s.size(); i++){
            if(s.find(s[i]) == s.rfind(s[i])){
                flag = 1;
                cout<<s[i]<<endl;
                break;
            }
        }
        if(flag == -1){
            cout<<-1<<endl;
        }
    }
}

 创作不易,感谢观看

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入浅出带你学习无参RCE

前言 无参RCE,顾名思义就是当我们不能传入参数的情况下进行命令执行&#xff0c;因为一般情况下命令执行必须是要含有参数的&#xff0c;本文会就着无参RCE问题带大家学习CTF中常见的无参RCE方式及用法&#xff0c;下面我们展开文章来讲解一下。 基础知识 首先我们要了解&am…

Revit剖面操作:怎么做折线剖面和快速剖面

一、Revit中如何做折线剖面 在绘图过程中&#xff0c;有时候根据实际情况需要绘制折线剖面&#xff0c;这里就简单介绍一些折线剖面的绘制方法。 1、选择视图选项卡中“剖面”绘制剖面&#xff0c;如图1所示。 2、选中“剖面”&#xff0c;点击右上角“拆分线段”&#xff0c;如…

ctf-show-misc-游戏题

目录前言Misc22超级玛丽魂斗罗游戏flag 终结篇加油各位( •̀ ω •́ )y 期待与君再相逢前言首先感谢ctf平台和出题的大佬其次感谢各位读者&#xff0c;对我的支持( •̀ ω •́ )y 有什么问题和建议可以私聊我本次出了一个专题&#xff0c;就是游戏专题 把所以关于游戏杂项的…

如何提高自动化测试覆盖率

自动化测试一直是测试人员的核心技能&#xff0c;也是测试的重要手段之一。尤其是在今年所谓的互联网寒冬的行情下&#xff0c;各大企业对测试人员的技术水平要求的很高&#xff0c;而测试人员的技术水平主要集中在三大自动化测试领域&#xff0c;再加测试辅助脚本的编写&#…

关于 DataLeap 中的 Notebook,你想知道的都在这

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 DataLeap 是火山引擎数智平台 VeDI 旗下的大数据研发治理套件产品&#xff0c;帮助用户快速完成数据集成、开发、运维、治、资产、安全等全套数据中台建设&#xff…

java-spring_bean实例化

bean是如何创建的实例化bean的三种方式构造方法静态工厂&#xff08;了解&#xff09;实例工厂与FactoryBean实例工厂FactoryBeanbean是如何创建的实例化bean的三种方式 构造方法 bean本质上就是对象&#xff0c;创建bean使用构造方法完成 提供可访问的构造方法 public clas…

现实版“狂飙”上演,背后有哪些猫腻?

目录 披着电商外衣行洗黑钱之实 电商平台如何防范黑灰产作恶 最近热播的电视剧《狂飙》中有这样一个故事情节&#xff0c;刑满释放的唐小虎出狱之后&#xff0c;大哥高启强就大方的赠予唐小虎一家游戏厅。但其表面上是游戏厅&#xff0c;实际上背后却暗藏赌场。而在后来的剧情…

<<Java开发环境配置>>5-MySQL安装教程(绿色版)

一.MySQL绿色版安装: 1.直接解压下载的ZIP文件到对应的目录下(切记安装目录不要有中文); 如图:我的安装目录:D:Program Files 2.创建配置文件: 在MySQL安装目录下&#xff0c;创建一个my.ini配置文件&#xff0c;然后在里面添加以下内容&#xff08;别忘了MySQL安装目录要改成…

基于单片机的温度控制系统设计(32+WIFI+蓝牙版)-实物设计

编号&#xff1a;M22033-04M设计简介&#xff1a;基础功能&#xff1a;1、可以通过温度传感器检测温湿度2、可以通过按键设置温度阈值3、当温度超过阈值时&#xff0c;蜂鸣器报警扩展功能&#xff1a;1、通过蓝牙连接手机并通过手机实现监控2、通过WiFi连接手机并通过手机实现监…

程序员一般通过什么途径接私活?

判断私活是否靠谱的通用标准&#xff1a; 1.钱款是否有担保&#xff0c;能做到“钱和代码两清” 2.项目是否真实&#xff0c;需求文档清晰&#xff0c;结款时间一目了然 3.项目来源是否可靠&#xff0c;渠道是否正规接私活的途径主要包括&#xff1a; 1.熟人/朋友介绍。这样的…

transformer总结

1.注意力机制 意义&#xff1a;人类的注意力机制极大提高了信息处理的效率和准确性。 公式&#xff1a; 1)自注意力机制 b都是在考虑了所有a的情况下生成的。 以产生b1向量为例&#xff1a; 1.在a这个序列中&#xff0c;找到与a1相关的其他向量 2.每个向量与a1关联的程度&a…

网络编程套接字(上篇)UDP实现简易多人聊天室

目录 背景知识 主机间通信本质 socket 端口号特点&#xff1a; 为什么不用进程pid&#xff1f; 网络字节序 socket编程接口API sockaddr结构 ​编辑 简单UDP网络程序 了解UDP协议 简易多人聊天室实现 服务端代码&#xff1a; 客户端代码&#xff1a; 背景知识 主…

MySQL第六章第四次作业

学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept) 学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键 课程表&#xff1a;Course (Cno, Cname,) 课程号&#xff0c;课程名 Cno为主键 学生选课表&#xff1a;SC (Sno, Cno, Score)…

java切换版本等注意事项

启动java工具&#xff0c;命令行为&#xff1a;java -jar xxx.jar 注意burpsuite&#xff0c;behinder需要jdk&#xff0c;如果是这个例子&#xff0c;jdk-11.0.12&#xff0c;shiro_attack_2.2需要jdk版本jdk1.8.0_291。 jdk版本切换方式&#xff1a; 编辑&#xff5e;目录…

教育舆情监测关键词有哪些,TOOM教育舆情监测系统流程?

教育舆情监测是指对教育领域的舆情进行收集、分析和处理的过程。舆情是指公众在各种渠道上对教育政策、教育机构、教育事件等方面的言论、态度和情绪。通过对教育舆情的监测和分析&#xff0c;可以了解公众对教育行业的看法和反应&#xff0c;提高对教育行业的管控能力&#xf…

MFC入门

1.什么是MFC?全称是Microsoft Foundation Class Library&#xff0c;我们称微软基础类库。它封装了windows应用程序的各种API以及相关机制的C类库MFC是一个大的类库MFC是一个应用程序框架MFC类库常用的头文件afx.h-----将各种MFC头文件包含在内afxwin.h-------包含了各种MFC窗…

AcWing语法基础课笔记 第六章 C++中的函数

第六章 C中的函数 函数让代码变得更加简洁。 ——闫学灿 目录 1.函数基础 1.1编写函数 1.2调用函数 1.3形参和实参 1.4函数的形参列表 1.5函数返回类型 1.6局部变量、全局变量与静态变量 2.参数传递 传值参数​编辑 2.2传引用参数 2.3数组形参…

从事1年软件测试,只会功能测试,想进一步学习,有没有好的建议呢?

作为一个在软件测试领域奋斗10年的老人&#xff0c;我前8年先后在不同的互联网公司担任高级软件测试工程师&#xff0c;测试主管等职&#xff0c;所以这么多年下来&#xff0c;也算是身经百战&#xff0c;阅人无数了。 根据粉丝的提问&#xff0c;得到你当前的状态是1&#xf…

中国天气——低纬度和高纬度环流复习笔记

低纬度和高纬度环流 低纬度大气运动基本特征 中低纬度大气运动的差别 低纬度的地转参数f很小&#xff0c;天气尺度系统具有非地转特性&#xff0c;但吃到以外的行星尺度还是有准地转近似特性因此中纬度有效的气压场和温度场分析系统运动和变化的方法在低纬度不再适用&#x…

虚拟现实三维数字沙盘电子沙盘可视化交互开发教程第5课

虚拟现实三维数字沙盘电子沙盘可视化交互开发教程第5课 设置system.ini 如下内容 Server122.112.229.220 userGisTest Passwordchinamtouch.com 该数据库中只提供 成都市火车南站附近的数据请注意&#xff0c;104.0648,30.61658 在鼠标指定的位置增加自己的UI对象&#xff1…