【C++】String类

目录

本文将对string常用函数进行说明

string基础介绍

string类的常用接口说明

string() &&string(const char* s)

拷贝:string (const string& str, size_t pos, size_t len = npos)

拷贝前n个进行构造:string (const char* s, size_t n);​编辑

字符串初始化:string (size_t n, char c);​编辑

string类对象的容量操作:

size() && length() && capacity()

缩小其容量以适应其当前大小:shrink_to_fit()

开辟空间:

reserve()//只会改变capacity

开空间+初始化:resize()//size和capacity动可进行改变

string类对象的修改操作

尾插:

插入一个字符push_back()

插入字符串:append()

operator+=

任意位置插入/头插

​编辑

删除:erase​编辑

替换:replace /查找:find

find_first_of//正着找

find_last_of//倒着找

交换swap​编辑

返回C格式字符串:c_str

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

begin()&&end()//迭代器

正向遍历

rbegin() && rend()//反向遍历(反向迭代器)

​编辑

operator[ ]​编辑


本文将对string常用函数进行说明

string文档:cplusplus.com/reference/string/string/?kw=string

string基础介绍

string 是一个表示文本字符串的数据类型。它是一个标准库提供的类,需要包含 <string> 头文件以及using namespace std;才能使用。

使用 string 类可以方便地处理和操作文本字符串。与使用字符数组相比,string 类提供了更多的功能和灵活性,同时也避免了手动管理内存的复杂性。

  1. 字符串是表示字符序列的类

  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。

  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信

    息,请参阅basic_string)。

  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits

    和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。

  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个

    类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

string类的常用接口说明

string() &&string(const char* s)

 string s1;
 string s2("HelloWord");

遍历s2:

 for (size_t i = 0; i < s2.size(); i++)//s2.size():字符串的长度 
 {
     s2[i]++;
 }
 cout<<s2[i]<<" ";//遍历

     string s3="HappyEveryDay";

隐式转换:"HappyEveryDay" 是一个字符串字面值,它的类型是 const char[](或者可以隐式转换为 const char*),而 s3 的类型是 std::string。这就涉及到一个类型转换的过程,将 const char[] const char* 转换为 std::string 对象。//构造+拷贝构造->优化为->构造

拷贝:string (const string& str, size_t pos, size_t len = npos)

从pos位置拷贝到行后npos个字符

若npos超过字符串长度则拷贝到末尾截止

 string s3="HappyEveryDay";
 string s4(s3,5,3);
 string s5(s3,5,20);

npos:

npos并不是真正意义上的-1,而是无符号整型最大值,故不给值时直接打印到字符串末尾:

拷贝前n个进行构造:string (const char* s, size_t n);

字符串初始化:string (size_t n, char c);

string类对象的容量操作:

size() && length() && capacity()

 string s1("HelloWord");
 cout<<s1.size()<<endl;//9
 cout<<s1.length()<<endl;//9

二者差别不大,只是为了保持一致和使用方便就引入了size

capacity:空间大小

缩小其容量以适应其当前大小:shrink_to_fit()

 int main() 
 {
   std::string str = "Hello, world!";
   
   // 在一系列操作后,字符串对象可能有多余的容量
   std::cout << "Capacity before: " << str.capacity() << std::endl;
 ​
   // 使用 shrink_to_fit() 函数,要求字符串对象缩小容量
   str.shrink_to_fit();
 ​
   std::cout << "Capacity after: " << str.capacity() << std::endl;
 ​
   return 0;
 }

上述代码中,我们首先创建了一个 std::string 对象 str,并将其初始化为 "Hello, world!"。接下来,我们输出了字符串对象的初始容量。 然后,我们使用 shrink_to_fit() 函数,对字符串对象进行了缩小容量的请求。这个函数会使字符串对象的容量与其当前大小相匹配。 最后,我们再次输出了字符串对象的容量,以展示 shrink_to_fit() 函数的效果。

请注意,shrink_to_fit() 函数的调用并不保证一定会缩小容量。具体是否发生容量的缩小取决于实现。在某些情况下,字符串对象的容量可能会保持不变。

 

开辟空间:

reserve()//只会改变capacity

若知道要开辟多少空间,用reserve()进行开辟,提高效率,减少扩容

以如下代码为例(不同的编译器扩容方式会有差异)

 //观察扩容情况
 string s;
 size_t sz=s.capacity();
 cout<< "making s grow:\n";
 for (int i = 0; i < 100; ++i)
 {
     s.push_back('c');
     if (sz!=s.capacity())
     {
         sz=s.capacity();
         cout<<"capacity changed:"<<sz<<'\n';
     }
 }

此时的输出:

making s grow:

capacity changed:47

capacity changed:95

capacity changed:191

使用reserve():

//观察扩容情况
string s;

s.reserve(100);//提前开辟空间

size_t sz=s.capacity();
cout<< "making s grow:\n";
for (int i = 0; i < 100; ++i)
{
    s.push_back('c');
    if (sz!=s.capacity())
    {
        sz=s.capacity();
        cout<<"capacity changed:"<<sz<<'\n';
    }
}

输出:

making s grow:

开空间+初始化:resize()//size和capacity动可进行改变

//此时初始化的值为:‘0’

s2.resize(100,'x');//全部初始化为'x'

当然resize也可以进行删除数据:

 //比size小,删除数据,保留前5个
 s2.resize(5);

虽然进行了数据删除,但是空间大小并不进行缩小(capacity不变)

string类对象的修改操作

尾插:

插入一个字符push_back()

 string s1("Hello");
 s1.push_back(' ');
 s1.push_back('!');
 cout << s1 << endl;//Hello !

插入字符串:append()

operator+=

operator+=在底层意义就是进行了封装

任意位置插入/头插

 string s1("Word");
 s1.insert(0, "Hello");
 cout << s1 << endl;
 ​
 s1.insert(5, "1");
 cout << s1 << endl;
 ​
 s1.insert(s1.begin() + 5, ' ');
 cout << s1 << endl;

输出结果:

HelloWord

Hello1Word

Hello 1Word

当然,不推荐使用,插入数据,后面数据需要后移,效率低

删除:erase

 string& erase (size_t pos = 0, size_t len = npos);

从pos位置删除npos个字符

 string s1("Hello Word");
 s1.erase(5,1);
 cout << s1 << endl; //HelloWord

不推荐使用,删除数据,后面数据需要前移,效率低

替换:replace /查找:find

 string s1("Hello Word i love you");
 ​
 s1.replace(pos, 1, "%20");//从pos位置后的一个字符替换为%20
 ​
 size_t pos = s1.find(' '); // 找到第一个并范围下标,若没找到返回-1
 ​
 pos = s1.find(' ',pos+3);//从pos+3位置向后找' '
 
string s1("Hello Word i love you");
 ​
 size_t num = 0;
 for (size_t i = 0; i < s1.size(); ++i)
 {
     if (s1[i] == ' ')
         ++num;
 }
 //提前开空间,减少开辟次数,提高效率,避免replace
 s1.reserve(s1.size()+2*num);
 ​
 size_t pos = s1.find(' '); // 找到第一个并范围下标,若没找到返回-1
 while (pos != string::npos)
 {
     s1.replace(pos, 1, "%20");   // 从pos位置后的一个字符替换为%20
     pos = s1.find(' ', pos + 3); // 从pos+3位置向后找' ',
 }
 cout << s1 << endl;
 //以空间换时间
 string s2("Hello Word i love you");
 string newStr;
 /*
 size_t num2 = 0;
 for (size_t i = 0; i < s1.size(); ++i)
 {
     if (s1[i] == ' ')
         ++num2;
 }
 s1.reserve(s1.size() + 2 * num2);
 */
 for (size_t i = 0; i < s2.size(); ++i)
 {
     if (s2[i] != ' ')
         newStr += s2[i];
     else
         newStr += "%20";
 }
 s2=newStr;
 cout << s2 << endl;

find 还可进行寻找文件后缀等等作用

 string file("string.cpp");
 size_t pos = file.find('.');
 ​
 if (pos != string::npos)
 {
     string suffix = file.substr(pos, file.size() - pos);//substr:提取从位置 poa 开始的前 file.size()-pos 个字符
     cout<<suffix<<endl;//.cpp
 }

find反向查找

 string file("string.cpp.txt.exe");
 size_t pos = file.rfind('.');
 ​
 if (pos != string::npos)
 {
     string suffix = file.substr(pos, file.size() - pos);//substr:提取从位置 poa 开始的前 file.size()-pos 个字符
     cout<<suffix<<endl;//.exe
 }

find_first_of//正着找

find_first_of() 函数返回一个 size_t 类型的值,表示找到的第一个匹配字符的位置。如果没有找到任何匹配的字符,则返回 std::string::npos

 #include <iostream>
 #include <string>
 ​
 int main() 
 {
   std::string str = "Hello, world!";
   std::string vowels = "aeiou";
 ​
   // 查找第一个元音字母的位置
   size_t pos = str.find_first_of(vowels);
   if (pos != std::string::npos) {
     std::cout << "The first vowel is at position " << pos << std::endl;
   } else {
     std::cout << "No vowels found." << std::endl;
   }
 ​
   return 0;
 }

在示例中,std::string 类型的字符串变量 str 存储了一个字符串,vowels 表示要查找的字符集合,即元音字母。函数 find_first_of() 被用于在 str 中查找第一个匹配元音字母的字符,并返回其位置。

find_last_of//倒着找

 #include <iostream>
 #include <string>
 ​
 int main() {
   std::string str = "Hello, world!";
   std::string vowels = "aeiou";
 ​
   // 查找最后一个元音字母的位置
   size_t pos = str.find_last_of(vowels);
   if (pos != std::string::npos) {
     std::cout << "The last vowel is at position " << pos << std::endl;
   } else {
     std::cout << "No vowels found." << std::endl;
   }
 ​
   return 0;
 }

std::string 类型的字符串变量 str 存储了一个字符串,vowels 表示要查找的字符集合,即元音字母。函数 find_last_of() 被用于在 str 中查找最后一个匹配元音字母的字符,并返回其位置。

交换swap

注意此处的swap与库中的swap不同

string::swap是将两个指针指向进行交换,而std::swap是进行深拷贝,string::swap更加高效

 // string::swap
 string s1("HelloWord");
 string s2("***********");
 cout << s1 << endl
      << s2 << endl;
 ​
 s1.swap(s2);
 cout << endl
      << s1 << endl
      << s2 << endl;
 ​
 // std::swap
 swap(s1, s2);
 cout << endl
      << s1 << endl
      << s2 << endl;
 

返回C格式字符串:c_str

 string s1("Hello Word");
 cout << (void *)s1.c_str() << endl;
 ​
 s1 += '\0';
 s1 += '\0';
 s1 += "xxxxxxx";
 ​
 cout << s1 << endl
      << s1.c_str() << endl;

c型字符串是以'\0'终止,遇到'\0'终止

而流插入/提取会忽视'\0',以s1.size();进行打印

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

begin()&&end()//迭代器

用迭代器去访问

正向遍历

 string s1("Hello Word");
 string::iterator it=s1.begin();//正向遍历
 while (it!=s1.end())
 {
     cout<<*it<<" ";
     ++it;
 }
 cout<<endl;
 //输出:H e l l o   W o r d 
 ​
 //const迭代器--只读不写
 string s3("Hello Word");
 string::const_iterator cit=s3.begin();// const_iterator
 while (cit!=s3.end())
 {
     cout<<*cit<<" ";
     ++cit;
 }
 cout<<endl;

 

另一种写法:

 for(auto ch: s1)
 {
  cout<<ch<<" ";
 }
 cout<<endl;

rbegin() && rend()//反向遍历(反向迭代器)

 //反向迭代
 string::reverse_iterator rit =s1.rbegin();//reverse_iterato:反向迭代器
 while (rit!=s1.rend())
 {
     cout<<*rit<<" ";
     ++rit;
 }
 cout<<endl; 
 ​
 //const  //const_reverse_iterator
 string::const_reverse_iterator crit =s1.rbegin();//auto crit=s.rbegin();
 while (crit!=s1.rend())
 {
     cout<<*crit<<" ";
     ++crit;
 }
 cout<<endl; 

输出:

operator[ ]

string也可以用下标的方式进行访问

 std::string str ("Test string");
 for (int i=0; i<str.length(); ++i)
 {
   std::cout << str[i];
 }

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值