一、引入动机
未使用STL前实现字符数组的方法:
1. 字符数组(C风格字符串)。缺陷:字符串长度是固定的,这是因为静态数组的长度有限而不能调整。
char sayHello = {'H', 'e', 'l', 'l', 'o', '!'};
2. 动态分配字符数组。缺陷:如果要在运行阶段动态改变数组长度,必须首先释放已分配的内存,再重新分配内存空间。
int arrayLen = 10;
char* dynamicStr = new char[arrayLen];
3. 将char*用作类成员属性。缺陷:实现较复杂,例如,将一个对象赋给另一个对象时,必须编写正确的复制构造函数和赋值运算符,否则会导致两个对象指向内存内相同的缓冲区,使销毁对象时出错。
STL的字符串类(包括std::string(普通字符串)和std::wstring(宽字符串))解决了这些问题。它减少了一些不必要的工作(如创建、操作等),且在内部管理内存分配细节,从而提高了程序的稳定性。
二、STL string的实例化和复制
std::string的实例化和复制方式如下。
重载形式 | 示例 |
---|---|
C风格的字符串 | const char* constCStyleString = "Hello string!"; std::string strFromConst(constCStyleString); |
直接用字符串做输入 | std::string str2("Hello string!"); |
使用另一个string对象 | std::string str2Copy(str2); |
接收输入字符串的前n个字符 | std::string partialCopy(strFromConst, 5); |
使其包含指定数量的特定字符 | std::string strRepeatChars(10, 'a); |
二、STL string的访问
定义了字符串stlString如下:
std::string stlString = "Hello string!";
以上述的stlString为例,std::string的访问方式有以下几种:
方式 | 示例 |
使用索引 | stlString[3] |
使用迭代器 | *charLocator,其中charLocator为stl::string::iterator类型的迭代器 |
转换为C风格字符串:使用.c_str()函数 | stlString.c_str() |
三、STL string的基础操作
操作 | 方式 | 描述 | 示例 |
---|---|---|---|
字符串长度 | str.length(); str.size() | 获取字符串长度 | int strLength = sampleStr.length() |
字符串拼接 | 运算符+或+= | sampleStr1 += sampleStr2 | |
str1.append(std::string str2) | sampleStr1.append(sampleStr2) | ||
字符串查找 | str1.find(char c, int pos); str1.find(std::string str2, int pos) | 如果没找到,返回std::string::npos(用它判断找到与否); 否则返回(pos开始首个)字符/子串在母串中的偏移量 | size_t charPos = sampleStr.find("day", 0) 从字符串sampleStr的位置0开始查找子串"day" |
字符串截短 | str.erase(int pos, int numChars) | 删除指定书目的字符参数说明: pos:给定位置, numChars:字符数 | sampleStr.erase(13, 28) |
str.erase(std::string::iterator iter1) | 删除迭代器指定的字符 | sampleStr.erase(iCharS) | |
str.erase(std::string::iterator iter1, std::string::iterator iter2) | 删除两个迭代器指定范围内的字符 | sampleStr.erase(sampleStr.begin(), sampleStr.end()) | |
str.clear() | 清空字符串并重置该string对象 | sampleStr.clear() | |
字符串反转 | 泛型算法std::reverse(iterator iter1, iterator iter2) | 反转两个迭代器指定范围内的字符; 注意迭代器不能超过边界; 包含头文件algorithm | reverse(sampleStr.begin(), sampleStr.end()); |
大小写转换 | 算法std::transform(...) | transform算法本身对集合中每个元素执行一个用户指定的函数,这里可用来实现字符串的大小写转换; 包含头文件algorithm | transform(inStr.begin(), inStr.end(), inStr.begin(), ::toupper); |
四、STL string的其他知识
1. std::string类是std::basic_string<T>模板类的具体化
(1)当使用_Elem=char具体化basic_string则有std::string;
(2)当使用_Elem=wchar具体化basic_string则有第一节提到的std::wstring。
(3)如果编程中需要更好地支持非拉丁文(如中文),使用std::wstring。
2. operator ""s
C++14起,STL支持operator ""s。""s是一个操作符函数,可将引号标识的字符串转换为std::basic_string<T>。
string str1("Conventional string \0 initialization");
cout << "Str1: " << str1 << " Length: " << str1.length() << endl;
// 输出:Str1: Conventional string Length: 20
// 注意字符串中间的终止空字符\0
string str2("Initialization \0 using literals"s);
cout << "Str2: " << str2 << " Length: " << str2.length() << endl;
// 输出:Str2: Initialization using literals Length: 31
// operator ""s让str2 能够包含并操作含有终止空字符\0的字符缓冲区
与""s类似,还有前置的字面量(什么是字面量?答:双引号之间的一串字符,如"Hello"通过双引号定义了一个字符串字面量),例如u""(转char16_t),U""(转char32_t)、L""(转wchar_t),R""(表示可以忽略转义字符),可以得到对应的字符串。详见这里。
摘录于《21天学通C++》