C++STL之string类的使用

目录

  • 1.STL简介
    • (1)什么是STL
    • (2)STL的版本
    • (3)如何学习STL
    • (4)STL的六大组件
  • 2.string类的基本概念
    • (1)含义
    • (2)使用方法
    • (3)原理
  • 3.string类中常见构造函数
    • 4.string类中析构函数
      • 5.string类对象的容量操作
        • (1)显示容量
        • (2)扩容
      • 6.string类中operator[]重载
        • (1)举例
        • (2)底层实现
      • 7.string类与迭代器
        • (1)举例
        • (2)反向迭代器
        • (3)使用迭代的意义
        • (4)补充:语法糖实现遍历
      • 8.string类对象的增删操作
        • (1)增删
        • (2)查与匹配
      • 9.string类中自定义插入与删除(效率低,不建议使用)
        • 10.string类字符串的比较
          • 11.string类字符串的转换
            • 12.总结

              1.STL简介
              (1)什么是STL
              STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
              可以理解为就是一个类似stdio.h的库,包含了这个库,里面的语法或者函数可以直接使用。

              (2)STL的版本
              最原始的版本是由Alexander Stepanov和Meng Lee开发的,并且他们要求对其进行开源处理。之后又经历了PJ.版本,RW版本,SGI版本等,目前SGI版本最应用最广泛的版本,我们后面学习STL要阅读部分源代码,主要参考这一版本。
              总结一下目前开源与闭源的操作系统或者软件:
              开源:STL,linux,git,Vue
              闭源:IOS,Windows

              (3)如何学习STL
              第一境界:熟练使用STL。
              第二境界:了解STL的源代码,即了解底层。
              第三境界:会自己扩充STL库。
              废话不多说,正式进入主题:

              (4)STL的六大组件
              STL有六大组成部分,我们会来逐一学习:
              C++STL之string类的使用
              文章图片

              首先我们来学习容器中的string类。

              2.string类的基本概念
              (1)含义
              string类,顾名思义是进行字符串操作的一个类,操作方式即使用其中的成员函数来进行操作。

              (2)使用方法
              #includeusing namespace std;

              string也是在类域std中的,我们在练习时也可以将类域std打开。

              (3)原理
              C++STL之string类的使用
              文章图片

              通过查阅文献,我们发现string类原来是typedef出来的,是对basic_string这一模板传入char类型时起的别名。这一模板的定义方式大概是这样的:
              templateclass basic_string{private:T* _str; //....}

              有人会问为什么要使用模板呢?字符串类型除了char还有别的嘛?
              其实字符类型除了char之外还有别的类型,比如wchar_t就占两个字节。我们存储汉字一般会使用两个字节来进行存储。所以对于两字节存储的字符再使用basic_string传入wchar_t起别名的话就方便的多了。
              注意:string类中传入的是char,上面只作了解即可。
              【C++STL之string类的使用】
              3.string类中常见构造函数 构造函数即用于初始化。
              1.string():构造空的string类对象str,即空字符串。
              2.string (const char* s):向对象中传入字符串来构造string对象。
              3.string(size_t n,char c):string类对象中包含n个字符c。
              4.string(const string&s):拷贝构造函数。
              string s1; //空字符串s1。 string s2("hello world"); //向s2中传入hello world。 string s3(s2, 2, 6); //向s3中传入s2中从第二个开始(不包括第二个)后六个字符。当最后不加数值时(即不加6),则会取后面的全部字符。 string s4(s2); //用s2对s4进行初始化。 cout << s1 << endl; //重载运算符,可以直接打印s1对象的字符串内容。 cout << s2 << endl; cout << s3 << endl; cout << s4 << endl;


              4.string类中析构函数 自动调用,不用管。

              5.string类对象的容量操作 1.size:返回有效字符长度。
              2.length:返回字符串的有效字符长度。是一个历史残留问题。
              3.capacity:返回空间总大小。
              4.empty:检测字符串是否为空,是返回true,不是返回false
              5.clear:清空有效字符。
              6.reserve:为字符串预留空间。
              7.resize:将有效字符改成n个,多出的用字符C填充。

              (1)显示容量
              string s1("hello world"); cout << s1.size() << endl; //输出字符串大小,不包括'\0' cout << s1.length() << endl; //输出字符串大小,不包括'\0' cout << s1.capacity() << endl; //输出空间总大小 s1.clear(); //清空有效字符串 cout << s1 << endl;

              C++STL之string类的使用
              文章图片


              (2)扩容
              扩容一般使用两种函数,reserve与resize。reserve主要为开空间,而resize在开空间的同时还会进行初始化。
              string s1("hello world"); cout << s1.capacity() << endl; s1.reserve(100); cout << s1.capacity() << endl;

              打印的结果是:
              C++STL之string类的使用
              文章图片

              通过打印我们发现,reserve扩展的空间是在原有字符串大小基础上扩展的,而不是在原有容量的基础上。
              string s1("hello world"); s1.resize(100,'x');

              我们可以通过调试来观察这段代码的效果:
              C++STL之string类的使用
              文章图片

              我们发现hello world并没有被覆盖,最大空间变成了111和reserve一样。但是,x只有89个,一共增加了100-11个x,但是在hello world后面增加了100个空间。
              如果我们开辟的空间小于字符串本身呢?s1.resize(5)表示的是只保留前五个字符大小。

              6.string类中operator[]重载

              (1)举例
              我们可以使用s1[i]来进行字符的读或者写的操作。
              string s1("hello world"); for (size_t i = 0; i < s1.size(); i++) {cout << s1[i] << " "; //s1[i]进行读操作s1[i] += 1; } cout << endl; for (size_t i = 0; i < s1.size(); i++) {cout << s1[i] << " "; //s1[i]进行写操作 }

              C++STL之string类的使用
              文章图片


              (2)底层实现
              char& operator[](size_t pos){return _str[pos]; //返回pos位置所在的字符}

              注意,这里使用引用返回不是为了减少拷贝,这里是为了修改返回对象。
              at也是和operator[]一样,但是检测越界的方法不同,operator[]使用断言,at直接抛异常。

              7.string类与迭代器 (1)举例
              在刚开始使用迭代器时,我们可以把它想象成一个指针类型。
              string s1("hello world"); string::iterator it = s1.begin(); while (it != s1.end()) {cout << *it << " "; ++it; } cout << endl;

              其中it就是一个迭代器类型的变量,由于函数iterator在类内,因此在使用时需要首先指明类域。
              C++STL之string类的使用
              文章图片

              我们仍然使用解引用操作符来进行类似解引用的操作。我们同样也可以通过*来对字符串的内容进行修改,对这段代码打印的结果是:
              C++STL之string类的使用
              文章图片


              (2)反向迭代器
              反向迭代器使用函数reverse_iterator
              string s1("hello world"); string::reverse_iterator rit = s1.rbegin(); while (rit != s1.rend()) {cout << *rit; ++rit; }

              打印的结果是刚好反过来的:
              C++STL之string类的使用
              文章图片

              注意:我们定义反向迭代器rit之后,在进行遍历时虽然是从后向前遍历,但是仍需要对rit进行++操作。

              (3)使用迭代的意义
              迭代的意义主要体现在和[]进行对比,有人可能认为既然可以用下标直接引用,为什么还要使用迭代器呢?
              这是因为对于string来说,下标和[]就足够好用,可以不使用迭代器,但是对于其他容器,比如list map/set等不支持下标加[]遍历,比如对于链表来说,由于物理内存不连续所以不能使用下标来进行遍历。
              除了普通迭代器之外,还有const修饰的迭代器等等。后面会详细说明的。

              (4)补充:语法糖实现遍历
              除了使用迭代器遍历之外,我们还可以使用语法糖来进行遍历操作:
              string s1("hello world"); for (auto& e : s1) {cout << e << " "; }

              范围for会把s1中的每一个字符取出来赋值给e(使用引用则为它本身),自动往后迭代,自动判断结束。
              C++STL之string类的使用
              文章图片


              8.string类对象的增删操作 push back:在字符串后尾插字符c
              append:在字符串后追加一个字符串
              operator+=:在字符串后追加字符串str
              c str:返回C格式字符串
              find+nops:从字符串pos位置开始往后找字符c,返回该字符再字符串中的位置。
              rfind:从字符串中pos位置开始往前找字符c,返回该字符再字符串中的位置。
              substr:在str中从pos位置开始,截取n个字符,然后将其返回。

              (1)增删
              string s1("hello world"); s1.push_back('a'); //在末尾插入字符a cout << s1 << endl; s1.append("bcd"); //在末尾插入字符串bcd cout << s1 << endl; s1 += 'e'; //在末尾插入字符e cout << s1 << endl; s1 += "hello linux"; //在末尾插入字符串hello linux cout << s1 << endl;

              C++STL之string类的使用
              文章图片

              注意:推荐直接使用操作符重载进行增删操作。

              (2)查与匹配
              下面是一段字符串截取的代码,截取后缀.txt:
              string file("test.txt"); size_t pos = file.find('.'); //返回第一次匹配'.'的位置 if (pos != string::npos) {string suffix = file.substr(pos, file.size() - pos); //将.之后的内容赋值给suffixcout << suffix << endl; }

              find会返回第一次出现匹配的位置,如果匹配失败会返回nops(无符号-1,表示一个极大的数)。
              substr是字符串截取函数,意思是截取pos位置与file.size()-pos位置的字符串。
              同上,我们也可以使用rfind进行倒着查找。
              这里再举一个截取网址的例子:
              我们都知道网址分为三部分:协议,域名与网络路径。下面使用find与substr来进行截取操作。
              string url("http://www.cplusplus.com/reference/string/string/find/"); size_t pos1 = url.find(':'); string protocol = url.substr(0, pos1 - 0); cout << protocol << endl; size_t pos2 = url.find('/', pos1 + 3); //从pos+3的位置开始找 string domain = url.substr(pos1 + 3, pos2 - (pos1 + 3)); cout << domain << endl; string uri = url.substr(pos2 + 1); //没指定结尾位置,默认为整个后面内容 cout << uri << endl;

              打印的结果为:
              C++STL之string类的使用
              文章图片


              9.string类中自定义插入与删除(效率低,不建议使用) 使用insert与erase两函数进行操作:
              string s("hello world"); s.insert(0, 1, 'x'); //在0位置插入一个1 s.insert(s.begin(), 'y'); //在头处插入一个y s.insert(0, "test"); //在头处插入test s.insert(4, "&&"); //在第四个位置插入特殊符号 s.erase(0, 1); //删除头处第一个字符 s.erase(s.size() - 1, 1); //尾删一个字符 cout << s << endl;

              打印的结果为:
              C++STL之string类的使用
              文章图片

              在使用erase时,如果不给值的话,会继续删完。
              尽量少使用头部和中间的删除,因为要挪动数据,效率较低。

              10.string类字符串的比较 和C语言中strcmp一样,string类也有对字符串的比较,不过是通过运算符重载。
              string s1("hello world"); string s2("string"); cout << (s1 < s2) << endl; cout << ("hhh" > s2) << endl;

              注意我们可以使用两种方式来说进行字符串比较,一种是s1 与strcmp原理一样,会从两个字符串起始位置开始比较,如果为真则返回1,如果为假返回0。
              C++STL之string类的使用
              文章图片


              11.string类字符串的转换 我们使用stoi(string to int)来将字符串转为整型,使用to_string来将其他类型转换为字符串。
              int val = stoi("1234"); string str = to_string(3.14);

              我们可以通过调试来观察转换是否成功:
              C++STL之string类的使用
              文章图片

              可见,转换很成功。

              12.总结 string类是表示字符串的字符串类,在使用string类时必须包含头文件,并开放std空间,在OJ中有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都会使用string类,很少有人去使用C库中的字符串操作函数。
              本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

                推荐阅读