【掌握C++ string 类】——【高效字符串操作】的【现代编程艺术】

CSDN 2024-08-04 16:35:01 阅读 55

专栏:C++学习笔记 

上一篇:【C++】——【 STL简介】——【详细讲解】

1. 为什么要学习 <code>string 类?

1.1 C 语言中的字符串

在 C 语言中,字符串是以 '\0' 结尾的字符集合。如下所示:

#include <stdio.h>

int main() {

char str[] = "Hello, World!";

printf("%s\n", str);

return 0;

}

需要记住的知识点:

C 风格字符串是以 <code>'\0' 结尾的字符数组。使用 char 类型数组表示字符串。C 库提供的字符串操作函数与字符串本身是分离的。

小李的理解: C 语言中的字符串处理很基础,使用字符数组来存储,但需要手动管理内存,很容易出错。

1.2 两个面试题

字符串转整形数字

题目描述:将字符串表示的数字转换为整形数字,例如将 "12345" 转换为 12345

实现方法:可以使用 std::stoi 函数将字符串转换为整形数字。

示例代码

#include <iostream>

#include <string>

int main() {

std::string str = "12345";

try {

int num = std::stoi(str); // 将字符串转换为整形数字

std::cout << "字符串 \"" << str << "\" 转换为整形数字: " << num << std::endl;

} catch (const std::invalid_argument& e) {

std::cout << "无效的输入: " << str << std::endl;

} catch (const std::out_of_range& e) {

std::cout << "输入超出范围: " << str << std::endl;

}

return 0;

}

 

需要记住的知识点

使用 <code>std::stoi 函数将字符串转换为整形数字。std::stoi 在转换失败时会抛出异常,可以根据需要进行异常处理。

小李的理解

使用 std::stoi 函数非常方便,可以直接将表示数字的字符串转换为整形数字。这在处理用户输入或文件读取的数据时非常有用。

字符串相加

题目描述:将两个字符串拼接成一个字符串,例如将 "Hello, ""World!" 拼接成 "Hello, World!"

实现方法:可以使用 + 运算符或者 append 方法将两个字符串拼接。

示例代码

#include <iostream>

#include <string>

int main() {

std::string str1 = "Hello, ";

std::string str2 = "World!";

// 方法1:使用 + 运算符拼接

std::string result1 = str1 + str2;

std::cout << "使用 + 运算符拼接: " << result1 << std::endl;

// 方法2:使用 append 方法拼接

std::string result2 = str1;

result2.append(str2);

std::cout << "使用 append 方法拼接: " << result2 << std::endl;

return 0;

}

需要记住的知识点

使用 <code>+ 运算符可以方便地将两个字符串拼接。使用 append 方法也可以实现字符串拼接,适用于更复杂的字符串操作。

小李的理解

C++ 中提供了多种字符串拼接方法,+ 运算符简单直观,适合拼接固定数量的字符串。append 方法则适合在循环或更复杂的逻辑中使用。

详细运行结果分析

字符串转整形数字

#include <iostream>

#include <string>

int main() {

std::string str = "12345";

try {

int num = std::stoi(str); // 将字符串转换为整形数字

std::cout << "字符串 \"" << str << "\" 转换为整形数字: " << num << std::endl;

} catch (const std::invalid_argument& e) {

std::cout << "无效的输入: " << str << std::endl;

} catch (const std::out_of_range& e) {

std::cout << "输入超出范围: " << str << std::endl;

}

return 0;

}

异常处理

<code>std::invalid_argument:如果输入的字符串不是一个有效的整数,则会抛出此异常。std::out_of_range:如果输入的字符串表示的整数超出了整形数字的范围,则会抛出此异常。

需要注意的地方std::stoi 在处理非常大的数字时,可能会抛出 std::out_of_range 异常。

补充代码:处理无效输入和超出范围的情况

#include <iostream>

#include <string>

int main() {

std::string str1 = "12345";

std::string str2 = "12345abc";

std::string str3 = "99999999999999999999999999";

try {

int num1 = std::stoi(str1); // 正确转换

std::cout << "字符串 \"" << str1 << "\" 转换为整形数字: " << num1 << std::endl;

} catch (const std::invalid_argument& e) {

std::cout << "无效的输入: " << str1 << std::endl;

} catch (const std::out_of_range& e) {

std::cout << "输入超出范围: " << str1 << std::endl;

}

try {

int num2 = std::stoi(str2); // 转换失败

std::cout << "字符串 \"" << str2 << "\" 转换为整形数字: " << num2 << std::endl;

} catch (const std::invalid_argument& e) {

std::cout << "无效的输入: " << str2 << std::endl;

} catch (const std::out_of_range& e) {

std::cout << "输入超出范围: " << str2 << std::endl;

}

try {

int num3 = std::stoi(str3); // 转换失败

std::cout << "字符串 \"" << str3 << "\" 转换为整形数字: " << num3 << std::endl;

} catch (const std::invalid_argument& e) {

std::cout << "无效的输入: " << str3 << std::endl;

} catch (const std::out_of_range& e) {

std::cout << "输入超出范围: " << str3 << std::endl;

}

return 0;

}

 

字符串相加

<code>#include <iostream>

#include <string>

int main() {

std::string str1 = "Hello, ";

std::string str2 = "World!";

// 方法1:使用 + 运算符拼接

std::string result1 = str1 + str2;

std::cout << "使用 + 运算符拼接: " << result1 << std::endl;

// 方法2:使用 append 方法拼接

std::string result2 = str1;

result2.append(str2);

std::cout << "使用 append 方法拼接: " << result2 << std::endl;

return 0;

}

细节分析

使用 <code>+ 运算符拼接时,会生成一个新的字符串对象。使用 append 方法拼接时,会在原有字符串对象上进行修改,适合在需要多次拼接的情况下使用以减少不必要的对象创建。

补充代码:使用多次拼接的情况

#include <iostream>

#include <string>

int main() {

std::string str1 = "Hello, ";

std::string str2 = "World!";

std::string str3 = " How are you?";

// 多次使用 + 运算符拼接

std::string result1 = str1 + str2 + str3;

std::cout << "多次使用 + 运算符拼接: " << result1 << std::endl;

// 多次使用 append 方法拼接

std::string result2 = str1;

result2.append(str2).append(str3);

std::cout << "多次使用 append 方法拼接: " << result2 << std::endl;

return 0;

}

 

通过这些详细的代码示例和运行结果分析,相信你能更好地理解如何在 C++ 中进行字符串转整形数字和字符串相加操作,并在实际应用中灵活使用这些方法。

2. 标准库中的 <code>string 类

2.1 string 类的基本介绍

文档介绍

string 是一个表示字符序列的类。string 类提供了丰富的接口,类似于标准容器(如 vector),但还添加了专门用于操作单字节字符字符串的设计特性。stringbasic_string 模板类的一个实例,使用 charchar_traitsallocator 作为模板参数。string 类独立于编码处理字节。

需要记住的知识点

string 类表示字符序列。提供类似于标准容器的接口。string 实际上是 basic_string<char, char_traits, allocator> 的实例。

小李的理解string 类封装了字符串操作,提供了很多方便的函数,不需要我们手动管理内存。

示例代码

#include <iostream>

#include <string>

int main() {

std::string str = "Hello, World!";

std::cout << str << std::endl;

return 0;

}

2.2 <code>string 类的常用接口

构造函数

string():构造一个空的 string 对象。

#include <iostream>

#include <string>

int main() {

std::string s;

std::cout << "Empty string: '" << s << "'" << std::endl;

return 0;

}

 <code>string(const char* s):用 C 风格字符串构造 string 对象。

#include <iostream>

#include <string>

int main() {

std::string s("Hello, World!");

std::cout << s << std::endl;

return 0;

}

<code>string(size_t n, char c):构造一个包含 n 个字符 cstring 对象。 

#include <iostream>

#include <string>

int main() {

std::string s(10, 'a');

std::cout << s << std::endl;

return 0;

}

<code>string(const string& s):拷贝构造函数,用另一个 string 对象构造新对象。

#include <iostream>

#include <string>

int main() {

std::string s1 = "Hello";

std::string s2(s1);

std::cout << s2 << std::endl;

return 0;

}

 

容量操作

<code>size() / length():返回字符串的有效字符长度。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

std::cout << "Size: " << s.size() << std::endl;

std::cout << "Length: " << s.length() << std::endl;

return 0;

}

<code>capacity():返回字符串的总容量。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

std::cout << "Capacity: " << s.capacity() << std::endl;

return 0;

}

 <code>empty():检测字符串是否为空,空则返回 true,否则返回 false

#include <iostream>

#include <string>

int main() {

std::string s;

if (s.empty()) {

std::cout << "String is empty" << std::endl;

}

return 0;

}

<code>clear():清空字符串中的有效字符。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

s.clear();

std::cout << "String after clear: '" << s << "'" << std::endl;

return 0;

}

<code>reserve(size_t res_arg=0):为字符串预留空间,不改变有效字符个数。

#include <iostream>

#include <string>

int main() {

std::string s;

s.reserve(100);

std::cout << "Reserved capacity: " << s.capacity() << std::endl;

return 0;

}

<code>resize(size_t n) / resize(size_t n, char c):将有效字符个数改为 n,多出的空间用字符 c 填充。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

s.resize(10, 'x');

std::cout << "Resized string: " << s << std::endl;

return 0;

}

访问及遍历操作

<code>operator[]:返回指定位置的字符。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

std::cout << "Character at index 1: " << s[1] << std::endl;

return 0;

}

<code>begin() / end():返回字符串的起始迭代器和结束迭代器。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

for (auto it = s.begin(); it != s.end(); ++it) {

std::cout << *it << ' ';

}

std::cout << std::endl;

return 0;

}

 <code>rbegin() / rend():返回反向迭代器。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

for (auto it = s.rbegin(); it != s.rend(); ++it) {

std::cout << *it << ' ';

}

std::cout << std::endl;

return 0;

}

 范围 <code>for 循环:C++11 引入的简洁遍历方式。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

for (char c : s) {

std::cout << c << ' ';

}

std::cout << std::endl;

return 0;

}

修改操作

1.push_back(char c):在字符串末尾添加字符 c

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

s.push_back('!');

std::cout << s << std::endl;

return 0;

}

<code>2.append(const string& str):在字符串末尾追加字符串 str。 

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

s.append(" World");

std::cout << s << std::endl;

return 0;

}

<code>3.operator+=:在字符串末尾追加字符串。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

s += " World";

std::cout << s << std::endl;

return 0;

}

 

<code>4.c_str():返回 C 风格字符串。

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

const char* c_str = s.c_str();

std::cout << c_str << std::endl;

return 0;

}

 

<code>5.find(char c, size_t pos=0):从指定位置开始查找字符 c

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

size_t pos = s.find('l');

if (pos != std::string::npos) {

std::cout << "Character 'l' found at position: " << pos << std::endl;

} else {

std::cout << "Character not found" << std::endl;

}

return 0;

}

 

<code>6.rfind(char c, size_t pos=npos):从指定位置开始反向查找字符 c

#include <iostream>

#include <string>

int main() {

std::string s = "Hello";

size_t pos = s.rfind('l');

if (pos != std::string::npos) {

std::cout << "Character 'l' found at position: " << pos << std::endl;

} else {

std::cout << "Character not found" << std::endl;

}

return 0;

}

 

<code>7.substr(size_t pos=0, size_t n=npos):返回从指定位置开始的子字符串。 

#include <iostream>

#include <string>

int main() {

std::string s = "Hello, World!";

std::string sub = s.substr(7, 5); // 从第7个位置开始,取5个字符

std::cout << "Substring: " << sub << std::endl;

return 0;

}

非成员函数

<code>1.operator+:字符串拼接。

#include <iostream>

#include <string>

int main() {

std::string s1 = "Hello";

std::string s2 = " World";

std::string s3 = s1 + s2;

std::cout << s3 << std::endl;

return 0;

}

 

<code>2.operator>>:输入运算符重载。 

#include <iostream>

#include <string>

int main() {

std::string s;

std::cout << "Enter a string: ";

std::cin >> s; // 从输入读取字符串,遇到空格结束

std::cout << "You entered: " << s << std::endl;

return 0;

}

<code>3.operator<<:输出运算符重载。 

#include <iostream>

#include <string>

int main() {

std::string s = "Hello, World!";

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

return 0;

}

<code>4.getline:读取一行字符串。 

#include <iostream>

#include <string>

int main() {

std::string line;

std::cout << "Enter a line of text: ";

std::getline(std::cin, line); // 从输入读取一行字符串

std::cout << "You entered: " << line << std::endl;

return 0;

}

5.关系运算符:字符串比较。 

<code>#include <iostream>

#include <string>

int main() {

std::string s1 = "Hello";

std::string s2 = "World";

if (s1 < s2) {

std::cout << s1 << " is less than " << s2 << std::endl;

} else {

std::cout << s1 << " is not less than " << s2 << std::endl;

}

return 0;

}

3. 扩展阅读

需要记住的知识点

<code>string 类是 basic_string 模板类的实例。提供丰富的接口,简化字符串操作。内存管理由 string 类自动处理,避免了手动管理内存的复杂性和风险。

小李的理解string 类让字符串操作变得简单而安全。通过理解 string 类的各种接口和功能,可以更高效地编写 C++ 程序。

示例代码

找字符串中第一个只出现一次的字符

#include <iostream>

#include <string>

class Solution {

public:

int firstUniqChar(const std::string& s) {

int count[256] = {0};

for (char c : s) {

count[c]++;

}

for (size_t i = 0; i < s.size(); ++i) {

if (count[s[i]] == 1) {

return i;

}

}

return -1;

}

};

int main() {

Solution solution;

std::string s = "leetcode";

int index = solution.firstUniqChar(s);

if (index != -1) {

std::cout << "The first unique character is at index: " << index << std::endl;

} else {

std::cout << "No unique character found" << std::endl;

}

return 0;

}

 

验证一个字符串是否是回文 

<code>#include <iostream>

#include <string>

#include <algorithm>

class Solution {

public:

bool isPalindrome(const std::string& s) {

std::string filtered;

for (char c : s) {

if (isalnum(c)) {

filtered += tolower(c);

}

}

std::string reversed = filtered;

std::reverse(reversed.begin(), reversed.end());

return filtered == reversed;

}

};

int main() {

Solution solution;

std::string s = "A man, a plan, a canal: Panama";

bool result = solution.isPalindrome(s);

if (result) {

std::cout << "\"" << s << "\" is a palindrome" << std::endl;

} else {

std::cout << "\"" << s << "\" is not a palindrome" << std::endl;

}

return 0;

}

总结 

1. 为什么要学习 <code>string 类?

C 语言中的字符串

C 风格字符串是以 '\0' 结尾的字符数组,使用 char 类型数组表示。C 库提供的字符串操作函数与字符串本身是分离的,需要手动管理内存,容易出错。

字符串转整形数字

使用 std::stoi 函数可以方便地将字符串转换为整形数字。std::stoi 在转换失败时会抛出异常,可以进行异常处理。

字符串相加

使用 + 运算符和 append 方法可以轻松实现字符串拼接。+ 运算符适合拼接固定数量的字符串,append 方法适合在循环或复杂逻辑中使用。

2. 标准库中的 string

基本介绍

string 类表示字符序列,提供类似于标准容器的接口。string 实际上是 basic_string<char, char_traits, allocator> 的实例,封装了字符串操作,提供方便的函数和自动内存管理。

常用接口

构造函数

string():构造一个空的 string 对象。string(const char* s):用 C 风格字符串构造 string 对象。string(size_t n, char c):构造一个包含 n 个字符 cstring 对象。string(const string& s):拷贝构造函数,用另一个 string 对象构造新对象。

容量操作

size() / length():返回字符串的有效字符长度。capacity():返回字符串的总容量。empty():检测字符串是否为空。clear():清空字符串中的有效字符。reserve(size_t res_arg=0):为字符串预留空间。resize(size_t n) / resize(size_t n, char c):将有效字符个数改为 n,多出的空间用字符 c 填充。

访问及遍历操作

operator[]:返回指定位置的字符。begin() / end():返回字符串的起始迭代器和结束迭代器。rbegin() / rend():返回反向迭代器。范围 for 循环:C++11 引入的简洁遍历方式。

修改操作

push_back(char c):在字符串末尾添加字符 cappend(const string& str):在字符串末尾追加字符串 stroperator+=:在字符串末尾追加字符串。c_str():返回 C 风格字符串。find(char c, size_t pos=0):从指定位置开始查找字符 crfind(char c, size_t pos=npos):从指定位置开始反向查找字符 csubstr(size_t pos=0, size_t n=npos):返回从指定位置开始的子字符串。

非成员函数

operator+:字符串拼接。operator>>:输入运算符重载。operator<<:输出运算符重载。getline:读取一行字符串。关系运算符:字符串比较。

3. 扩展阅读

string 类是 basic_string 模板类的实例,提供丰富的接口,简化字符串操作。内存管理由 string 类自动处理,避免了手动管理内存的复杂性和风险。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。