一、string是什么

String 本质是由多个字符组成的线性有序序列,是编程语言中专门封装字符数组的高级数据结构。

字符串:"hello"

底层存储:[ 'h' , 'e' , 'l' , 'l' , 'o' ]

和C语言中的char[ ]相似。

二、string的优点

在 C 语言中我们用 char* / char[]处理字符串,痛点非常多:

  • 需要手动管理内存,容易内存泄漏;

  • 字符串拼接、拷贝、查找、截取都要手写逻辑,代码冗余;

  • 没有封装好的成员方法,易用性极差;

  • 无法直接用运算符做字符串比较、拼接。

C++ STL 提供的 std::string,它本质是封装了字符动态数组的容器,完美替代原生字符数组:

  • 自动管理内存,无需手动 malloc/free;
  • 包含很多字符串操作函数;
  • 支持迭代器、兼容 STL 常规用法;
  • 支持运算符重载,拼接、比较极其简洁。

三、string 常见初始化方式

学习 string类,是离不开查阅文档的

string 的文档

名称使用示例功能说明
default(默认构造)string();构造一个空字符串,长度为零个字符
copy (拷贝构造)string (const string& str);构造str的副本。

from c-string(拷贝c

字符串)

string (const char* s);复制s指向的以null 结尾的字符序列。

使用示例

oid Teststring()
{
string s1; // 构造空的string类对象s1
string s2("hello string"); // 用C格式字符串构造string类对象s2
string s3(s2); // 拷贝构造s2

操作符operator=

#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;
}
//输出结果:
//    Test string: x

四、string类对象的容量操作

获取长度、返回空间大小,判空,清空,预留空间,修改空间大小

名称

使用示例

功能说明

⭐size

str.size()

返回字符串有效字符长度

length

str.length()

返回字符串有效字符长度

capacity

str.capacity()

返回空间总大小

⭐empty

str.empty( )

检测字符串是否为空串,是返回true,否则返回false

⭐clear

str.clear( )

清空有效字符

⭐reserve

s.reserve(100);

为字符串预留100空间

⭐resize

s.resize(10, 'x');

将有效字符的个数改成n个,多出的空间用字符c填充

注意:

clear()

  • 作用:只清空有效字符,将 size() 置为 0。

  • 不会释放底层空间,capacity() 大小保持不变。


resize(size_t n)resize(size_t n, char c)

  • 共同作用:将字符串有效字符个数修改为 n 个

  • 区别:

    • resize(n)字符增多时,用数字“0”填充。

    • resize(n, c)字符增多时,用字符“c”填充。

  • 规则:

    • n < 当前 size:截断字符串,size 变小,capacity 不变。

    • n > 当前 size:扩展字符串,size 变大,capacity 可能扩容。


 reserve()

  • 作用:为 string 预留底层空间。

  • 特点:

    • 不改变有效元素个数(size 不变)。

    • 仅改变底层容量 capacity

  • 规则:

    • 当参数大于当前 capacity 时:扩大容量。

    • 当参数小于等于当前 capacity 时:不做任何改变,不会缩容。

使用示例

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s = "hello world";

    // 1. size / length 获取有效字符个数
    cout << s.size() << endl;     // 输出:11
    cout << s.length() << endl;   // 输出:11

    // 2. capacity 获取底层容量
    cout << s.capacity() << endl; // 输出:15(不同编译器略有差异)

    // 3. empty 判断是否为空
    cout << s.empty() << endl;    // 输出:0  0代表非空

    // 4. reserve 预留空间,只改容量不改长度
    s.reserve(100);
    cout << s.capacity() << endl; // 输出:111
    cout << s.size() << endl;     // 输出:11

    // 5. resize 改变有效长度
    s.resize(5);
    cout << s << endl;            // 输出:hello
    cout << s.size() << endl;     // 输出:5

    s.resize(10, '*');
    cout << s << endl;            // 输出:hello*****
    cout << s.size() << endl;     // 输出:10

    // 6. clear 清空字符,容量不变
    s.clear();
    cout << s.size() << endl;     // 输出:0
    cout << s.capacity() << endl; // 输出:111
    cout << s.empty() << endl;    // 输出:1  1代表为空

    return 0;
}

五、string类对象的访问及遍历操作

名称

使用示例

功能说明

⭐operator[]

s[0]

返回 pos 位置的字符,const string 对象调用时返回 const char&

begin()

end()

s.begin()

s.end ()

begin() 获取指向第一个字符的迭代器;end() 获取指向最后一个字符下一个位置的迭代器

rbegin()

rend()

s.rbegin ()

s.rend ()

rbegin() 获取指向最后一个字符的反向迭代器;rend() 获取指向第一个字符前一个位置的反向迭代器

范围 for(C++11)

for (char ch : s) {cout << ch;}

更简洁的遍历方式,底层等价于迭代器遍历

使用示例

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "Hello123";

    // 1. 下标访问
    cout << "s[0] = " << s[0] << endl;  // 输出:s[0] = H

    // 2. 普通迭代器
    cout << "迭代器遍历: ";             // 输出:迭代器遍历:
    for (auto it = s.begin(); it != s.end(); ++it)
        cout << *it;                    // 依次输出:H e l l o 1 2 3
    cout << endl;                       // 换行

    // 3. 反向迭代器
    cout << "反向遍历: ";               // 输出:反向遍历:
    for (auto it = s.rbegin(); it != s.rend(); ++it)
        cout << *it;                    // 依次输出:3 2 1 o l l e H
    cout << endl;                       // 换行

    // 4. 范围 for (最推荐)
    cout << "范围for: ";                // 输出:范围for:
    for (char ch : s)
        cout << ch;                     // 依次输出:H e l l o 1 2 3
    cout << endl;                       // 换行

    return 0;
}

六. string类对象的修改操作

尾插、查找、截取

名称

使用实例

功能说明

push back

s.push_back('c');

在字符串后尾插字符c

append

s.append(" World");

在字符串后追加一个字符串

⭐operator+=

s += "str";

在字符串后追加字符串str

⭐c_str

s.c_str();

返回C格式字符串

⭐find + npos

s.find('c');

从字符串pos位置开始往找字符c,返回该字符在字符串中的位置

rfind

s.rfind('c');

从字符串pos位置开始往找字符c,返回该字符在字符串中的位置

substr

s.substr(pos, n);

在str中从pos位置开始,截取n个字符,然后将其返回

使用示例

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "Hello";

    // 1. push_back:在字符串后尾插字符
    s.push_back('!');       // 在末尾加 '!'
    cout << s << endl;      // 输出:Hello!

    // 2. append:在字符串后追加一个字符串
    s.append(" World");     // 追加 " World"
    cout << s << endl;      // 输出:Hello! World

    // 3. operator+=(重点):追加字符/字符串,和 append 等价但更常用
    s += "!!";              // 追加字符串 "!!"
    s += '?';               // 追加字符 '?'
    cout << s << endl;      // 输出:Hello! World!!?

    // 4. c_str(重点):返回C格式字符串(const char*)
    const char* cstr = s.c_str();
    cout << cstr << endl;   // 输出:Hello! World!!?(和printf兼容)
    printf("printf输出:%s\n", cstr); // 常用于C语言API交互

    // 5. find + npos(重点):从pos位置往后找字符/字符串,返回下标;找不到返回npos
    size_t pos = s.find('W');   // 从0位置往后找 'W'
    if (pos != string::npos) {  // 必须判断是否找到
        cout << "'W'的位置:" << pos << endl; // 输出:7
    } else {
        cout << "未找到" << endl;
    }

    size_t notFound = s.find('x');
    if (notFound == string::npos) {
        cout << "'x'未找到,npos值为:" << string::npos << endl;
    }

    // 6. rfind:从pos位置往前找字符/字符串(反向查找)
    size_t rPos = s.rfind('!'); // 从末尾往前找第一个 '!'
    cout << "最后一个'!'的位置:" << rPos << endl; // 输出:13

    // 7. substr:从pos位置开始,截取n个字符(不写n则截取到末尾)
    string sub = s.substr(6, 5); // 从下标6开始,截取5个字符
    cout << "截取的子串:" << sub << endl; // 输出:World

    return 0;
}


七. string类非成员函数

运算符重载、“+”、“<<”,">>"

获取一行输入、字典序比较

函数

功能说明

operator+

string c = a + " " + b;

尽量少用,因为传值返回,导致深拷贝效率低

⭐operator>>

——

输入运算符重载

⭐operator<<

——

输出运算符重载

⭐getline

getline(cin, line);

获取一行字符串(可包含空格)

⭐relational operators

(s1 == s3)

(s1 != s2)

(s1 < s2)

(s2 > s1)

大小比较(按字典序)

使用示例

#include <iostream>
#include <string>
using namespace std;

int main() {
    // ------------------------------
    // 1. operator+(不推荐)
    // ------------------------------
    string a = "Hello";
    string b = "World";
    string c = a + " " + b; // 不推荐:会多次深拷贝,效率低
    cout << "operator+结果:" << c << endl;
    // 推荐用 += 代替:
    string d = "Hello";
    d += " ";
    d += "World";
    cout << "推荐写法(+=):" << d << endl;

    // ------------------------------
    // 2. operator>>(输入运算符重载)
    // ------------------------------
    string input1;
    cout << "请输入一个单词(operator>>):";
    cin >> input1; // operator>> 默认以空格/换行分隔,只能读单个单词
    cout << "你输入的单词:" << input1 << endl;

    // ------------------------------
    // 3. operator<<(输出运算符重载)
    // ------------------------------
    string output = "这是输出运算符测试";
    cout << "operator<<输出:" << output << endl; // cout << string 就是调用 operator<<

    // ------------------------------
    // 4. getline(获取一行字符串)
    // ------------------------------
    // 注意:如果前面用过 cin >>,会残留换行符,需要先清空缓冲区
    cin.ignore(); // 忽略上一次输入残留的换行
    string line;
    cout << "请输入一行文本(可以带空格):";
    getline(cin, line); // 读取整行,包括空格,直到遇到换行符
    cout << "你输入的整行:" << line << endl;

    // ------------------------------
    // 5. relational operators(大小比较)
    // ------------------------------
    string s1 = "apple";
    string s2 = "banana";
    string s3 = "apple";

    cout << boolalpha; // 让bool输出true/false而不是1/0
    cout << "s1 == s3 ? " << (s1 == s3) << endl; // true
    cout << "s1 != s2 ? " << (s1 != s2) << endl; // true
    cout << "s1 < s2 ? " << (s1 < s2) << endl;   // true(按字典序比较)
    cout << "s2 > s1 ? " << (s2 > s1) << endl;   // true

    return 0;
}

更多推荐