精通C++ STL(一):解开string类的面纱与高效应用

目录

string的定义方式

string的插入

string的拼接

string的删除

string的查找

string的比较

string的替换

string的交换

string的大小和容量

string中元素的访问

string中运算符的使用

string中与迭代器相关的函数

string与字符串之间的转换

string中子字符串的提取

string中的getline函数


string的定义方式

  • string():默认构造函数,创建一个空字符串。

  • string (const string& str):拷贝构造函数,创建一个新的字符串对象,它是给定字符串str的一个副本。

  • string (const string& str, size_t pos, size_t len = npos):从已存在的字符串str中提取子串构造新字符串。pos是开始位置的索引,len是要提取的字符数;如果省略或设为npos,则提取从pos到字符串末尾的所有字符。

  • string (const char* s):从C风格字符串s构造字符串对象。

  • string (const char* s, size_t n):从C风格字符串s的前n个字符构造字符串对象。

  • string (size_t n, char c):创建一个长度为n,每个字符都为c的字符串。

  • template <class InputIterator> string (InputIterator first, InputIterator last):这是一个模板构造函数,它接受一对迭代器(firstlast),在这对迭代器所指定的范围内构造字符串。这使得可以从任何支持迭代访问的对象(如数组、容器等)中构造字符串。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    // 1. 默认构造函数
    string strDefault;
    cout << strDefault << endl;

    // 2. 拷贝构造函数
    string strCopy("Hello");
    string strCopied(strCopy);
    cout << strCopied << endl;

    // 3. 从已有字符串提取子串构造
    string strSubstr("HelloWorld", 6);
    cout << strSubstr << endl;

    // 4. 从C风格字符串构造
    string strFromCStr("World");
    cout << strFromCStr << endl;

    // 5. 从C风格字符串的部分构造
    const char* partCStr = "HelloWorld";
    string strPartCStr(partCStr, 5);
    cout << strPartCStr << endl;

    // 6. 创建指定长度和字符的字符串
    string strCharRepeat(5, 'A');
    cout << strCharRepeat << endl;

    // 7. 使用迭代器构造
    char arr[] = { 'H', 'e', 'l', 'l', 'o' };
    string strFromIter(arr, arr + sizeof(arr) - 1);
    cout << strFromIter << endl;

    return 0;
}

代码结果:

string的插入

  使用push_back进行尾插

void push_back(char ch);

功能说明:

  • 参数ch - 要添加到字符串末尾的字符。
  • 返回值:此函数没有返回值,它直接修改调用它的字符串对象,在其末尾增加给定的字符。
  • 扩容:如果添加字符导致字符串超出当前容量,std::string会自动进行内存管理,包括重新分配内存和复制现有内容到新位置,以容纳新增的字符,这个过程对用户透明。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str = "Hello, ";
    str.push_back('W');
    str.push_back('o');
    str.push_back('r');
    str.push_back('l');
    str.push_back('d');
    str.push_back('!');

    cout << str << endl;  // 输出: Hello, World!

    return 0;
}

代码结果:

  使用insert插入

插入单个字符:

string& insert(size_type pos, char ch);
  • 参数pos - 插入字符的位置(基于0的索引)。ch - 要插入的字符。
  • 返回值:返回对字符串自身的引用,允许链式调用。

插入字符串:

string& insert(size_t pos, const string& str);
string& insert(size_t pos, const string& str, size_t subpos, size_t sublen = npos);
  • 第一种形式直接在pos位置插入整个字符串str
  • 第二种形式从字符串strsubpos位置开始,插入sublen个字符到pos位置。如果sublen被省略或设置为npos,则插入从subposstr末尾的所有字符。

插入字符数量:

string& insert(size_t pos, size_t count, char ch);
  • pos位置插入count个字符ch

插入迭代器范围:

template <class Iterator>
string& insert(size_t pos, Iterator first, Iterator last);
  • 插入由迭代器firstlast指定的范围内所有字符到pos位置。

代码演示:

#include <iostream>
#include <string>

using namespace std;

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

    // 在索引2的位置插入字符'a'
    str.insert(2, "a");
    cout << str << endl;  // 输出: Helalo

    // 在末尾插入字符串" World"
    str.insert(str.size(), " World");
    cout << str << endl;  // 输出: Hela World

    // 插入重复字符'e'三次
    str.insert(1, 3, 'e');
    cout << str << endl;  // 输出: Heeele World

    return 0;
}

代码结果:

string的拼接

  使用append函数完成string的拼接

 追加字符串:

string& append(const string& str);
  • 将整个字符串str追加到当前字符串末尾。

追加子串:

string& append(const string& str, size_t pos, size_t n = npos);
  • 从字符串strpos位置开始追加n个字符到当前字符串末尾。如果n等于npos,则追加从posstr末尾的所有字符。

追加字符数量:

string& append(size_t n, char c);
  • 在字符串末尾追加n个字符c

追加字符数组:

string& append(const char* s);
string& append(const char* s, size_t n);
  • 第一种形式追加C风格字符串s直到遇到空字符\0
  • 第二种形式追加C风格字符串s的前n个字符。

追加迭代器范围:

template <class Iterator>
string& append(Iterator first, Iterator last);
  • 追加由迭代器firstlast指定的范围内所有字符。

代码演示:

#include <iostream>
#include <string>

using namespace std;

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

    // 追加字符串" World"
    str.append(" World");
    cout << str << endl;  // 输出: Hello World

    // 追加三个字符'a'
    str.append(3, '!');
    cout << str << endl;  // 输出: Hello World!!!

    // 从"C-style String"中追加前4个字符
    const char* cs = "C-style String";
    str.append(cs, 4);
    cout << str << endl;  // 输出: Hello World!!!C-st

    return 0;
}

代码结果:

string的删除

  使用pop_back进行尾删

void pop_back();

功能说明:

  • 此函数没有返回值,它直接修改调用它的字符串对象,移除其末尾的字符。
  • 如果字符串为空,调用pop_back函数是未定义行为。实践中,一些实现可能会抛出异常或忽略此操作,但最好避免在空字符串上调用此函数。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() {
    std::string str = "Hello, World!";

    // 删除末尾的感叹号
    str.pop_back();
    cout << str << endl;  // 输出: Hello, World

    // 再次删除,这次是'd'
    str.pop_back();
    cout << str << endl;  // 输出: Hello, Worl

    // 继续删除,直至字符串为空
    while ( !str.empty() ) 
    {
        str.pop_back();
    }
    cout << (str.empty() ? "Now the string is empty." : "String still has characters.") << endl;  // 输出: Now the string is empty.

    return 0;
}

代码结果:

  使用erase删除

删除单个字符:

iterator erase(iterator position);
  • 删除指针position所指向的字符,并返回下一个字符的迭代器。

删除指定范围内的字符:

iterator erase(iterator first, iterator last);
  • 删除从迭代器firstlast之间(不包括last)的所有字符,并返回last之后的第一个字符的迭代器。

删除指定位置及其后的若干字符:

string& erase(size_t pos = 0, size_t n = npos);
  • 删除从索引pos开始的n个字符。如果n等于npos,则删除从pos到字符串末尾的所有字符。返回修改后的字符串的引用。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string str = "Hello, World!";

    // 删除第7个字符(逗号)
    str.erase(6, 1);
    cout << str << endl;  // 输出: Hello World!

    // 删除从位置3到5的字符("lo")
    str.erase(3, 2);
    cout << str << endl;  // 输出: HelWorld!

    // 使用迭代器删除"World"之后的所有字符
    auto it = str.find("World");
    if (it != string::npos)
    {
        it += 5; // 移动到"World"之后
        str.erase(it, str.end());
    }
    cout << str << endl;  // 输出: HelWorld

    return 0;
}

代码结果:

string的查找

  使用find函数正向搜索第一个匹配项

查找子串:

size_t find(const string& str, size_t pos = 0) const;
  • 在字符串中查找子串str首次出现的位置,搜索从索引pos开始。默认情况下,pos为0,即从字符串开头开始搜索。

查找单个字符:

size_t find(char c, size_t pos = 0) const;
  • 查找字符c首次出现的位置,搜索同样从索引pos开始。

查找子串并指定结束搜索位置:

size_t find(const string& str, size_t pos, size_t n) const;
  • 查找子串str的前n个字符首次出现的位置,搜索从索引pos开始。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str = "Hello, this is a test string.";

    // 查找子串"test"
    size_t pos1 = str.find("test");
    if (pos1 != string::npos) 
    {
        cout << "Found 'test' at position: " << pos1 << endl;
    }
    else 
    {
        cout << "'test' not found." << endl;
    }

    // 查找字符'a',从位置10开始
    size_t pos2 = str.find('a', 0);
    cout << "Found 'a' after position 0 at: " << pos2 << endl;

    // 尝试查找不存在的子串
    size_t pos3 = str.find("notfound");
    if (pos3 == std::string::npos) 
    {
        cout << "'notfound' not found in the string." << endl;
    }

    return 0;
}

代码结果:

  使用rfind函数反向搜索第一个匹配项

查找子串:

size_t rfind(const string& str, size_t pos = npos) const;
  • 从字符串末尾开始查找子串str首次出现的位置,可以指定搜索的起始位置posnpos来从字符串的末尾开始搜索,默认也是这样。

查找单个字符:

size_t rfind(char c, size_t pos = npos) const;
  • 从字符串末尾开始查找字符c首次出现的位置,同样可以指定搜索的起始位置。

查找子串并指定结束搜索位置:

size_t rfind(const string& str, size_t pos, size_t n) const;
  • 从字符串末尾开始查找子串str的前n个字符首次出现的位置,搜索从索引pos开始。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str = "Hello, this is a test. Testing, 1, 2, test.";

    // 从后往前查找子串"test"
    size_t pos1 = str.rfind("test");
    if (pos1 != string::npos) 
    {
        cout << "Found 'test' from end at position: " << pos1 << endl;
    }
    else 
    {
        cout << "'test' not found from end." << endl;
    }

    // 查找字符't',限制搜索范围
    size_t pos2 = str.rfind('t', 20);
    cout << "Last 't' before position 20 found at: " << pos2 << endl;

    // 尝试查找不存在的子串
    size_t pos3 = str.rfind("notfound");
    if (pos3 == std::string::npos) 
    {
        cout << "'notfound' not found from end in the string." << endl;
    }

    return 0;
}

代码结果:

string的比较

  使用compare函数完成比较

函数原型及返回值意义:

int compare(const string& str) const;
int compare(size_t pos1, size_t n1, const string& str) const;
int compare(size_t pos1, size_t n1, const string& str, size_t pos2, size_t n2 = npos) const;
int compare(const char* s) const;
int compare(size_t pos1, size_t n1, const char* s) const;
int compare(size_t pos1, size_t n1, const char* s, size_t n2) const;

返回值解释:

  • 如果当前字符串小于比较的字符串,则返回负整数。
  • 如果两者相等,则返回0。
  • 如果当前字符串大于比较的字符串,则返回正整数。

比较整个字符串:

std::string str1 = "apple";
std::string str2 = "banana";
int result = str1.compare(str2);

        如果result < 0,说明str1在字典顺序上小于str2;如果result > 0,则str1大于str2;若result == 0,两者相等。

比较子串:

std::string str1 = "pineapple";
std::string str2 = "apple";
int result = str1.compare(4, 5, str2); // 从str1的第4个字符开始,比较5个字符

        这里比较的是"apple"与"apple",由于它们相等,返回值将是0。

比较与C风格字符串:

std::string str = "hello";
int result = str.compare("world");

        比较"hello"与"world"。

指定长度的比较:

std::string str1 = "abcdef";
std::string str2 = "abcxyz";
int result = str1.compare(0, 3, str2, 0, 3); // 比较前3个字符

        比较"abc"与"abc",结果为0,因为两者相同。

string的替换

  使用replace函数完成string的替换

 替换单个范围的子串:

string& replace(size_t pos, size_t len, const string& str);
  • 从位置pos开始,替换长度为len的子字符串为str

使用子串替换另一子串:

string& replace(size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
  • 同样从位置pos开始,替换长度为len的子字符串,但是使用str中的从subpos开始长度为sublen的子串进行替换。

用单个字符替换:

string& replace(size_t pos, size_t len, size_t n, char c);
  • 从位置pos开始,替换长度为len的子字符串为n个字符c

迭代器范围替换:

string& replace(iterator i1, iterator i2, const string& str);
string& replace(iterator i1, iterator i2, size_t n, char c);
  • 使用迭代器i1i2指定的范围内的字符被strn个字符c替换。

 代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str = "Hello, world! Welcome to the programming world.";

    // 替换"world"为"universe"
    size_t pos = str.find("world");
    if (pos != string::npos) 
    {
        str.replace(pos, 5, "universe");
    }
    cout << str << endl;  // 输出: Hello, universe! Welcome to the programming world.

    // 使用子串替换
    pos = str.find("programming", pos);
    if (pos != string::npos) 
    {
        str.replace(pos, 11, "coding", 4, 4); // 取"coding"的前4个字符
    }
    cout << str << endl;  // 输出: Hello, universe! Welcome to the coding world.

    // 用字符替换
    str.replace(0, 7, 5, '-');
    cout << str << endl;  // 输出: ----- universe! Welcome to the coding world.

    return 0;
}

代码结果:

string的交换

  使用swap函数完成两个string类的交换

函数原型:

void swap(string& other);

用法:

        这个函数接受一个引用到另一个std::string对象作为参数,并直接交换两个字符串的内部数据结构,包括它们的字符缓冲区。交换后,两个字符串对象将包含对方之前的字符内容,但它们的容量和其它属性(如分配的内存大小)也会相应交换。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str1 = "Hello, World!";
    string str2 = "Goodbye, World!";

    cout << "Before swapping:\nstr1 = " << str1 << "\nstr2 = " << str2 << endl;

    // 使用swap函数交换两个字符串的内容
    str1.swap(str2);

    cout << "After swapping:\nstr1 = " << str1 << "\nstr2 = " << str2 << endl;

    return 0;
}

代码结果:

string的大小和容量

  使用size函数或length函数获取当前有效字符的个数

size()函数:

  • 原型
    size_t size() const;
  • 功能:返回字符串中字符的数量。
  • 备注:作为STL容器通用接口的一部分,它符合容器类的一般使用习惯。

length()函数:

  • 原型
    size_t length() const;
  • 功能:同样返回字符串中字符的数量。
  • 备注:这个函数主要是为了兼容传统的C语言风格的字符串处理,如strlen函数,使得C++程序员在使用std::string时能有熟悉的感觉。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    // 初始化一个字符串
    string greeting = "Hello, World!";

    // 使用size()函数获取字符串长度
    cout << "The length of the string using size() is: " << greeting.size() << endl;

    // 使用length()函数获取字符串长度
    cout << "The length of the string using length() is: " << greeting.length() << endl;

    return 0;
}

代码结果:

  使用max_size函数获取string对象对多可包含的字符数

函数原型:

size_t max_size() const;

功能解释:

  • 返回值max_size函数返回size_type类型的值,表示当前系统环境下std::string对象理论上能存储的最大字符数量。size_type是一个无符号整型,足以存储任何可能的字符串长度。
  • 用途:虽然通常情况下不会达到这个极限值,但它可以用来做边界检查,比如在动态分配或调整字符串大小之前,确保操作不会超出可能的容量限制。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str;
    cout << "The maximum size of a string on this system can be: " << str.max_size() << " characters." << endl;
    return 0;
}

代码结果:

  使用capacity函数获取当前对象所分配的存储空间的大小

函数原型:

size_type capacity() const noexcept;

功能说明:

  • 返回值:返回当前字符串对象已分配的存储空间大小,以字符数量为单位。size_type是一个无符号整型,确保可以表示任何可能的容量值。
  • 目的:提供关于字符串内部存储管理的信息,帮助优化字符串操作,比如通过预先调整容量(reserve()函数)来避免自动增长导致的多次内存重分配。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str("Hello");
    cout << "Current string: \"" << str << "\"\n";
    cout << "Current capacity: " << str.capacity() << endl;

    // 添加字符直到触发自动增长
    while (str.capacity() == str.size()) 
    { // 这里仅为示例,实际上不会进入循环,因为capacity通常大于size
        str += 'a';
        cout << "Added a character. New capacity: " << str.capacity() << endl;
    }

    return 0;
}

代码结果:

  使用resize改变当前对象的有效字符的个数

 函数原型:

void resize(size_type n, char c = '\0');

参数说明:

  • n:指定新的字符串长度。如果这个值大于当前长度,则字符串会被扩展,新添加的位置会被字符c填充;如果这个值小于当前长度,则字符串会被截断到指定长度。
  • c:可选参数,默认值为\0(空字符)。当扩展字符串时,如果指定了这个参数,新增的位置将被此字符填充;如果不指定或值为默认,则默认使用空字符填充。

功能描述:

  1. 扩展字符串:如果n大于当前字符串的长度,resize函数会在字符串末尾添加足够数量的字符c,直到字符串长度达到n
  2. 缩短字符串:如果n小于当前字符串的长度,resize会直接截断字符串,从原字符串末尾移除多出的字符,直到长度为n
  3. 调整容量resize操作可能会影响到字符串的容量(即分配给字符串的内存空间),特别是当扩展字符串时,可能需要重新分配内存以容纳更多的字符。

代码演示:

#include <iostream>
#include <string>

using namespace std;

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

    // 扩展字符串并在末尾填充'a'
    str.resize(10, 'a');
    cout << "After resizing to 10 with 'a': " << str << endl; // 输出: Helloaaaaaa

    // 缩短字符串
    str.resize(3);
    cout << "After resizing to 3: " << str << endl; // 输出: Hel

    return 0;
}

代码结果:

  使用reserve改变当前对象的容量大小

 函数原型:

void reserve(size_type n);

参数说明:

  • n:指定要求的最小容量,即至少能存储n个字符的内存空间。如果n小于或等于当前的容量,则函数什么也不做。如果n大于当前的容量,那么string对象将尝试重新分配内存以满足新的容量需求。

功能描述:

  • 预防内存重分配:通过预先分配足够的内存,当后续通过插入操作增加字符串长度时,只要增加的长度不超过预留的容量,就不会发生内存重分配,从而提高了程序的效率。
  • 不改变字符串内容reserve()调用不会改变字符串的实际内容或长度,只影响其容量。
  • 内存分配策略:实现可能会根据特定的内存管理策略(如分配多于请求的内存以应对未来增长)来决定实际分配的内存大小,但这保证至少能满足n个字符的存储需求。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str;

    // 预先分配能容纳100个字符的内存空间
    str.reserve(100);

    cout << "Initial capacity: " << str.capacity() << endl; // 显示初始容量

    // 接着可以安全地执行一系列的插入操作,而不会频繁触发内存重分配
    for (int i = 0; i < 100; ++i) 
    {
        str.push_back('A' + (i % 26)); // 填充字母
    }

    cout << "After inserting characters, capacity: " << str.capacity() << endl; // 显示调整后的容量
    cout << "Size after insertions: " << str.size() << endl; // 显示实际大小

    return 0;
}

代码结果:

  使用clear删除对象的内容,删除后对象变为空字符串

函数原型:

void clear() noexcept;

功能描述:

  • 清空内容:调用clear()后,字符串中的所有字符都将被移除,字符串长度变为0。
  • 保留容量:虽然字符串变得为空,但它所占用的内存容量(即可以存储的字符数量而无需重新分配内存)通常保持不变。这意味着,再次添加字符时,直到达到原有容量之前,不会触发新的内存分配。
  • 性能优势:由于不需要重新分配内存,对于频繁需要清空并重新填充内容的场景,使用clear()比反复创建新的字符串对象更为高效。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str = "Hello, World!";

    cout << "Before clear: \"" << str << "\", Size: " << str.size() << ", Capacity: " << str.capacity() << endl;

    str.clear();

    cout << "After clear: \"" << str << "\", Size: " << str.size() << ", Capacity: " << str.capacity() << endl;

    return 0;
}

 代码结果:

  使用empty判断对象是否为空

函数原型:

bool empty() const noexcept;

功能描述:

  • 检查字符串状态empty()函数不接受任何参数,它检查调用该函数的字符串对象是否为空。
  • 返回值:如果字符串长度为0,表示字符串为空,则返回true;如果字符串包含至少一个字符,则返回false
  • 常量成员函数:由于它被声明为const,这意味着它不会修改字符串对象的状态,只读取信息。

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str1 = "";
    string str2 = "Hello";

    if (str1.empty()) 
    {
        cout << "str1 is empty." << endl;
    }
    else 
    {
        cout << "str1 is not empty." << endl;
    }

    if (str2.empty()) 
    {
        cout << "str2 is empty." << endl;
    }
    else 
    {
        cout << "str2 is not empty." << endl;
    }

    return 0;
}

代码结果:

string中元素的访问

  [ ]+下标

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main() 
{
    string str = "Hello, World!";

    // 访问第一个字符
    char firstChar = str[0];
    cout << "First character: " << firstChar << endl; // 输出 H

    // 访问最后一个字符
    char lastChar = str[str.size() - 1];
    cout << "Last character: " << lastChar << endl; // 输出 !
}

代码结果:

  使用at访问对象中的元素

代码演示:

#include <iostream>
#include <string>
#include <stdexcept> // 引入此头文件以处理std::out_of_range异常

int main() 
{
    try {
        std::string str = "Hello, World!";

        // 安全地访问第一个字符
        char firstChar = str.at(0);
        std::cout << "First character: " << firstChar << std::endl; // 输出 H

        // 尝试访问超出范围的字符,这将抛出异常
        char invalidAccess = str.at(20); // 假设字符串没有这么长
        std::cout << "Invalid access character: " << invalidAccess << std::endl;
    }
    catch (const std::out_of_range& e) 
    {
        std::cerr << "Caught an out_of_range exception: " << e.what() << std::endl;
    }

    return 0;
}

代码结果:

  使用范围for访问对象中的元素

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";

    // 使用范围for循环遍历字符串中的每个字符
    for (char ch : str) 
    {
        std::cout << ch << std::endl; // 分别打印每个字符
    }

    // 或者,如果你想在一行中打印整个字符串,不换行
    std::cout << "Printing the string in one line: ";
    for (char ch : str) 
    {
        std::cout << ch;
    }
    std::cout << std::endl; // 在所有字符打印完成后换行

    return 0;
}

代码结果:

 

  使用迭代器访问对象中的元素

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";

    // 使用迭代器遍历字符串
    for (std::string::iterator it = str.begin(); it != str.end(); ++it) 
    {
        std::cout << *it << std::endl; // 打印每个字符
    }

    // 使用const_iterator进行只读遍历
    for (std::string::const_iterator cit = str.cbegin(); cit != str.cend(); ++cit) 
    {
        std::cout << *cit; // 同样打印每个字符,但明确表示不修改
    }
    std::cout << std::endl; // 在所有字符打印完成后换行

    return 0;
}

代码结果:

string中运算符的使用

  operator=

 代码演示:

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s1;
	string s2("CSDN");

	//支持string类的赋值
	s1 = s2;
	cout << s1 << endl; //CSDN

	//支持字符串的赋值
	s1 = "hello";
	cout << s1 << endl;  //hello

	//支持字符的赋值
	s1 = 'x';
	cout << s1 << endl; //x

	return 0;
}

代码结果:

 

  operator+=

 代码演示:

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s1;
	string s2("hello");

	//支持string类的复合赋值
	s1 += s2;
	cout << s1 << endl; //hello

	//支持字符串的复合赋值
	s1 += " CSDN";
	cout << s1 << endl; //hello CSDN

	//支持字符的复合赋值
	s1 += '!';
	cout << s1 << endl; //hello CSDN!

	return 0;
}

代码结果:

  operator+

基本用法:

  • 字符串与字符串相加
  • 字符串与C风格字符串相加
  • 字符串与字符相加

代码演示:

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s;
	string s1("super");
	string s2("man");
	char str[] = "woman";
	char ch = '!';

	//string类 + string类
	s = s1 + s2;
	cout << s << endl; //superman

	//string类 + 字符串
	s = s1 + str;
	cout << s << endl; //superwoman

	//字符串 + string类
	s = str + s1;
	cout << s << endl; //womansuper

	//string类 + 字符
	s = s1 + ch;
	cout << s << endl; //super!
	
	//字符 + string类
	s = ch + s1;
	cout << s << endl; //!super

	return 0;
}

代码结果:

  operator>> 和 operator<<

 operator<< (插入运算符):

  • 功能: 该运算符用于将数据插入到输出流中。最常见的用途是在std::cout上,用于打印变量的值或者字符串到控制台或其他输出设备。

  • 语法::std::cout << expression1 << expression2 ...;

  • 示例

    int age = 25;
    std::string name = "Alice";
    std::cout << "Name: " << name << ", Age: " << age << std::endl;

        上述代码会输出: Name: Alice, Age: 25

operator>>() (提取运算符):

  • 功能::该运算符用于从输入流中提取(读取)数据到变量中。最常用的输入流是std::cin,它通常用于接收用户键盘输入。

  • 语法::std::cin >> variable1 >> variable2 ...;

  • 示例

    int number;
    std::string inputText;
    std::cout << "Enter an integer: ";
    std::cin >> number;
    std::cout << "Enter some text: ";
    std::cin >> inputText;

        在上述代码中,程序首先提示用户输入一个整数,然后输入一段文本。

 

  relational operators

  1. 等于 (==)

    • 功能:检查两个字符串是否相等,即它们的字符序列完全相同。
    • 示例
      if (str1 == str2) { /* 字符串str1和str2相等 */ }
  2. 不等于 (!=)

    • 功能:检查两个字符串是否不相等。
    • 示例
      if (str1 != str2) { /* 字符串str1和str2不相等 */ }
  3. 小于 (<)

    • 功能:按照字典顺序,检查左边的字符串是否在右边的字符串之前。
    • 示例
      if (str1 < str2) { /* 字符串str1在str2之前 */ }
  4. 大于 (>)

    • 功能:按照字典顺序,检查左边的字符串是否在右边的字符串之后。
    • 示例
      if (str1 > str2) { /* 字符串str1在str2之后 */ }
  5. 小于等于 (<=)

    • 功能:检查左边的字符串是否在右边的字符串之前或与之相等。
    • 示例
      if (str1 <= str2) { /* 字符串str1在str2之前或与之相等 */ }
  6. 大于等于 (>=)

    • 功能:检查左边的字符串是否在右边的字符串之后或与之相等。
    • 示例
      if (str1 >= str2) { /* 字符串str1在str2之后或与之相等 */ }

注意:这些运算符在比较字符串时,按照字符的ASCII(或Unicode)值逐个进行比较,首先是第一个字符,如果相同则继续比较下一个,直到找到不匹配的字符或一个字符串结束。 

string中与迭代器相关的函数

  与正向迭代器相关的函数

        begin函数

函数原型:

iterator begin();
const_iterator begin() const;

功能说明:

  • 非const版本begin()返回一个迭代器,指向字符串的第一个字符。这个迭代器是可修改的,意味着你可以通过它来修改字符串的内容。

  • const版本:在const上下文中(比如字符串为const std::string类型或者被const引用或指针引用),begin()返回一个const_iterator,它只能用于读取字符串内容,不能修改。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";

    // 遍历字符串
    for (auto it = str.begin(); it != str.end(); ++it) 
    {
        std::cout << *it; // 输出字符串中的每个字符
    }
    std::cout << std::endl;

    // 在const上下文中的使用
    const std::string constStr = "Example";
    for (auto cit = constStr.begin(); cit != constStr.end(); ++cit) 
    {
        std::cout << *cit; // 输出: Example
    }
    std::cout << std::endl;

    return 0;
}

代码结果:

        end函数

 函数原型:

iterator end(); 
const_iterator end() const;

功能说明:

  • 非const版本:返回一个迭代器,指向字符串的末端,可以用来检测遍历是否结束,但不应解引用此迭代器访问实际的字符。

  • const版本:在const上下文中,end()返回一个const_iterator,同样指向字符串末端,用于只读操作。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";

    // 遍历字符串
    for (auto it = str.begin(); it != str.end(); ++it) 
    {
        std::cout << *it; // 输出字符串中的每个字符
    }
    std::cout << std::endl;

    // 在const上下文中的使用
    const std::string constStr = "Example";
    for (auto cit = constStr.begin(); cit != constStr.end(); ++cit) 
    {
        std::cout << *cit; // 输出: Example
    }
    std::cout << std::endl;

    return 0;
}

代码结果:

  与反向迭代器相关的函数

        rbegin函数

函数原型:

reverse_iterator rbegin(); 
const_reverse_iterator rbegin() const;

功能说明:

  • 非const版本:返回一个反向迭代器,初始时指向字符串的最后一个字符。这个迭代器允许你从字符串的末尾向前遍历。

  • const版本:在const上下文中,rbegin()返回一个const_reverse_iterator,同样指向字符串的最后一个字符,但不允许修改字符串内容。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";

    // 反向遍历字符串
    for (auto rit = str.rbegin(); rit != str.rend(); ++rit) 
    {
        std::cout << *rit; // 逆序输出字符串中的每个字符
    }
    std::cout << std::endl;

    // 在const上下文中的使用
    const std::string constStr = "Example";
    for (auto crit = constStr.rbegin(); crit != constStr.rend(); ++crit) 
    {
        std::cout << *crit; // 逆序输出: !dlroW ,olleH
    }
    std::cout << std::endl;

    return 0;
}

代码结果:

        rend函数

函数原型:

reverse_iterator rend(); 
const_reverse_iterator rend() const;

功能说明:

  • 非const版本:返回一个反向迭代器,逻辑上位于字符串的开始位置之前,用于标识反向遍历的终点。

  • const版本:在const上下文中,rend()返回一个const_reverse_iterator,同样位于开始位置之前,确保遍历时不可修改字符串。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";

    // 反向遍历字符串
    for(auto rit = str.rbegin(); rit != str.rend(); ++rit) 
    {
        std::cout << *rit; // 逆序输出字符串中的每个字符,直到遇到rend()
    }
    std::cout << std::endl;

    // 在const上下文中的使用
    const std::string constStr = "Example";
    for(auto crit = constStr.rbegin(); crit != constStr.rend(); ++crit) 
    {
        std::cout << *crit; // 类似地,逆序输出: !elpmaxE
    }
    std::cout << std::endl;

    return 0;
}

代码结果:

string与字符串之间的转换

  将字符串转换为string

#include <iostream>
#include <string>

using namespace std;

int main()
{
	//方式一
	string s1("hello world");

	//方式二
	char str[] = "hello world";
	string s2(str);

	cout << s1 << endl; //hello world
	cout << s2 << endl; //hello world

	return 0;
}

  使用c_str或data将string转换为字符串

c_str():

  • 功能c_str()方法返回一个指向常量字符数组的指针,这个字符数组包含了std::string对象的内容,末尾带有空字符\0。这意味着返回的指针指向的数据是不可修改的。
  • 适用场景:当你需要将std::string传递给要求C字符串的API或者C库函数时(例如printf),应使用c_str()。因为这些函数期望字符串以\0结尾,并且通常假设字符串是不可变的。

data():

  • 功能data()方法同样返回一个指向字符数组的指针,该数组包含了字符串的内容,但直到C++11标准,data()返回的指针是否以\0结尾并未明确规定。从C++11开始,data()保证了当字符串不是空字符串时,返回的指针指向的数组末尾也会有\0。不过,与c_str()不同的是,如果std::string对象是可变的,通过data()获得的指针指向的数据可能是可修改的。
  • 适用场景:当你只需要读取字符串内容而不需要确保字符串不可变,或者需要传递给接受const char*但不修改其内容的函数时,可以使用data()。但在将字符串传递给可能修改其内容的C函数之前,应当谨慎,最好使用c_str()或确保std::string对象本身不可变。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string str = "Hello, World!";
    
    // 使用c_str()方法
    const char* cStr = str.c_str();
    std::cout << "Using c_str(): " << cStr << std::endl;

    // 使用data()方法
    const char* pData = str.data();
    std::cout << "Using data(): " << pData << std::endl;

    return 0;
}

代码结果:

string中子字符串的提取

  使用substr函数提取string中的子字符串

函数原型:

std::string substr(size_type pos = 0, size_type n = npos) const;

参数说明:

  • pos:子字符串开始提取的位置索引,默认为0,即字符串的起始位置。
  • n:要提取的字符数量。如果省略或设置为nposstd::string::npos表示最大可能值,通常用作结束标志),则提取从pos开始到字符串结束的所有字符。

返回值:

        返回一个新的std::string对象,包含从原字符串中提取的子字符串。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string originalString = "Hello, World!";
    
    // 提取从位置3开始的5个字符
    std::string subStr1 = originalString.substr(3, 5);
    std::cout << "Substring 1: " << subStr1 << std::endl; // 输出: lo, W
    
    // 提取从位置7到字符串结束的子字符串
    std::string subStr2 = originalString.substr(7);
    std::cout << "Substring 2: " << subStr2 << std::endl; // 输出: World!
    
    // 提取整个字符串(等效于pos=0, n=npos)
    std::string subStr3 = originalString.substr();
    std::cout << "Substring 3: " << subStr3 << std::endl; // 输出: Hello, World!
    
    return 0;
}

代码结果:

  使用copy函数将string的子字符串复制到字符数组中 

 代码演示:

#include <iostream>
#include <string>
#include <algorithm> // 包含std::copy
#include <iterator>  // 包含std::begin, std::end

int main() 
{
    std::string str = "Hello, World!";
    char charArray[10]; // 目标字符数组

    // 使用substr获取子字符串
    std::string subStr = str.substr(0, 5); // 获取前5个字符 "Hello"

    // 使用std::copy将子字符串复制到字符数组
    std::copy(subStr.begin(), subStr.end(), charArray);

    // 确保字符串末尾加上空字符
    charArray[subStr.size()] = '\0';

    std::cout << "Copied substring: " << charArray << std::endl;

    return 0;
}

代码结果:

string中的getline函数

函数原型:

std::istream& getline(std::istream& is, std::string& str, char delim = '\n');

参数说明:

  • is:输入流对象,通常为std::cin,但也可以是其他输入流对象,如文件流std::ifstream
  • strstd::string对象的引用,用于存储读取到的行内容。
  • delim:可选参数,指定的分隔符,默认为\n(换行符)。读取会停止于该分隔符,但分隔符本身不会被存储在字符串中。

代码演示:

#include <iostream>
#include <string>

int main() 
{
    std::string userInput;

    std::cout << "请输入一行文本: ";
    // 读取整行文本直到遇到换行符
    std::getline(std::cin, userInput);
    std::cout << "你输入的是: " << userInput << std::endl;

    // 另一个例子,使用自定义分隔符
    std::cout << "使用自定义分隔符读取(以#结束): ";
    std::getline(std::cin, userInput, '#');
    std::cout << "你输入的是: " << userInput << std::endl;

    return 0;
}

代码演示:

  • 56
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值