【C++进阶】深入STL之string:掌握高效字符串处理的关键

简介: 【C++进阶】深入STL之string:掌握高效字符串处理的关键

前言:STL(Standard Template Library,标准模板库)是C++标准库的重要组成部分,它提供了一系列通用的数据结构和算法。在STL中,string类是一个非常重要的容器,用于处理字符串数据。本文将详细介绍STL中的string类,包括其基本概念、常用操作以及使用示例

STL的六大组件

📒1. STL基本介绍

🎈STL的版本

  • 原始版本
    Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本–所有STL实现版本的始祖。
  • P. J. 版本
    由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。
  • RW版本
    由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。
  • SGI版本
    由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本

🎩STL的缺陷

  • STL库的更新太慢了。这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出来已经相隔了13年,STL才进一步更新。
  • STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
  • STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
  • STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语法本身导致的

📒2. string类的基本概念

string类是一个模板类,专门用于处理字符串数据。 在C++中,字符串是由一系列字符组成的序列,而string类则提供了对这些字符序列进行高效操作的功能。与传统的C语言风格字符串(以\0结尾的字符数组)相比,string类更加安全和易用,因为它会自动管理内存,并提供了丰富的成员函数来操作字符串


string类成员函数:

class string
{
private:
  char* ——str;
  int _capacity;
  int _size;
};


📒3. string类的常用操作

🌈string类对象的常见构造

函数名称 功能说明
string() 构造空的string类对象,即空字符串
string(const char* s) 用const对象来构造string类对象
string(size_t n, char c) string类对象中包含n个字符c
string(s.begin(), s.end()) 用迭代区间构造
string(const string&s) 拷贝构造函数
int main()
{
  string s1(); // 空字符串
  string s2("hello world"); // const对象构造string类对象
  string s3(10, 'x'); // n个字符c构造
  string s4(s2.begin(), s2.end()); // 用迭代区间构造
  string s5 = s2; // 拷贝构造
  return 0;
}

注意:在这里迭代器类似于指针!


🌞string类对象的容量操作

函数名称 功能说明
size 返回字符串有效字符长度
length 返回字符串有效字符长度
capacity 返回空间总大小
empty 检测字符串释放为空串,是返回true,否则返回false
clear 清空有效字符
reserve 为字符串预留空间
resize 将有效字符的个数该成n个,多出的空间用字符c填充
int main()
{
  string s("hello world");
  // 返回字符串有效字符长度
  cout << s.size() << endl;
  cout << s.length() << endl;
  // 返回空间总大小
  cout << s.capacity() << endl;
  // 检测字符串释放为空串,是返回true,否则返回false
  cout << s.empty() << endl;
  // 清空有效字符
  s.clear();
  cout << "clear after: " << s << endl;
  // 为字符串预留空间
  s.reserve(100); // 一般会多预留空间
  cout << "reserve(100)after: " << s.size() << endl;
  cout << "reserve(100)after: " << s.capacity() << endl;
  
  cout << endl;
  // 将有效字符的个数该成n个,多出的空间用字符c填充
  s.resize(100);
  cout << "resize(100)after: " << s.size() << endl;
  cout << "resize(100)after: " << s.capacity() << endl;
  return 0;
}

注意:

  • size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
  • clear()只是将string中有效字符清空,不改变释放空间
  • reserve()只会变大,如果是将元素个数减少,底层空间总大小不变
  • resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变



🌙string类对象的访问及遍历操作

函数名称 功能说明
operator[ ] 返回pos位置的字符,const string类对象调用
begin+ end begin 获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin + rend begin 获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭器
范围for C++11支持更简洁的范围for的新遍历方式
int main()
{
  string s("hello world");
  for (int i = 0; i < s.size(); i++)
  {
    cout << s[i];
  }
  cout << endl;
  // 迭代器
  string::iterator it = s.begin();
  while (it != s.end())
  {
    cout << *it;
    it++;
  }
  cout << endl;
  // 范围for
  for (auto ch : s)
  {
    cout << ch;
  }
  cout << endl;
  return 0;
}

关于迭代器

迭代器的用法像指针一样能够+–也可以解引用拿到指向的内容


⭐string类对象的修改操作

函数名称 功能说明
push_back 在字符串后尾插字符c
append 在字符串后追加一个字符串
operator+= 在字符串后追加字符串str
c_str 返回C格式字符串
find + npos 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr 在str中从pos位置开始,截取n个字符,然后将其返回

注意:npos是无符号的整形,值为-1,npos是int的最大值


int main()
{
  string s1("h");
  // 插入字符
  s1.push_back('e');
  //插入字符串
  s1.append("llo ");
  s1 += "world";
  // 将s1变成 hello world
  //c_str函数返回字符串从\0结尾的字符串,但是c++中的字符串不一定
  s1 += '\0';
  s1 += "aaa";
  cout << s1 << endl; // hello worldaaa
  cout << s1.c_str() << endl; // hello world

  // find  从pos位置开始查找字符并返回其位置
  // rfind  从pos位置开始往前查找字符并返回其位置
  int ret = s1.find('l',3);
  cout << s1[++ret] << endl; // o

  //substr  从ret位置开始截取pos个字符,如果pos不传参数将会截取到最后
  string s2 = s1.substr(0);
  cout << s2 << endl; // hello worldaaa
  return 0;
}

这里要注意的是:

  • c_str,C格式字符串是以’\0’结尾的但是C++里面不一定
  • substr,当我们没有结束位置时,它会遍历完整个字符串
  • 关于修改操作其实还有inserterase,但是这两个涉及挪动数据,效率不高,能不用就不用
string s1("hello world!!!");
// 头插
s1.insert(0, 1, 'x');
// 删除
s1.erase(0,5);

我们来查阅一下这三个函数

insert可以在pos位置插入一个字符,一个字符串或者一个string类甚至还可以指定插入字符串的长度,insert接口有很多

erase可以删除从pos位置往后len个字符,如果pos不传参数,则从0位置删除npos个



📒4. 总结拓展

🔥拓展:getline

getline是用于从输入流中读取一行字符串并保存到指定的字符串变量中的函数,直到遇到换行符或达到指定的最大字符数

代码演示:

int main()
{
    string s;
    getline(cin, s);
    cout << s << endl;
    cout << endl;
    cin >> s;
    cout << s << endl;
    return 0;
}

💧总结

在深入学习和掌握了STL中string类的运用后,我们可以深刻感受到C++在处理字符串时的灵活性和高效性。通过合理利用string提供的各种成员函数和特性,实现更加高效且易于维护的代码。对于学习后面的STL容器也有很大帮助!

目录
相关文章
|
2天前
|
存储 算法 C++
C++一分钟之-标准模板库(STL)简介
【6月更文挑战第21天】C++ STL是高效通用的算法和数据结构集,简化编程任务。核心包括容器(如vector、list)、迭代器、算法(如sort、find)和适配器。常见问题涉及内存泄漏、迭代器失效、效率和算法误用。通过示例展示了如何排序、遍历和查找元素。掌握STL能提升效率,学习过程需注意常见陷阱。
20 4
|
6天前
|
算法 前端开发 Linux
【常用技巧】C++ STL容器操作:6种常用场景算法
STL在Linux C++中使用的非常普遍,掌握并合适的使用各种容器至关重要!
33 10
|
4天前
|
存储 编译器 C++
|
3天前
|
C语言 C++
C++对C的改进和拓展\string类型
C++对C的改进和拓展\string类型
5 1
|
8天前
|
存储 算法 程序员
【C++进阶】深入STL之 栈与队列:数据结构探索之旅
【C++进阶】深入STL之 栈与队列:数据结构探索之旅
16 4
|
8天前
|
算法 安全 编译器
【C++进阶】模板进阶与仿函数:C++编程中的泛型与函数式编程思想
【C++进阶】模板进阶与仿函数:C++编程中的泛型与函数式编程思想
22 1
|
8天前
|
存储 缓存 编译器
【C++进阶】深入STL之list:模拟实现深入理解List与迭代器
【C++进阶】深入STL之list:模拟实现深入理解List与迭代器
10 0
|
8天前
|
C++ 容器
【C++进阶】深入STL之list:高效双向链表的使用技巧
【C++进阶】深入STL之list:高效双向链表的使用技巧
13 0
|
8天前
|
编译器 C++ 容器
【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题
【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题
14 0
|
3天前
|
C++
C++一分钟之-类与对象初步
【6月更文挑战第20天】C++的类是对象的蓝图,封装数据和操作。对象是类的实例。关注访问权限、构造析构函数的使用,以及内存管理(深拷贝VS浅拷贝)。示例展示了如何创建和使用`Point`类对象。通过实践和理解原理,掌握面向对象编程基础。
30 2
C++一分钟之-类与对象初步