STL: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)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

    总结:

    1. string是表示字符串的字符串类
    2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

本章节主要介绍string类的常用接口

string的构造

在这里插入图片描述

(1)空字符串构造函数(默认构造函数):构造一个空字符串,长度为零个字符。

(2)拷贝构造函数:构造str的副本。

(3)子串构造函数:复制从字符位置pos开始并跨越len个字符的str的部分(或者如果str太短或者len为string::npos,则复制到str的末尾)。

(4)用C字符串构造:复制由s指向的以空字符结尾的字符序列(C字符串)。

(5)用缓冲区数据构造:从由s指向的字符数组中复制前n个字符。

(6)填充构造函数:使用n个连续的字符c填充字符串。

(7)范围构造函数:以相同顺序复制范围[first,last)中的字符序列。

下面这两个用到了C++11的内容,以后会介绍。

(8)初始化器列表:以相同顺序复制il中的每个字符。

(9)移动构造函数:获取str的内容。 str将处于未指定但有效的状态。

Example:

// string constructor
#include <iostream>
#include <string>

int main ()
{
  std::string s0 ("Initial string");

  // constructors used in the same order as described above:
  std::string s1;
  std::string s2 (s0);
  std::string s3 (s0, 8, 3);
  std::string s4 ("A character sequence");
  std::string s5 ("Another character sequence", 12);
  std::string s6a (10, 'x');
  std::string s6b (10, 42);      // 42 is the ASCII code for '*'
  std::string s7 (s0.begin(), s0.begin()+7);

  std::cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;
  std::cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a;
  std::cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n';
  return 0;
}

Output:

s1: 
s2: Initial string
s3: str
s4: A character sequence
s5: Another char
s6a: xxxxxxxxxx
s6b: **********
s7: Initial

string的赋值重载

在这里插入图片描述

字符串赋值:为字符串分配一个新值,替换其当前内容。

其中(4)和(5)是C++11新增的。

Example:

// string assigning
#include <iostream>
#include <string>

int main ()
{
  std::string str1, str2, str3;
  str1 = "Test string: ";   // c-string
  str2 = 'x';               // single character
  str3 = str1 + str2;       // string

  std::cout << str3  << '\n';
  return 0;
}

Output:

Test string: x

string的容量

size(length)

在这里插入图片描述

字符串的返回长度:返回字符串的长度(以字节为单位)。

这两个函数的功能都是返回字符串的长度,参数类型和返回值类型也都一样,那么库里面为什么要提供两个一模一样的函数呢?

因为string类的出现早于STL,对于string类可以用strlen来表示有效数据的个数,但是对于STL中的其他容器,如listvectordequemapset等,就不宜用strlen表示有效数据的个数,而用sizestring为了和STL中的其他容器保持接口的一致性,就增加了size接口。其实作用是一样的,今后使用时两者都可。

max_size

在这里插入图片描述

返回字符串的最大大小:返回字符串可以达到的最大长度。

resize

在这里插入图片描述

调整字符串大小:将字符串大小调整为 n 个字符的长度。

如果 n 小于当前字符串长度,则当前值将缩短为其第一个 n 个字符,从而删除第 n个字符之外的字符。

如果 n 大于当前字符串长度,则通过在末尾插入所需数量的字符来扩展当前内容,以达到 n 的大小。如果指定了 c,则新元素将初始化为 c 的副本,否则,它们是值初始化的字符(空字符)。

Example:

// resizing string
#include <iostream>
#include <string>

int main ()
{
  std::string str ("I like to code in C");
  std::cout << str << '\n';

  unsigned sz = str.size();

  str.resize (sz+2,'+');
  std::cout << str << '\n';

  str.resize (14);
  std::cout << str << '\n';
  return 0;
}

Output:

I like to code in C
I like to code in C++
I like to code

reserve

在这里插入图片描述

请求更改容量:请求将字符串容量调整为计划的大小更改,长度最多为 n 个字符。

如果 n 大于当前字符串容量,则该函数会导致容器将其容量增加到 n 个字符(或更大)。

在所有其他情况下,它被视为收缩字符串容量的非约束性请求:容器实现可以自由优化,并使字符串的容量大于 n

此函数对字符串长度没有影响,并且无法更改其内容。

capacity

在这里插入图片描述

已分配存储的返回大小:返回当前为字符串分配的存储空间的大小,以字节表示。

此容量不一定等于字符串长度。它可以等于或更大,额外的空间允许对象在向字符串添加新字符时优化其操作。

请注意,此容量不假定字符串的长度有限制。当此容量耗尽并需要更多容量时,对象会自动扩展它(重新分配其存储空间)。字符串长度的理论限制由成员max_size给出。

字符串的容量可以在修改对象时随时更改,即使此修改意味着大小减小或容量尚未耗尽(这与向量容器中对容量的保证形成鲜明对比)。

可以通过调用成员 Reserve 来显式更改字符串的容量。

clear

在这里插入图片描述

清除字符串:清除字符串的内容,该字符串将变为空字符串长度0 个字符)。但是不会改变底层空间的大小,即capacity不变。

Example:

// string::clear
#include <iostream>
#include <string>

int main ()
{
  char c;
  std::string str;
  std::cout << "Please type some lines of text. Enter a dot (.) to finish:\n";
  do {
    c = std::cin.get();
    str += c;
    if (c=='\n')
    {
       std::cout << str;
       str.clear();
    }
  } while (c!='.');
  return 0;
}

该程序重复用户引入的每一行,直到某一行包含一个点 ('.')。每个换行符 ('\n') 都会触发行的重复和当前字符串内容的清除。

empty

在这里插入图片描述

测试字符串是否为空:返回字符串是否为空(即其长度是否为 0)。

shink_to_fit

在这里插入图片描述

收缩以适合:请求字符串减小其容量以适合其大小

这是C++11中新增的接口。

该请求不具有约束力,容器实现可以自由优化,并使字符串的容量大于其大小

此函数对字符串长度没有影响,并且无法更改其内容。

Example:

// string::shrink_to_fit
#include <iostream>
#include <string>

int main ()
{
  std::string str (100,'x');
  std::cout << "1. capacity of str: " << str.capacity() << '\n';

  str.resize(10);
  std::cout << "2. capacity of str: " << str.capacity() << '\n';

  str.shrink_to_fit();
  std::cout << "3. capacity of str: " << str.capacity() << '\n';

  return 0;
}

Possible output:(因为这个函数并没有要求编译器的行为,所以在不同的编译器下运行的结果可能会有不同)

1. capacity of str: 100
2. capacity of str: 100
3. capacity of str: 10

而在VS2022下,输出的结果为:

在这里插入图片描述

string的元素访问

operator[] 和 at

在这里插入图片描述

获取字符串的字符:返回对字符串中位置 pos 处的字符的引用。

在这里插入图片描述

获取字符串中的字符:返回对字符串中位置 pos 处的字符的引用。

该函数会自动检查 pos 是否是字符串中字符的有效位置(即 pos 是否小于字符串长度),如果不是,则抛出out_of_range异常。

这两个函数的参数和返回值完全相同,用法也完全相同,区别仅在于对越界的处理,operator[]调用时如果出现越界,则会通过assert终止程序,而at则会抛异常out_of_range

Example:

int main()
{
	string s("12345");
	try {
		s.at(10) = '6';
	}
	catch (...)
	{
		cout << "越界访问" << endl;
	}
	return 0;
}

Output:

越界访问

front 和 back

在这里插入图片描述

访问第一个字符:返回对字符串的第一个字符的引用。

与成员 string::begin 不同,它返回对同一字符的迭代器,此函数返回直接引用。

不得在空字符串上调用此函数。

在这里插入图片描述

访问最后一个字符:返回对字符串最后一个字符的引用。

不得在空字符串上调用此函数。

string的迭代器 和 范围for

在这里插入图片描述

因为string有迭代器,所以string也可以使用范围for遍历。

Example:

#include <iostream>
#include <string>

int main ()
{
    std::string str ("Test string");
    for ( std::string::iterator it=str.begin(); it!=str.end(); ++it)
        std::cout << *it;
    std::cout << '\n';

	for(auto& e : str)
    {
        std::cout << e;
    }
    std::cout << '\n';

    return 0;
}

Output:

Test string
Test string

string的修改

operator+=

在这里插入图片描述

追加到字符串:通过在当前值的末尾附加其他字符来扩展字符串

Example:

#include <iostream>
#include <string>

int main ()
{
  std::string name ("John");
  std::string family ("Smith");
  name += " K. ";         // c-string
  name += family;         // string
  name += '\n';           // character

  std::cout << name;
  return 0;
}

Output:

John K. Smith

append

在这里插入图片描述

追加到字符串:通过在当前值的末尾附加其他字符来扩展字符串

Example:

#include <iostream>
#include <string>

int main ()
{
    std::string str;
    std::string str2="Writing ";
    std::string str3="print 10 and then 5 more";

    // used in the same order as described above:
    str.append(str2);                       // "Writing "
    str.append(str3,6,3);                   // "10 "
    str.append("dots are cool",5);          // "dots "
    str.append("here: ");                   // "here: "
    str.append(10u,'.');                    // ".........."
    str.append(str3.begin()+8,str3.end());  // " and then 5 more"
    str.append<int>(5,0x2E);                // "....."

    std::cout << str << '\n';
    return 0;
}

Output:

Writing 10 dots here: .......... and then 5 more.....

push_back

在这里插入图片描述

将字符附加到字符串:将字符 c 追加到字符串的末尾,将其长度增加 1。

assign

在这里插入图片描述

将内容分配给字符串:为字符串分配一个新值,替换其当前内容。

作用和operator=相似

Example:

#include <iostream>
#include <string>

int main ()
{
    std::string str;
    std::string base="The quick brown fox jumps over a lazy dog.";

    // used in the same order as described above:

    str.assign(base);
    std::cout << str << '\n';

    str.assign(base,10,9);
    std::cout << str << '\n';         // "brown fox"

    str.assign("pangrams are cool",7);
    std::cout << str << '\n';         // "pangram"

    str.assign("c-string");
    std::cout << str << '\n';         // "c-string"

    str.assign(10,'*');
    std::cout << str << '\n';         // "**********"

    str.assign<int>(10,0x2D);
    std::cout << str << '\n';         // "----------"

    str.assign(base.begin()+16,base.end()-12);
    std::cout << str << '\n';         // "fox jumps over"

    return 0;
}

Output:

The quick brown fox jumps over a lazy dog.
brown fox
pangram
c-string
**********
----------
fox jumps over

insert

在这里插入图片描述

插入到字符串中:在字符串中插入其他字符,紧挨着 pos(或 p)指示的字符:

(1) 字符串:插入 str 的副本。

(2) 子字符串:插入 str 的子字符串的副本。子字符串是 str 中从字符位置 subpos 开始并跨越 sublen 字符的部分(或者直到 str 的末尾,如果任一 str 太短或 sublennpos)。

(3) C-串:插入由 s 指向的以 null 结尾的字符序列(C 字符串)形成的字符串的副本。

(4) 缓冲器:插入 s 指向的字符数组中的前 n 个字符的副本。

(5)填写:插入字符 cn 个连续副本。

(6) 单字:插入字符 c

(7) 范围:以相同的顺序在 [first,last) 范围内插入字符序列的副本。

(8) 初始值设定项列表:以相同的顺序插入 il 中每个字符的副本。

Example:

#include <iostream>
#include <string>

int main ()
{
  std::string str="to be question";
  std::string str2="the ";
  std::string str3="or not to be";
  std::string::iterator it;

  // used in the same order as described above:
  str.insert(6,str2);                 // to be (the )question
  str.insert(6,str3,3,4);             // to be (not )the question
  str.insert(10,"that is cool",8);    // to be not (that is )the question
  str.insert(10,"to be ");            // to be not (to be )that is the question
  str.insert(15,1,':');               // to be not to be(:) that is the question
  it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question
  str.insert (str.end(),3,'.');       // to be, not to be: that is the question(...)
  str.insert (it+2,str3.begin(),str3.begin()+3); // (or )

  std::cout << str << '\n';
  return 0;
}

Output:

to be, or not to be: that is the question...

erase

在这里插入图片描述

清除字符串中的字符:清除部分字符串,减少其长度

(1)顺序:擦除字符串值中从字符位置 pos 开始并跨越 len 字符的部分(如果内容太短或 lenstring::npos,则擦除字符串值的末尾。 请注意,默认参数会擦除字符串中的所有字符(和成员函数 clear一样)。

(2)字符:擦除 p 指向的字符。

(3) 范围:擦除 [first,last) 范围内的字符序列。

Example:

#include <iostream>
#include <string>

int main ()
{
  std::string str ("This is an example sentence.");
  std::cout << str << '\n';
                                           // "This is an example sentence."
  str.erase (10,8);                        //            ^^^^^^^^
  std::cout << str << '\n';
                                           // "This is an sentence."
  str.erase (str.begin()+9);               //           ^
  std::cout << str << '\n';
                                           // "This is a sentence."
  str.erase (str.begin()+5, str.end()-9);  //       ^^^^^
  std::cout << str << '\n';
                                           // "This sentence."
  return 0;
}

Output:

This is an example sentence.
This is an sentence.
This is a sentence.
This sentence.

replace

在这里插入图片描述

替换字符串的一部分

用新内容替换字符串中从字符 pos 开始并跨越 len 字符的部分(或字符串在 [i1,i2) 之间的部分):

(1)字符串:副本 str.

(2)子字符串:复制从字符位置 subpos 开始并跨越 sublen 字符的 str 部分(如果任一 str 太短或 sublenstring::npos,则复制到 str 的末尾)。

(3)C-串:复制以 s 为结尾的以 null 结尾的字符序列(C 字符串)。

(4)缓冲器:从 s 指向的字符数组中复制前 n 个字符。

(5)填写:将字符串部分替换为字符 cn 个连续副本。

(6)范围:以相同的顺序复制 [first,last) 范围内的字符序列。

(7)初始值设定项列表:以相同的顺序复制 il 中的每个字符。

swap

在这里插入图片描述

交换字符串值:通过 str 的内容交换容器的内容,str 是另一个字符串对象。长度可能不同。

请注意,存在一个同名的非成员函数 swap,它使用行为类似于此成员函数的优化重载该算法。

pop_back

在这里插入图片描述

删除最后一个字符:擦除字符串的最后一个字符,有效地将其长度减少 1。

string的输入输出

operator<<

在这里插入图片描述
将字符串插入到流中:将符合 str 值的字符序列插入到 os 中。

需要注意的是:string的输出并不以遇到\0而结束,而是以size()为准,这是与打印字符串的不同之处。

Example:

#include <iostream>       // std::cout
#include <string>         // std::string

int main()
{
    std::string str = "hello";
    str += '\0';
    str += " world";
    std::cout << str << '\n';
    
    return 0;
}

Output:

hello world

operator>>

在这里插入图片描述

从流中提取字符串:从输入流中提取字符串 is,将序列存储在 str 中,该序列将被覆盖(str 的先前值被替换)。

但是流提取操作符是遇到\0空格就停止的,那么如果想要在string中写入空格,可以使用getline

getline

在这里插入图片描述

将行从流获取到字符串:从 is 中提取字符并将它们存储到 str 中,直到找到分隔符 delim(或换行符 '\n',用于(2))

string的查找

在这里插入图片描述

在字符串中查找内容:在字符串中搜索其参数指定的序列的第一次出现。

指定 pos 时,搜索仅包括位置 pos 处或位置 pos 之后的字符,忽略任何可能出现的包含位置 pos 之前的字符。

请注意,与成员find_first_of不同,每当搜索多个字符时,仅其中一个字符匹配是不够的,整个序列必须匹配。

Example:

#include <iostream>       // std::cout
#include <string>         // std::string

int main ()
{
  std::string str ("There are two needles in this haystack with needles.");
  std::string str2 ("needle");

  // different member versions of find in the same order as above:
  std::size_t found = str.find(str2);
  if (found!=std::string::npos)
    std::cout << "first 'needle' found at: " << found << '\n';

  found=str.find("needles are small",found+1,6);
  if (found!=std::string::npos)
    std::cout << "second 'needle' found at: " << found << '\n';

  found=str.find("haystack");
  if (found!=std::string::npos)
    std::cout << "'haystack' also found at: " << found << '\n';

  found=str.find('.');
  if (found!=std::string::npos)
    std::cout << "Period found at: " << found << '\n';

  // let's replace the first needle:
  str.replace(str.find(str2),str2.length(),"preposition");
  std::cout << str << '\n';

  return 0;
}

Output:

first 'needle' found at: 14
second 'needle' found at: 44
'haystack' also found at: 30
Period found at: 51
There are two prepositions in this haystack with needles.

rfind

在这里插入图片描述

查找字符串中内容的最后出现项:在字符串中搜索其参数指定的序列的最后一次出现项。

find_first_of

在这里插入图片描述

在字符串中查找字符:在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。

该函数与find的区别是:find找到的序列必须和提供的序列完全相同,find_first_of则是找到序列中的任意一个即可。

Example:

#include <iostream>       // std::cout
#include <string>         // std::string
#include <cstddef>        // std::size_t

int main ()
{
  std::string str ("Please, replace the vowels in this sentence by asterisks.");
  std::size_t found = str.find_first_of("aeiou");
  while (found!=std::string::npos)
  {
    str[found]='*';
    found=str.find_first_of("aeiou",found+1);
  }

  std::cout << str << '\n';

  return 0;
}

Output:

Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.

find_last_of

在这里插入图片描述

从末尾查找字符串中的字符:在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。

find_first_not_of

在这里插入图片描述
查找字符串中缺少字符:在字符串中搜索与其参数中指定的任何字符不匹配的第一个字符。

find_last_not_of

在这里插入图片描述

从末尾查找字符串中不匹配的字符:在字符串中搜索与其参数中指定的任何字符不匹配的最后一个字符。

string的其他操作

substr

在这里插入图片描述

生成子字符串:返回一个新构造的对象,其值初始化为此对象的子字符串的副本。

Example:

#include <iostream>
#include <string>

int main ()
{
  std::string str="We think in generalities, but we live in details.";
                                           // (quoting Alfred N. Whitehead)

  std::string str2 = str.substr (3,5);     // "think"

  std::size_t pos = str.find("live");      // position of "live" in str

  std::string str3 = str.substr (pos);     // get from "live" to the end

  std::cout << str2 << ' ' << str3 << '\n';

  return 0;
}

Output:

think live in details.

c_str

在这里插入图片描述

获取 C 字符串等效项:返回指向数组的指针,该数组包含以 null 结尾的字符序列(即 C 字符串),表示字符串对象的当前值。

Example:

#include <iostream>
#include <cstring>
#include <string>

int main ()
{
  std::string str ("Please split this sentence into tokens");

  char * cstr = new char [str.length()+1];
  std::strcpy (cstr, str.c_str());

  // cstr now contains a c-string copy of str

  char * p = std::strtok (cstr," ");
  while (p!=0)
  {
    std::cout << p << '\n';
    p = std::strtok(NULL," ");
  }

  delete[] cstr;
  return 0;
}

Output:

Please
split
this
sentence
into
tokens
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值