【C++从0到王者】第九站:String基本介绍及使用(下)

简介: 【C++从0到王者】第九站:String基本介绍及使用

五、一些经典的力扣题

1.仅仅反转字母

题目链接:仅仅反转字母

这道题思路很简单,我们采用双指针,利用快速排序的思路即可。isalpha()函数是判断一个字符是否为英文字母,若是返回真,否则返回假

class Solution {
public:
    string reverseOnlyLetters(string s) {
        int end=s.size()-1;
        int begin=0;
        while(begin<end)
        {
            while((begin<end)&&(!isalpha(s[begin])))
            {
                begin++;
            }
            while((begin<end)&&(!isalpha(s[end])))
            {
                end--;
            }
            swap(s[begin],s[end]);
            begin++;
            end--;
        }
        return s;
    }
};

2.字符串相加

题目链接:https://leetcode.cn/problems/add-strings/

对于这道题,我们的思路是逐位相加。从末尾开始一步一步相加。一开始让进位端为0,然后将相加端都给提取出来,让这三个相加,得到一个数,然后考虑进位,然后将字符给一位一位加上去,最后逆置字符串即可。

class Solution {
public:
    string addStrings(string num1, string num2) {
        int end1=num1.size()-1;
        int end2=num2.size()-1;
        string s;
        int carry=0;
        while(end1>=0||end2>=0)
        {
            int val1= (end1>=0)?num1[end1]-'0':0;
            int val2= (end2>=0)?num2[end2]-'0':0;
            end1--;
            end2--;
            int ret=val1+val2+carry;
            carry=ret/10;
            ret=ret%10;
            s+=ret+'0';
        }
        if(carry>0)
        {
            s+='1';
        }
        reverse(s.begin(),s.end());
        return s;
    }
};

当然我们也可以采用头插的方式,由于库中并没有给出头插的方式,因为头插的效率太低,string的底层是一个顺序表,我们知道对于顺序表更喜欢尾插。虽然没有头插,但是提供了insert的接口

我们使用第六个成员函数即可。将一个字符插在某个迭代器之前

class Solution {
public:
    string addStrings(string num1, string num2) {
        int end1=num1.size()-1;
        int end2=num2.size()-1;
        string s;
        int carry=0;
        while(end1>=0||end2>=0)
        {
            int val1= (end1>=0)?num1[end1]-'0':0;
            int val2= (end2>=0)?num2[end2]-'0':0;
            end1--;
            end2--;
            int ret=val1+val2+carry;
            carry=ret/10;
            ret=ret%10;
            //s+=ret+'0';
            s.insert(s.begin(),ret+'0');
        }
        if(carry>0)
        {
            //s+='1';
            s.insert(s.begin(),'1');
        }
        //reverse(s.begin(),s.end());
        return s;
    }
};

虽然两种方式都可以,但是综合来看,第一种的效率更佳,总时间复杂度为O(N),第二种的总时间复杂度为O(N2)。

六、String其他接口

1.operator[]操作符

这个操作符,在文章我前面已经介绍过,这里在此简单的介绍一下

这个函数可以去访问string某个下标的元素,他有两个函数重载,一个是加了const修饰的,一个是未修饰的,函数在使用时候会自动匹配最合适的一个函数来进行调用

2.at

at其实与operator[]几乎是一样的。

at和operator[]唯一的不同之处就在于对于越界的检查是不一样的

当发生越界的时候,at是抛异常的方式,operator[]则是断言的方式

即at比较温柔一点,operator[]比较暴力

3.assign

assign这个接口的功能是赋值,他有以下的函数重载

如下是他与append的对比

4.insert

insert顾名思义就是在某个位置插入,他有如下的函数重载:

这些函数的功能也是比较明确简单的

如下代码是部分函数的演示

int main()
{
  string s1("hello world");
  s1.append("xxxxxx");
  cout << s1 << endl;
  s1.assign("xxxxxx");
  cout << s1 << endl;
  s1.insert(0, "hello");
  cout << s1 << endl;
  s1.insert(5, "world");
  cout << s1 << endl;
  s1.insert(0, 10, 'x');
  cout << s1 << endl;
  s1.insert(s1.begin()+10, 10, 'y');
  cout << s1 << endl;
  return 0;
}

insert虽然看上去不错,但是效率比较低下,不宜多用。

5.erase

erase用于从pos位置删除n个字符

如下所示是这个函数的演示

6.replace

顾名思义,这个函数的意思是替代

如下所示是replace函数的一些使用

然而这个函数看似方便,实际上效率极低。一般不会轻易使用这个函数

比如说当我们想要将某个字符串的空格替换为20%的时候,我们可以使用这个函数,但是效率太低,不满意。我们可以使用其他的函数来实现这个功能

int main()
{
  string s1("hello world hello world");
  string s2;
  for (auto ch : s1)
  {
    if (ch != ' ')
    {
      s2 += ch;
    }
    else
    {
      s2 += "20%";
    }
  }
  s1 = s2;
  cout << s1 << endl;
}

7.c_str

这个函数的功能是返回他底层的字符串

这个函数一般是用于跟c的一些接口函数进行配合

int main()
{
  string filename = "test.cpp";
  FILE* fout = fopen(filename.c_str(), "r");
  return 0;
}

我们使用string类型而不是直接使用字符串的好处就在于,string的库非常丰富。我们可以直接去进行调用

8.find

顾名思义,他的功能就是查找,有如下几个函数重载

如果找到了对应的内容,就返回这个位置的下标

9.substr

find可以很方便的找到要找到内容的起始下标。而substr的功能则是取出字符类中字符串中的某一部分,并且返回这一部分

这样的话,我们就可以使用find和substr进行搭配,来进行网站的分割

我们知道网站分为三部分:协议,域名,资源

我们对一个网站进行分割的代码如下所示

int main()
{
  string ur1 = "https://home.firefoxchina.cn/?fromwww";
  size_t pos1 = ur1.find("://");
  //协议
  string protocol;
  if (pos1 != string::npos)
  {
    protocol = ur1.substr(0, pos1);
  }
  //域名和资源
  string domain;
  string uri;
  size_t pos2 = ur1.find('/', pos1 + 3);
  if (pos2 != string::npos)
  {
    domain = ur1.substr(pos1 + 3, pos2 - (pos1 + 3));
    uri = ur1.substr(pos2 + 1);
  }
  cout << protocol << endl;
  cout << domain << endl;
  cout << uri << endl;
  return 0;
}

10.rfind

rfind和find类似,只不过他是从后往前找,这样的好处在于找一个文件的后缀,因为一个文件可能会有多个后缀,所以我们显然不可能从前往后找,我们必须从后往前找,故

11.find_first_of

从名字上来说,它的功能似乎与find类型?

其实不然,虽然它的参数也和find一样,但它的功能是从所给的字符串中,找到第一个和这里面中的任何一个字符相同的字符位置

如下代码所示,功能就是找出这句话中aeiou的位置,并将其替换为*字符

12.find_last_of

这个函数的功能和上面的是十分类似的,唯一不同的就是它是从后往前找的

13.relational operators

这里面其实就是一些运算符重载,其实里面的函数实现是存在一些冗余的,只需要实现对象和对象之间的比较即可,其他的都有隐式类型转换

14.operator+

这个运算符重载也很好理解,就是两个字符串进行相加,但需要注意的是,相加后是不改变原来的对象的

15.getline

这个函数的功能需要与cin对比来看,cin相当于scanf,getline相当于gets。cin当遇到空格时就不读了。而getline可以自己设置结束读取标志,或者默认换行时候才结束,这就在当我们读取一个句子的时候,由于有空格,我们就必须使用getline函数了

我们可以看下面这个例子

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

下面才是正确的代码

#include <iostream>
using namespace std;
int main() 
{
    string s;
    getline(cin,s);
    int len=s.size();
    int pos=s.rfind(' ');
    if(pos!=string::npos)
    {
        cout<< len-(pos+1);
    }
    else 
    {
        cout<< len;
    }
}

16.string转为其他类型

在c语言中字符串转为其他类型时候有两个函数可以去调用:atoi,itoa

但是这两个函数其实并不是很好用

在c++中,我们有这样一系列的函数可以进行转换

17.其他类型转化为string类型

有以下函数重载可以实现这个功能

七、string与模板

我们也许会发现,string貌似跟类模板关系不是很大。

但其实string也是一个模板出来的

我们可以注意到,string其实typedef出来的

类似的,其实还有很多的string

相关文章
|
15天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
37 5
|
15天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
26 2
|
2月前
|
C++ 容器
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
23 1
|
2月前
|
C++ 容器
|
2月前
|
C++ 容器
|
2月前
|
C语言 C++
深度剖析C++string(中)
深度剖析C++string(中)
50 0
|
2月前
|
存储 编译器 程序员
深度剖析C++string(上篇)(2)
深度剖析C++string(上篇)(2)
38 0
|
2月前
|
存储 Linux C语言
深度剖析C++string(上篇)(1)
深度剖析C++string(上篇)(1)
33 0
|
2月前
|
C++