【C++】string类常用函数接口

Love The Way You Lie 2024-03-30 10:30 138阅读 0赞

在使用库函数中的string类时,需要包含头文件#include 。
1.构造函数和拷贝构造

  1. string s1;
  2. string s2("hello world");
  3. string s3(s2);

下面通过VS调试的监视窗口看一下初始化之后的内容:
在这里插入图片描述
还有一种构造函数,是拷贝一个字符串的一部分:string (const string& str, size_t pos, size_t len = npos);

  1. string s4(s3, 0, 5);
  2. cout << s4 << endl;
  3. string s5(s3, 0);
  4. cout << s5 << endl;

第一个参数是被拷贝的对象,第二个是拷贝开始的位置(注意是从0开始,而不是从1开始);第三个参数是拷贝的字符个数,默认的是npos; npos是一个无符号的-1,补码为全1,是一个非常大的数,也就是说如果我们不传拷贝的长度的话,那么就是从拷贝位置开始,知道字符串结束。
在这里插入图片描述
最后还有一种是通过n个char进行构造:string (size_t n, char c);

  1. string s6(10, 'c');
  2. cout << s6 << endl;

下面介绍一种不同的构造写法:
string s7 = “hello world”;在构造函数中是没有这种的,但是这样写实际上进行了隐式类型的转化,”hello world”先构造了一个临时的string对象,临时string对象再拷贝给s7;编译器这时会进行优化,优化为直接构造。

2.operator>>和operator<<
string类中是重载了流插入和流提取运算符的,所以可以直接来使用;

  1. cin >> s1;
  2. cout << s1;

3.operator=
string (1)
string& operator= (const string& str);
c-string (2)
string& operator= (const char* s);
character (3)
string& operator= (char c);
string类型的赋值支持三种形式:

  1. string s1;
  2. string s2("hello world");
  3. s1 = s2;
  4. s1 = "xxxx";
  5. s1 = 'x';

4.operator[ ]
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
string对象是可以像数组一样进行访问的:

  1. void test_string3()
  2. {
  3. string s1("hello world");
  4. for (size_t i = 0; i < s1.size(); i++)
  5. {
  6. cout << s1[i];
  7. }
  8. cout << endl;
  9. }

注意string中的size函数是返回string对象的字符个数,返回的类型是size_t。可以借助size函数直接对string对象进行遍历;由于operator[ ]返回的是一个char的引用,所以可以对string对象进行修改,而且引用返回还有一个作用就是减少了拷贝。
在这里插入图片描述
const对象会调用 const char& operator[] (size_t pos) const;是不能修改的,只能进行访问。
最后,提到operator[ ]就不得不说另一个方法,at功能和operator[ ]是一样的,但是只能作为函数调用;并且operator[ ]越界会直接assert断言终止程序,at越界会抛异常。
5.Iterator
迭代器: 迭代器 有时又称 光标 是程序设计的 软件设计模式 ,可在容器对象上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节, 各种语言实现迭代器的方式皆不尽同。

  1. void test_string4()
  2. {
  3. string s("iterator");
  4. string::iterator it = s.begin();
  5. while (it != s.end())
  6. {
  7. cout << *it << " ";
  8. it++;
  9. }
  10. cout << endl;
  11. }

iterator是一个像指针一样的类型,有可能就是指针,有可能不是指针,但是用法上像指针。
s.begin()返回的是第一个字符的位置,s.end()返回的是最后一个字符的下一个位置,所以可以通过s.begin()、s.end()对string对象进行遍历。
还有一个点需要注意:while循环的 !=不要写成 < ;因为 <需要物理地址空间连续,在string和vector中可以使用,但是迭代器是所有容器通用的遍历方式,比如list物理空间一定是连续的,那么此时就不能用 < ,只能用 !=。
既然提到了迭代器,就需要介绍一下另一种简单的遍历方式,范围for:这种遍历方式的底层就是迭代器,但是写起来很简单,下面以遍历我们在test_string4中的string对象s为例。

  1. for (auto ch : s)
  2. {
  3. cout << ch << " ";
  4. }
  5. cout << endl;

范围for会自动迭代,自动判断结束;会依次取s的每个字符,赋值给ch。
有了正向的迭代器,也有反向的迭代器,反向迭代器会反向的取数据:
在这里插入图片描述

  1. void test_string5()
  2. {
  3. string s("reverse_iterator");
  4. string::reverse_iterator rit = s.rbegin();
  5. while (rit != s.rend())
  6. {
  7. cout << *rit;
  8. rit++;
  9. }
  10. cout << endl;
  11. }

在使用上正向和反向迭代器其实是一样的,需要注意的是无论是正向迭代器还是反向迭代器都需要标明类域,因为迭代器就是在类域当中的。
一般的迭代器会有两种形式:iterator begin(); const_iterator begin() const; 这在反向迭代器中其实也是有的,在C++标准库中既有一般的迭代器,也有const迭代器,const迭代器就是适合const对象使用的;对const迭代器指向的内容进行修改是会出现错误的。
6.push_back append operator+=
void push_back (char c); push_back只能一个字符一个字符的尾插,空间不够会自动扩容。
string& append (const char* s); append可以尾插一个字符串。

  1. void test_string6()
  2. {
  3. string s("hello");
  4. s.push_back('-');
  5. s.push_back('-');
  6. s.append("world");
  7. cout << s << endl;
  8. }

相比于上面两个接口,operator+=用起来会更好用,string& operator+= (const char* s);
string& operator+= (char c);可以直接+=一个字符或者一个字符串,用起来比较简单。

  1. void test_string6()
  2. {
  3. string s("hello");
  4. s += ' ';
  5. s += "world";
  6. cout << s << endl;
  7. }

operator+=的底层就是调用push_back和append。
append还有一种追加方式是使用迭代器区间:template string& append (InputIterator first, InputIterator last);

  1. string s1("我来啦");
  2. s.append(s1.begin(), s1.end());
  3. cout << s << endl;

在追加的时候不一定只是追加一个string对象,也可以只追加一部分,这时候需要对迭代器区间进行修改。
7.insert erase
insert和erase在string中并不常用,因为效率很低,但是不排除一些特殊场景需要用到:

  1. string s("wo lai le");

把所有的空格替换成20%:

  1. void test_string7()
  2. {
  3. string s("wo lai le");
  4. //string& insert (size_t pos, const char* s);
  5. for (size_t i = 0; i < s.size(); i++)
  6. {
  7. if (s[i] == ' ')
  8. {
  9. s.insert(i, "20%");
  10. i += 3;
  11. }
  12. }
  13. //string& erase (size_t pos = 0, size_t len = npos);
  14. for (size_t i = 0; i < s.size(); i++)
  15. {
  16. if (s[i] == ' ')
  17. {
  18. s.erase(i, 1);
  19. }
  20. }
  21. cout << s << endl;
  22. }

发表评论

表情:
评论列表 (有 0 条评论,138人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java函数接口

    Java 8 中引入的常用函数式接口,也就是 java.util.function 包中的接口。这些接口提供了一种简洁的方式来定义函数,常用于 Lambda 表达式和方法引用。

    相关 Java函数接口

    目录 一、概述 1、概念 备注: 2、格式 3、@FunctionalInterface注解 二、函数式接口的使用 1、通过将接口作为方法的参数使用 函数式接口