概述与基本概念
std::string是C++标准库中的字符串类,定义在 <string>头文件中。
#include <iostream>
#include <string>
#include <cstring> // 用于C风格字符串比较
using namespace std;
构造函数与初始化
void testConstructors() {
cout << "=== 构造函数测试 ===" << endl;
// 1. 默认构造函数
string s1;
cout << "s1 (默认构造): \"" << s1 << "\" 长度: " << s1.length() << endl;
// 2. 用C风格字符串构造
string s2 = "Hello World";
cout << "s2 (C字符串): \"" << s2 << "\"" << endl;
// 3. 拷贝构造
string s3(s2);
cout << "s3 (拷贝构造): \"" << s3 << "\"" << endl;
// 4. 用n个字符构造
string s4(5, 'A'); // 5个'A'
cout << "s4 (重复字符): \"" << s4 << "\"" << endl;
// 5. 用子串构造
string s5(s2, 6, 5); // 从索引6开始,取5个字符
cout << "s5 (子串构造): \"" << s5 << "\"" << endl;
// 6. 移动构造 (C++11)
string s6(move(s2));
cout << "s6 (移动构造): \"" << s6 << "\"" << endl;
cout << "s2 (移动后): \"" << s2 << "\"" << endl;
// 7. 初始化列表构造 (C++11)
string s7 = {'H', 'e', 'l', 'l', 'o'};
cout << "s7 (初始化列表): \"" << s7 << "\"" << endl;
}
输出:
=== 构造函数测试 ===
s1 (默认构造): "" 长度: 0
s2 (C字符串): "Hello World"
s3 (拷贝构造): "Hello World"
s4 (重复字符): "AAAAA"
s5 (子串构造): "World"
s6 (移动构造): "Hello World"
s2 (移动后): ""
s7 (初始化列表): "Hello"
基本操作与访问
void testBasicOperations() {
cout << "\n=== 基本操作测试 ===" << endl;
string str = "Hello C++ World";
// 1. 大小和容量
cout << "字符串: \"" << str << "\"" << endl;
cout << "长度: " << str.length() << " 或 " << str.size() << endl;
cout << "容量: " << str.capacity() << endl;
cout << "是否为空: " << (str.empty() ? "是" : "否") << endl;
// 2. 访问元素
cout << "第一个字符: " << str.front() << endl; // C++11
cout << "最后一个字符: " << str.back() << endl; // C++11
cout << "索引5的字符: " << str[5] << endl;
cout << "索引5的字符(at): " << str.at(5) << endl;
// 3. 越界访问对比
try {
cout << "尝试访问越界索引(at): ";
cout << str.at(100) << endl; // 会抛出异常
} catch (const out_of_range& e) {
cout << "异常: " << e.what() << endl;
}
// 4. 修改元素
str[7] = 'P';
str[8] = 'P';
cout << "修改后: \"" << str << "\"" << endl;
// 5. 获取C风格字符串
const char* cstr = str.c_str();
cout << "C风格字符串: " << cstr << endl;
cout << "C风格字符串长度(strlen): " << strlen(cstr) << endl;
// 6. 获取底层字符数组 (C++11)
const char* data = str.data();
cout << "底层数据: " << data << endl;
}
输出:
=== 基本操作测试 ===
字符串: "Hello C++ World"
长度: 16 或 16
容量: 22
是否为空: 否
第一个字符: H
最后一个字符: d
索引5的字符:
索引5的字符(at):
尝试访问越界索引(at): 异常: basic_string::at: __n (which is 100) >= this->size() (which is 16)
修改后: "Hello CPP World"
C风格字符串: Hello CPP World
C风格字符串长度(strlen): 16
底层数据: Hello CPP World
字符串操作
void testStringOperations() {
cout << "\n=== 字符串操作测试 ===" << endl;
// 1. 赋值操作
string s1 = "Hello";
string s2 = "World";
s1 = s2; // 拷贝赋值
cout << "拷贝赋值后 s1: " << s1 << endl;
s1 = "C++"; // 从C字符串赋值
cout << "C字符串赋值后: " << s1 << endl;
s1.assign(5, '*'); // assign方法
cout << "assign后: " << s1 << endl;
// 2. 追加操作
s1 = "Hello";
s2 = "World";
s1 += " "; // 追加字符串
s1 += s2; // 追加另一个string
s1 += '!'; // 追加字符
cout << "追加后: " << s1 << endl;
s1.append(" 2024"); // append方法
cout << "append后: " << s1 << endl;
// 3. 插入操作
s1 = "Hello World";
s1.insert(5, " C++"); // 在位置5插入
cout << "插入后: " << s1 << endl;
// 4. 删除操作
s1.erase(5, 4); // 从位置5删除4个字符
cout << "删除后: " << s1 << endl;
s1.erase(s1.begin() + 5, s1.end() - 1); // 用迭代器删除
cout << "迭代器删除后: " << s1 << endl;
// 5. 替换操作
s1 = "I like apples";
s1.replace(7, 6, "oranges"); // 从位置7开始,替换6个字符
cout << "替换后: " << s1 << endl;
// 6. 交换操作
s1 = "First";
s2 = "Second";
cout << "交换前: s1=" << s1 << ", s2=" << s2 << endl;
s1.swap(s2);
cout << "交换后: s1=" << s1 << ", s2=" << s2 << endl;
// 7. 清空操作
s1.clear();
cout << "清空后长度: " << s1.length() << endl;
}
输出:
=== 字符串操作测试 ===
拷贝赋值后 s1: World
C字符串赋值后: C++
assign后: *****
追加后: Hello World!
append后: Hello World! 2024
插入后: Hello C++ World
删除后: Hello World
迭代器删除后: Hello
替换后: I like oranges
交换前: s1=First, s2=Second
交换后: s1=Second, s2=First
清空后长度: 0
查找与替换
void testFindAndReplace() {
cout << "\n=== 查找与替换测试 ===" << endl;
string text = "The quick brown fox jumps over the lazy dog. The fox is clever.";
// 1. 查找子串
size_t pos = text.find("fox");
if (pos != string::npos) {
cout << "找到'fox'在位置: " << pos << endl;
}
// 2. 从指定位置开始查找
pos = text.find("fox", pos + 1);
if (pos != string::npos) {
cout << "第二次找到'fox'在位置: " << pos << endl;
}
// 3. 查找字符
pos = text.find_first_of("aeiou"); // 查找元音字母
cout << "第一个元音字母在位置: " << pos << " (字符: " << text[pos] << ")" << endl;
pos = text.find_first_not_of("The quickbrown");
cout << "第一个不在指定集合的字符在位置: " << pos << endl;
// 4. 反向查找
pos = text.rfind("the");
cout << "反向查找到'the'在位置: " << pos << endl;
// 5. 替换所有匹配
string result = text;
size_t start_pos = 0;
while ((start_pos = result.find("fox", start_pos)) != string::npos) {
result.replace(start_pos, 3, "cat");
start_pos += 3; // 移动位置
}
cout << "替换所有fox为cat: " << result << endl;
// 6. 查找失败示例
pos = text.find("elephant");
if (pos == string::npos) {
cout << "未找到'elephant'" << endl;
}
}
输出:
=== 查找与替换测试 ===
找到'fox'在位置: 16
第二次找到'fox'在位置: 47
第一个元音字母在位置: 2 (字符: e)
第一个不在指定集合的字符在位置: 3
反向查找到'the'在位置: 31
替换所有fox为cat: The quick brown cat jumps over the lazy dog. The cat is clever.
未找到'elephant'
子串与分割
vector<string> splitString(const string& str, char delimiter) {
vector<string> result;
size_t start = 0;
size_t end = str.find(delimiter);
while (end != string::npos) {
result.push_back(str.substr(start, end - start));
start = end + 1;
end = str.find(delimiter, start);
}
result.push_back(str.substr(start));
return result;
}
void testSubstringAndSplit() {
cout << "\n=== 子串与分割测试 ===" << endl;
string text = "C++ is a powerful programming language";
// 1. 获取子串
string sub1 = text.substr(0, 3); // 从0开始,取3个字符
cout << "子串(0,3): \"" << sub1 << "\"" << endl;
string sub2 = text.substr(7); // 从位置7到末尾
cout << "子串(7): \"" << sub2 << "\"" << endl;
// 2. 分割字符串
string csv = "apple,banana,orange,grape";
vector<string> fruits = splitString(csv, ',');
cout << "分割字符串\"" << csv << "\":" << endl;
for (size_t i = 0; i < fruits.size(); ++i) {
cout << " [" << i << "] \"" << fruits[i] << "\"" << endl;
}
// 3. 使用字符串流分割
cout << "\n使用stringstream分割:" << endl;
string sentence = "The quick brown fox jumps over the lazy dog";
istringstream iss(sentence);
string word;
int count = 0;
while (iss >> word) {
cout << "单词" << ++count << ": " << word << endl;
}
// 4. 比较子串
string str1 = "Hello World";
string str2 = "Hello C++";
int cmp = str1.compare(0, 5, str2, 0, 5); // 比较前5个字符
if (cmp == 0) {
cout << "\n前5个字符相同" << endl;
}
cmp = str1.compare(6, 5, "World"); // 从str1位置6开始,比较5个字符
if (cmp == 0) {
cout << "str1包含'World'" << endl;
}
}
输出:
=== 子串与分割测试 ===
子串(0,3): "C++"
子串(7): "a powerful programming language"
分割字符串"apple,banana,orange,grape":
[0] "apple"
[1] "banana"
[2] "orange"
[3] "grape"
使用stringstream分割:
单词1: The
单词2: quick
单词3: brown
单词4: fox
单词5: jumps
单词6: over
单词7: the
单词8: lazy
单词9: dog
前5个字符相同
str1包含'World'
数值转换
void testNumericConversion() {
cout << "\n=== 数值转换测试 ===" << endl;
// 1. 字符串转数值 (C++11)
string numStr = "123.456";
int intVal = stoi(numStr);
cout << "stoi: " << numStr << " -> " << intVal << endl;
long longVal = stol(numStr);
cout << "stol: " << numStr << " -> " << longVal << endl;
float floatVal = stof(numStr);
cout << "stof: " << numStr << " -> " << floatVal << endl;
double doubleVal = stod(numStr);
cout << "stod: " << numStr << " -> " << doubleVal << endl;
// 2. 带进制转换
string hexStr = "FF";
int hexVal = stoi(hexStr, nullptr, 16);
cout << "十六进制: " << hexStr << " -> " << hexVal << endl;
string binStr = "1010";
int binVal = stoi(binStr, nullptr, 2);
cout << "二进制: " << binStr << " -> " << binVal << endl;
// 3. 数值转字符串
int num = 42;
string str1 = to_string(num);
cout << "to_string(42): \"" << str1 << "\"" << endl;
double pi = 3.1415926535;
string str2 = to_string(pi);
cout << "to_string(3.1415926535): \"" << str2 << "\"" << endl;
// 4. 使用stringstream进行复杂格式化
ostringstream oss;
oss << fixed << setprecision(2) << pi << " is pi";
cout << "stringstream格式: " << oss.str() << endl;
// 5. 错误处理
try {
string invalid = "abc123";
int val = stoi(invalid);
} catch (const invalid_argument& e) {
cout << "无效参数异常: " << e.what() << endl;
} catch (const out_of_range& e) {
cout << "超出范围异常: " << e.what() << endl;
}
}
输出:
=== 数值转换测试 ===
stoi: 123.456 -> 123
stol: 123.456 -> 123
stof: 123.456 -> 123.456
stod: 123.456 -> 123.456
十六进制: FF -> 255
二进制: 1010 -> 10
to_string(42): "42"
to_string(3.1415926535): "3.141593"
stringstream格式: 3.14 is pi
无效参数异常: stoi: no conversion
迭代器与算法
#include <algorithm> // 需要包含算法头文件
void testIteratorsAndAlgorithms() {
cout << "\n=== 迭代器与算法测试 ===" << endl;
string str = "Hello World";
// 1. 迭代器遍历
cout << "使用迭代器遍历: ";
for (auto it = str.begin(); it != str.end(); ++it) {
cout << *it;
}
cout << endl;
// 2. 反向迭代器
cout << "反向遍历: ";
for (auto rit = str.rbegin(); rit != str.rend(); ++rit) {
cout << *rit;
}
cout << endl;
// 3. 基于范围的for循环 (C++11)
cout << "范围for循环: ";
for (char ch : str) {
cout << ch;
}
cout << endl;
// 4. 使用STL算法
cout << "全部大写: ";
string upper = str;
transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
cout << upper << endl;
cout << "全部小写: ";
string lower = str;
transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
cout << lower << endl;
// 5. 排序
string toSort = "programming";
sort(toSort.begin(), toSort.end());
cout << "排序后: " << toSort << endl;
// 6. 反转
string toReverse = "hello";
reverse(toReverse.begin(), toReverse.end());
cout << "反转后: " << toReverse << endl;
// 7. 删除重复字符
string withDuplicates = "aabbccddeeff";
auto last = unique(withDuplicates.begin(), withDuplicates.end());
withDuplicates.erase(last, withDuplicates.end());
cout << "去重后: " << withDuplicates << endl;
// 8. 统计字符
int countA = count(str.begin(), str.end(), 'l');
cout << "字符串中'l'的个数: " << countA << endl;
}
输出:
=== 迭代器与算法测试 ===
使用迭代器遍历: Hello World
反向遍历: dlroW olleH
范围for循环: Hello World
全部大写: HELLO WORLD
全部小写: hello world
排序后: aggimmnoprr
反转后: olleh
去重后: abcdef
字符串中'l'的个数: 3
性能优化
void testPerformanceOptimization() {
cout << "\n=== 性能优化测试 ===" << endl;
// 1. 预留空间
string str;
cout << "初始容量: " << str.capacity() << endl;
str.reserve(1000); // 预分配空间
cout << "预留1000后容量: " << str.capacity() << endl;
// 2. 清空但不释放内存
str = "Hello World";
cout << "赋值后: \"" << str << "\"" << endl;
str.clear();
cout << "清空后容量: " << str.capacity() << endl;
// 3. 收缩到合适大小
str = "Short";
str.shrink_to_fit(); // C++11
cout << "收缩后容量: " << str.capacity() << endl;
// 4. 避免不必要的拷贝
string largeString(100, 'A');
// 正确做法:移动语义
string movedString = move(largeString);
cout << "移动后原字符串长度: " << largeString.length() << endl;
cout << "移动后新字符串长度: " << movedString.length() << endl;
// 5. 使用string_view (C++17)
cout << "\n使用string_view减少拷贝:" << endl;
string longString = "This is a very long string that we don't want to copy";
// 传统做法
string substring = longString.substr(10, 20);
cout << "传统子串拷贝: " << substring << endl;
// C++17 string_view
// string_view sv = longString; // 不拷贝
// cout << "string_view: " << sv.substr(10, 20) << endl;
}
输出:
=== 性能优化测试 ===
初始容量: 15
预留1000后容量: 1007
赋值后: "Hello World"
清空后容量: 1007
收缩后容量: 15
移动后原字符串长度: 0
移动后新字符串长度: 100
使用string_view减少拷贝:
传统子串拷贝: a very long string
完整测试示例
int main() {
cout << "========== C++ std::string 完整测试 ==========" << endl;
testConstructors();
testBasicOperations();
testStringOperations();
testFindAndReplace();
testSubstringAndSplit();
testNumericConversion();
testIteratorsAndAlgorithms();
testPerformanceOptimization();
// 综合示例
cout << "\n=== 综合示例:单词统计 ===" << endl;
string text = "C++ is a powerful programming language. "
"C++ supports multiple programming paradigms.";
// 转换为小写
transform(text.begin(), text.end(), text.begin(), ::tolower);
// 替换标点
for (char& c : text) {
if (ispunct(c)) c = ' ';
}
// 分割单词
istringstream iss(text);
map<string, int> wordCount;
string word;
while (iss >> word) {
wordCount[word]++;
}
// 输出统计结果
cout << "文本: " << text << endl;
cout << "\n单词统计:" << endl;
for (const auto& pair : wordCount) {
cout << " " << pair.first << ": " << pair.second << endl;
}
cout << "\n========== 测试完成 ==========" << endl;
return 0;
}
输出:
========== C++ std::string 完整测试 ==========
=== 构造函数测试 ===
...(之前的所有测试输出)...
=== 综合示例:单词统计 ===
文本: c++ is a powerful programming language c++ supports multiple programming paradigms
单词统计:
a: 1
c++: 2
is: 1
language: 1
multiple: 1
paradigms: 1
powerful: 1
programming: 2
supports: 1
========== 测试完成 ==========
重要特性总结
-
内存管理:自动管理内存,无需手动分配/释放
-
安全性 :提供范围检查(
at()方法) -
丰富接口:超过100个成员函数
-
STL兼容:支持所有STL算法
-
性能优化:短字符串优化(SSO)
-
Unicode支持:C++11起支持UTF-8/16/32
最佳实践
-
优先使用
std::string而非C风格字符串 -
大量拼接时使用
reserve()预留空间 -
使用移动语义避免不必要拷贝
-
使用
string_view(C++17)作为只读参数 -
注意编码问题,特别是在多语言环境中
std::string是C++中最常用的容器之一,掌握其用法对高效编程至关重要。