当前位置:首页 » 《随便一记》 » 正文

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

22 人参与  2024年05月26日 14:06  分类 : 《随便一记》  评论

点击全文阅读


目录

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(空字符)。当扩展字符串时,如果指定了这个参数,新增的位置将被此字符填充;如果不指定或值为默认,则默认使用空字符填充。

功能描述:

扩展字符串:如果n大于当前字符串的长度,resize函数会在字符串末尾添加足够数量的字符c,直到字符串长度达到n缩短字符串:如果n小于当前字符串的长度,resize会直接截断字符串,从原字符串末尾移除多出的字符,直到长度为n调整容量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; //xreturn 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; //!superreturn 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

等于 (==)

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

不等于 (!=)

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

小于 (<)

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

大于 (>)

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

小于等于 (<=)

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

大于等于 (>=)

功能:检查左边的字符串是否在右边的字符串之后或与之相等。示例
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 worldcout << s2 << endl; //hello worldreturn 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::endint 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::ifstreamstrstd::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;}

代码演示:


点击全文阅读


本文链接:http://zhangshiyu.com/post/113865.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1