【C++ string】学习笔记

简介

string 是 C++ 标准库中的一个类,定义在 <string> 头文件中,是一个动态大小的字符数组。

定义与构造

//要使用 string,你需要包含 <string> 头文件:
#include <string>

定义一个 string 可以使用几种不同的方式:

//默认构造:创建一个空字符串。
  string s;

//使用字符串文字:创建一个字符串并初始化。
  string s = "Hello, World!";

//使用字符数组:
  const char* c_str = "Hello!";
  string s(c_str);

//指定长度的字符串:创建一个长度为 n 的字符串,初始化为某个字符。
  string s(5, 'a');  // "aaaaa"

基本操作

插入一个字符

使用s.insert()函数在s的k1号位置处插入一个字符c;和vector一样

int k1;
char c;
cin>>k1>>c;
s.insert(s.begin() + k1, c);

获取字符串长度

string s = "Hello";
int len = s.size();  // 或者 s.length(),返回字符串的长度

访问字符

char ch = s[1];  // 获取第二个字符,注意索引从 0 开始

char ch2 = s.at(1);  // 或者使用 at(),当索引超出范围时会抛出异常

at()用法补充说明

at() 方法用于访问字符串中的指定位置的字符,且会进行边界检查。如果访问的索引超出了字符串的有效范围,它会抛出 std::out_of_range 异常。

at(1) 会访问字符串中的第二个字符(索引从 0 开始)。如果字符串的长度小于或等于 1,则会抛出异常。
相比于使用 operator[](即 s[1]),at() 方法提供了更安全的访问方式,因为它会在越界时抛出异常。

string s = "Hello";
char ch2 = s.at(1);  // ch2 = 'e',因为 "Hello" 中的第二个字符是 'e'
对比 [] 和 at()
s[1] 可以直接访问索引为 1 的字符,但如果索引越界,不会抛出异常,而是返回一个未定义的行为。

string s = "Hi";
char ch = s[10];  // 未定义行为,如果越界访问,程序不会抛出异常
s.at(1) 则更安全,如果索引越界,程序会抛出异常,提醒开发者发生了错误。

string s = "Hi";
try {
    char ch = s.at(10);  // 会抛出 std::out_of_range 异常
} catch (const out_of_range& e) {
    cout << "Out of range error: " << e.what() << endl;
}

/*
总结:
at():用于访问字符串中的字符,并且会检查越界,如果越界则抛出异常。
[]:可以访问字符,但不进行越界检查,可能导致未定义行为。
通常,建议在访问字符串字符时使用 at(),尤其在涉及到不确定长度的字符串时,能更好地避免潜在的错误。
*/

修改字符

s[0] = 'h';  // 修改第一个字符

字符串拼接

string s1 = "Hello";
string s2 = " World!";

string s3 = s1 + s2;  // 拼接
s1.append(s2);  // 使用 append() 方法

查找字符串find

int pos = s.find("lo");  // 返回子字符串首次出现的位置,如果没有找到返回 string::npos
//size_t pos = s.find("lo");
if (pos != string::npos) {
    cout << "'lo' found at position " << pos << endl;
}
/*
string::npos 是 C++ 标准库中的一个常量,用于表示一个无效的字符串位置。它通常与 find()、rfind() 和类似的函数一起使用,以指示查找失败的情况。
*/

提取子字符串substr

string s2 = s.substr(0, 3);  // 从位置 0 开始,提取 3 个字符 substr(pos, length)

删除字符

位置是迭代器的位置。和vector一样

数字表示

s.erase(1, 3);  // 从位置 1 开始,删除 3 个字符 erase(pos, length)

迭代器表示

 使用s.erase()函数删除s的k2号位置的字符。

s.erase(s.begin() + k2);

替换字符

s.replace(pos, len, s1);

s.replace(0, 5, "Hi");  // 从位置 0 开始,替换 5 个字符为 "Hi".在s的基础上修改
//或者结果赋值给一个新的string,命名为s1
string s1 = s.replace(0, 5, "Hi");

转换大小写

transform(s.begin(), s.end(), s.begin(), ::tolower);  // 转小写
transform(s.begin(), s.end(), s.begin(), ::toupper);  // 转大写

清空字符串

s.clear();  // 清空字符串内容

比较字符串

直接使用 > < == 进行比较(字典序)

if (s1 == s2) {
    cout << "Strings are equal" << endl;
}

转换为C风格字符串

const char* cstr = s.c_str();  // 将 string 转为 C 风格字符串

 整数转字符串

int x = 10;
string v = to_string(x);

字符串转整数

string s = "1234";
int num = stoi(s);

注意!stoi()只能用于字符串,对于字符char会报错。

字符转整数

方法 1:利用 ASCII 码计算
char c = '5';
int num = c - '0';  // '5' - '0' = 5

适用场景

  • 仅适用于 '0' 到 '9' 的字符。

  • 如果 c 不是数字字符(如 'a'),结果会是错误的('a' - '0' = 49)。

方法 2:先转成 string,再用 stoi()
char c = '5';
int num = stoi(string(1, c));  // 构造一个长度为 1 的 string

适用场景

  • 适用于任何 char,但比方法 1 稍慢。

  • 如果 c 不是数字字符(如 'a'),stoi() 会抛出 std::invalid_argument 异常。

方法 3:使用 istringstream(更通用)
#include <sstream>
char c = '5';
int num;
istringstream(string(1, c)) >> num;

适用场景

  • 适用于更复杂的转换(如十六进制字符 'A' 转 10)。

  • 比 stoi() 稍慢,但更灵活。

检查是否为空

if (s.empty()) {
    cout << "String is empty" << endl;
}
//如果为空,返回true

序列反转

在 C++ 中,reverse() 是标准库 <algorithm> 头文件中的一个算法,用于反转容器中的元素顺序。它可以用来反转任何支持迭代器的容器(如 vector、string、deque 等)。

reverse() 将 [first, last) 范围内的元素顺序反转。即第一个元素与最后一个元素交换,第二个元素与倒数第二个元素交换,以此类推。

//基本语法
#include <algorithm>
void reverse(Iterator first, Iterator last);
//reverse()没有返回值,它直接修改原容器或序列
//故不用s.reverse(),而是直接reverse()
    
//string reversed = reverse(substr.begin(), substr.end());这是错误用法,没有返回值
    string s = "Hello, World!";
    reverse(s.begin(), s.end());//s.end()是最后一个元素的后一个位置
    cout << "Reversed string: " << s << endl;

两个字符的反转

//两个字符的三种反转方式
    string substr = s.substr(i, 2);  // 获取长度为 2 的子字符串
    string reversed = string(1, substr[1]) + substr[0];  // 反转该子字符串

    string reversed = {substr[1], substr[0]};

    reverse(substr.begin(), substr.end());

示例程序

#include <iostream>
#include <string>

using namespace std;

int main() {
    // 创建字符串
    string s = "Hello, World!";
    
    // 输出字符串
    cout << "Original string: " << s << endl;
    
    // 获取长度
    cout << "Length of string: " << s.size() << endl;
    
    // 拼接字符串
    string s2 = " How are you?";
    string s3 = s + s2;
    cout << "Concatenated string: " << s3 << endl;
    
    // 查找子字符串
    size_t pos = s.find("World");
    if (pos != string::npos) {
        cout << "'World' found at position: " << pos << endl;
    }
    
    // 提取子字符串
    string sub = s.substr(7, 5);  // "World"
    cout << "Substring: " << sub << endl;
    
    // 修改字符串
    s[0] = 'h';  // 将 "Hello" 改为 "hello"
    cout << "Modified string: " << s << endl;
    
    // 清空字符串
    s.clear();
    cout << "String after clear: " << (s.empty() ? "Empty" : s) << endl;
    
    return 0;
}

 优点

  • 自动管理内存string 会自动管理内存分配和释放,不需要显式地处理内存分配。

  • 便捷的操作:提供了许多方法,简化了字符串操作(如拼接、查找、替换等)。

  • 可以与 C 风格字符串互操作:可以方便地将 string 转换为 C 风格字符串(const char*)并与 C 函数一起使用。

 总结

  • string 是一个非常强大且灵活的字符串类,提供了多种方法来操作字符串。

  • 它是 C++ 标准库的一部分,能够更安全和方便地操作字符串,避免了 C 风格字符串中的许多麻烦(如手动管理内存、缺乏边界检查等)。

  • string 是 C++ 中处理字符串时的首选类型,尤其适合需要频繁操作字符串的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值