String类

string是C++的一个类类型(不是基本类型),用于处理字符串。相对的C中的字符串是字符数组。

1.头文件和命名空间

需要引用string、iostream、sstream、algorithm等STD库。

#include<string> //必须有的主要头文件
#include<iostream> //用于输入输出
#include<sstream> //用于字符串流
#include<algorithm> //算法操作

using namespace std;

2.构造函数

// 默认构造函数
string str1;                    // 空字符串

// 从C风格字符串构造
string str2("Hello");          // "Hello"
string str3 = "World";         // "World"

// 从另一个string构造
string str4(str2);             // "Hello"
string str5 = str2;            // "Hello"

// 从部分字符串构造
string str6("Hello World", 5); // "Hello" (前5个字符)
string str7(str2, 1, 3);       // "ell" (从位置1开始,长度3)

// 重复字符构造
string str8(5, 'A');           // "AAAAA"

// 使用迭代器构造
string str9(str2.begin(), str2.end());  // "Hello"

// 使用初始化列表 (C++11)
string str10{'H', 'e', 'l', 'l', 'o'};  // "Hello"

3.基本操作

3.1 赋值操作

string s1, s2, s3;
// 赋值操作
s1 = "Hello";                  // "Hello"
s2 = s1;                       // "Hello"
s3.assign("World");            // "World"
s3.assign(s1, 1, 3);           // "ell" (从s1的位置1开始,长度3)
s3.assign(5, 'X');             // "XXXXX"

长度和容量

string s = "Hello";

cout << s.length() << endl;    // 5
cout << s.size() << endl;      // 5 (与length()相同)
cout << s.capacity() << endl;  // 当前分配的存储空间大小
cout << s.max_size() << endl;  // 最大可能长度

s.resize(10, '!');             // "Hello!!!!!"
s.resize(3);                   // "Hel"

s.reserve(100);                // 预分配100字符的空间
s.shrink_to_fit();             // 减少容量以匹配大小(C++11)

访问字符

string s = "Hello";

// 使用下标运算符
char c1 = s[0];                // 'H'
s[1] = 'a';                    // "Hallo"

// 使用at()函数(会检查边界)
char c2 = s.at(2);             // 'l'
// s.at(10);                   // 抛出std::out_of_range异常

// 访问首尾字符
char first = s.front();        // 'H' (C++11)
char last = s.back();          // 'o' (C++11)

// 获取C风格字符串
const char* cstr = s.c_str();  // 以null结尾的C字符串
const char* data = s.data();   // 字符数组(C++17前可能不以null结尾)

3.2 字符串修改

追加

string s = "Hello";

s += " World";                 // "Hello World"
s.append("!!!");               // "Hello World!!!"
s.push_back('?');              // "Hello World!!!?"

// 追加部分字符串
s.append("ABCDEF", 3);         // 追加前3个字符 "ABC"
s.append(s, 0, 3);             // 追加s的前3个字符

// 使用insert插入
s.insert(5, " C++");           // 在位置5插入 "Hello C++ World!!!?ABC"

删除

string s = "Hello World";

s.erase(5, 6);                 // "Hello" (从位置5删除6个字符)
s.erase(s.begin() + 2);        // "Helo" (删除位置2的字符)
s.erase(s.begin() + 1, s.begin() + 3); // "Ho" (删除[1,3)的字符)

s.clear();                     // 清空字符串
s = "Hello World";
s.pop_back();                  // "Hello Worl" (C++11)

替换

string s = "Hello World";

s.replace(6, 5, "C++");        // "Hello C++" (从位置6开始,替换5个字符)
s.replace(s.begin(), s.begin() + 5, "Hi"); // "Hi World"

3.3 字符串查找

string s = "Hello World, Hello C++";

// find - 查找子串
size_t pos1 = s.find("Hello");     // 0
size_t pos2 = s.find("Hello", 1);  // 13 (从位置1开始找)
size_t pos3 = s.find("Java");      // string::npos (未找到)

// rfind - 从后向前查找
size_t pos4 = s.rfind("Hello");    // 13

// find_first_of - 查找字符集中任意字符首次出现
size_t pos5 = s.find_first_of("aeiou");  // 1 ('e')

// find_last_of - 查找字符集中任意字符最后出现
size_t pos6 = s.find_last_of("aeiou");   // 17 ('+')

// find_first_not_of - 查找不在字符集中的字符首次出现
size_t pos7 = s.find_first_not_of("Helo "); // 5 ('W')

// find_last_not_of - 查找不在字符集中的字符最后出现
size_t pos8 = s.find_last_not_of("+C");  // 16 (' ')

3.4 子串操作

string s = "Hello World";

// substr - 获取子串
string sub1 = s.substr(6);        // "World" (从位置6到结尾)
string sub2 = s.substr(0, 5);     // "Hello" (从位置0开始,长度5)
string sub3 = s.substr(6, 100);   // "World" (长度超过时取到结尾)
// string sub4 = s.substr(100);   // 抛出std::out_of_range异常

// compare - 比较字符串
int cmp1 = s.compare("Hello");    // >0 (s > "Hello")
int cmp2 = s.compare(6, 5, "World"); // 0 (s从6开始的5个字符等于"World")

3.5 字符串比较

string s1 = "apple";
string s2 = "banana";

// 使用比较运算符
bool b1 = (s1 == s2);      // false
bool b2 = (s1 != s2);      // true
bool b3 = (s1 < s2);       // true (字典序比较)
bool b4 = (s1 > s2);       // false
bool b5 = (s1 <= s2);      // true
bool b6 = (s1 >= s2);      // false

// 与C字符串比较
bool b7 = (s1 == "apple"); // true
bool b8 = ("apple" == s1); // true (有重载运算符)

// 使用compare函数
int result = s1.compare(s2);
if (result < 0) cout << "s1 < s2" << endl;
else if (result > 0) cout << "s1 > s2" << endl;
else cout << "s1 == s2" << endl;

3.6 输入输出

// 从标准输入读取
string input;
cout << "Enter a string: ";
cin >> input;                    // 读取到空白字符为止
getline(cin, input);             // 读取整行(包括空格)

// 清除输入缓冲区
cin.ignore(numeric_limits<streamsize>::max(), '\n');

// 输出
cout << "You entered: " << input << endl;

// 格式化输出
printf("C-style: %s\n", input.c_str());

// 使用stringstream
stringstream ss;
ss << "Number: " << 42 << " String: " << input;
string formatted = ss.str();
cout << formatted << endl;

3.7 字符串转换

数字转换

// 字符串转数字
string num_str = "123";
int num1 = stoi(num_str);        // 123
double num2 = stod("3.14");      // 3.14
long num3 = stol("1000000");     // 1000000

// 带异常处理
try {
    int num = stoi("abc");       // 抛出invalid_argument
} catch (const invalid_argument& e) {
    cout << "Invalid argument: " << e.what() << endl;
} catch (const out_of_range& e) {
    cout << "Out of range: " << e.what() << endl;
}

// 数字转字符串
string s1 = to_string(123);      // "123"
string s2 = to_string(3.14);     // "3.140000"
string s3 = to_string(true);     // "1"

大小写转换

string s = "Hello World";

// 转换为大写
transform(s.begin(), s.end(), s.begin(), ::toupper);
cout << s << endl;  // "HELLO WORLD"

// 转换为小写
transform(s.begin(), s.end(), s.begin(), ::tolower);
cout << s << endl;  // "hello world"

// 使用C++11的lambda
transform(s.begin(), s.end(), s.begin(),
    [](unsigned char c) { return toupper(c); });

3.8 字符串分割和连接

分割字符串

vector<string> split_string(const string& str, char delimiter) {
    vector<string> tokens;
    string token;
    istringstream token_stream(str);
    
    while (getline(token_stream, token, delimiter)) {
        if (!token.empty()) {
            tokens.push_back(token);
        }
    }
    
    return tokens;
}

// 使用示例
string data = "apple,banana,cherry,date";
vector<string> fruits = split_string(data, ',');
// fruits = {"apple", "banana", "cherry", "date"}

连接字符串

// 使用 + 运算符
string s1 = "Hello" + string(" ") + "World";  // "Hello World"

// 使用 append
string s2 = "Hello";
s2.append(" ").append("World");  // "Hello World"

// 连接字符串数组
vector<string> words = {"Hello", "World", "!"};
string result;
for (const auto& word : words) {
    if (!result.empty()) result += " ";
    result += word;
}
// result = "Hello World !"

// 使用 accumulate (C++17)
#include <numeric>
string joined = accumulate(next(words.begin()), words.end(), words[0],
    [](string a, string b) { return a + " " + b; });

3.9 字符串算法操作

#include <algorithm>

string s = "Hello World";

// 反转字符串
reverse(s.begin(), s.end());      // "dlroW olleH"
reverse(s.begin(), s.end());      // 恢复原状

// 排序字符串
sort(s.begin(), s.end());         // " HWdellloor"
sort(s.begin(), s.end(), greater<char>()); // "roollledWH "

// 移除特定字符
s = "Hello World";
s.erase(remove(s.begin(), s.end(), 'l'), s.end());
// s = "Heo Word"

// 移除连续重复字符
s = "Hellooo Wooorld";
auto last = unique(s.begin(), s.end());
s.erase(last, s.end());
// s = "Helo World"