C++ 字符串与字符数组的 10 种转换方法:从入门到精通
1. std::string 转 const char* (最常用)
2. std::string 转 char* (需要谨慎)
3. const char* 转 std::string (最常用)
4. char* 转 std::string (也常用)
5. 字符数组转 std::string (利用构造函数)
6. 字符串拼接:std::string 和 const char* (简单)
7. 字符串拼接:std::string 和 char* (也简单)
8. 使用 std::stringstream 进行转换 (灵活)
9. 使用 std::copy 进行字符数组拷贝 (底层)
10. 使用 assign 方法进行字符数组赋值 (灵活)
总结
你好,我是老王。在 C++ 编程中,字符串 (string) 和字符数组 (char array) 的转换是经常遇到的问题。虽然 C++ 标准库提供了 std::string
类,简化了字符串的处理,但在某些场景下,我们仍然需要与 C 风格的字符数组交互。比如,调用 C 语言编写的 API,或者需要更底层的内存控制。所以,熟练掌握字符串和字符数组之间的转换方法,对每个 C++ 程序员来说都至关重要。
本文将详细介绍 10 种常见的转换方法,涵盖从初学者到进阶者的各种需求。我会尽量用通俗易懂的语言,结合实际的代码示例,让你能够轻松掌握这些技巧。 让我们一起开始吧!
1. std::string
转 const char*
(最常用)
这是最常见的转换方式。std::string
提供了 c_str()
和 data()
两个成员函数,可以将字符串转换为 C 风格的 const char*
。
c_str()
: 返回一个指向以空字符结尾的字符数组的指针。通常用于需要 C 风格字符串作为输入的情况。data()
: 返回一个指向字符数组的指针,不保证以空字符结尾。如果需要保证字符串以空字符结尾,请手动添加。
#include <iostream> #include <string> int main() { std::string str = "Hello, world!"; // 使用 c_str() const char* cstr1 = str.c_str(); std::cout << "cstr1: " << cstr1 << std::endl; // 输出: cstr1: Hello, world! // 使用 data() const char* cstr2 = str.data(); std::cout << "cstr2: " << cstr2 << std::endl; // 输出: cstr2: Hello, world! return 0; }
注意: c_str()
和 data()
返回的指针指向的内存由 std::string
管理,不要试图修改该内存,也不要在 std::string
对象被销毁后使用这些指针。
2. std::string
转 char*
(需要谨慎)
将 std::string
转换为 char*
需要特别小心,因为这涉及到对字符串内容的修改。通常情况下,不推荐直接将 std::string
转换为 char*
,除非你非常清楚自己在做什么。
方法一:使用 strcpy
或 memcpy
复制字符串
这种方法创建了一个新的字符数组,并将 std::string
的内容复制到该数组中。
#include <iostream> #include <string> #include <cstring> // 或者 <string.h> int main() { std::string str = "Hello, world!"; size_t len = str.length(); // 分配足够的空间,包括空字符 char* cstr = new char[len + 1]; // 使用 strcpy strcpy(cstr, str.c_str()); // 或者使用 memcpy // memcpy(cstr, str.c_str(), len + 1); std::cout << "cstr: " << cstr << std::endl; // 输出: cstr: Hello, world! // 修改 cstr cstr[0] = 'h'; std::cout << "cstr: " << cstr << std::endl; // 输出: cstr: hello, world! delete[] cstr; // 释放内存 cstr = nullptr; return 0; }
注意:
- 需要手动分配足够的内存。
- 需要手动释放内存,防止内存泄漏。
strcpy
存在安全隐患,可能导致缓冲区溢出。建议使用strncpy
或memcpy
,并确保目标缓冲区足够大。
方法二:使用 &str[0]
(不推荐)
std::string
内部通常使用一个 char
数组来存储字符串数据。理论上,你可以通过 &str[0]
获取指向该数组的指针。
#include <iostream> #include <string> int main() { std::string str = "Hello, world!"; // 获取指向内部字符数组的指针 (不推荐) char* cstr = &str[0]; std::cout << "cstr: " << cstr << std::endl; // 输出: cstr: Hello, world! // 修改 cstr cstr[0] = 'h'; std::cout << "str: " << str << std::endl; // 输出: str: hello, world! return 0; }
警告:
- 这种方法依赖于
std::string
的内部实现,不保证在所有编译器或标准库版本中都有效。 std::string
可能会在内部重新分配内存,导致&str[0]
指针失效。- 不推荐在 Release 版本中使用。
3. const char*
转 std::string
(最常用)
这是将 C 风格字符串转换为 std::string
的最简单方法。 std::string
的构造函数接受 const char*
作为参数。
#include <iostream> #include <string> int main() { const char* cstr = "Hello, world!"; std::string str(cstr); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
4. char*
转 std::string
(也常用)
与 const char*
类似,std::string
的构造函数也接受 char*
作为参数。
#include <iostream> #include <string> int main() { char cstr[] = "Hello, world!"; std::string str(cstr); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
5. 字符数组转 std::string
(利用构造函数)
除了直接使用 char*
,你还可以使用字符数组的起始地址和长度来构造 std::string
。
#include <iostream> #include <string> int main() { char carr[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0' }; size_t len = sizeof(carr) / sizeof(carr[0]) - 1; // 减去空字符 std::string str(carr, len); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
6. 字符串拼接:std::string
和 const char*
(简单)
std::string
提供了 +=
运算符,可以方便地将 const char*
拼接到字符串的末尾。
#include <iostream> #include <string> int main() { std::string str = "Hello"; const char* cstr = ", world!"; str += cstr; std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
7. 字符串拼接:std::string
和 char*
(也简单)
与 const char*
类似,+=
运算符也支持将 char*
拼接到字符串的末尾。
#include <iostream> #include <string> int main() { std::string str = "Hello"; char cstr[] = ", world!"; str += cstr; std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
8. 使用 std::stringstream
进行转换 (灵活)
std::stringstream
是一个非常有用的工具,可以用于在字符串和各种数据类型之间进行转换。
const char*
转 std::string
:
#include <iostream> #include <string> #include <sstream> int main() { const char* cstr = "Hello, world!"; std::stringstream ss; ss << cstr; std::string str = ss.str(); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
char*
转 std::string
:
#include <iostream> #include <string> #include <sstream> int main() { char cstr[] = "Hello, world!"; std::stringstream ss; ss << cstr; std::string str = ss.str(); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
优点:
- 可以方便地进行多种数据类型之间的转换。
- 可以进行格式化输出。
缺点:
- 比直接使用构造函数稍慢。
9. 使用 std::copy
进行字符数组拷贝 (底层)
std::copy
算法可以用于将字符数组的内容复制到 std::string
的内部存储中。
#include <iostream> #include <string> #include <algorithm> // 包含 std::copy #include <iterator> // 包含 std::back_inserter int main() { char carr[] = "Hello, world!"; std::string str; std::copy(carr, carr + strlen(carr), std::back_inserter(str)); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
说明:
std::back_inserter(str)
返回一个插入迭代器,它将元素添加到str
的末尾。strlen(carr)
获取字符数组的长度。
10. 使用 assign
方法进行字符数组赋值 (灵活)
std::string
的 assign
方法提供了更灵活的字符串赋值方式,可以从字符数组中复制指定长度的字符。
#include <iostream> #include <string> int main() { char carr[] = "Hello, world!"; size_t len = strlen(carr); std::string str; str.assign(carr, len); std::cout << "str: " << str << std::endl; // 输出: str: Hello, world! return 0; }
assign
方法的其他用法:
str.assign(cstr, n)
: 从cstr
中复制前n
个字符到str
。str.assign(n, ch)
: 将str
赋值为n
个字符ch
的重复。
总结
掌握 C++ 字符串和字符数组之间的转换方法,可以让你更灵活地处理字符串,并与 C 语言库进行交互。 我总结了 10 种常用的转换方法,希望能帮助你解决实际开发中的问题。
std::string
转const char*
: 使用c_str()
或data()
。std::string
转char*
: 谨慎使用,推荐使用strcpy
或memcpy
复制字符串,并手动管理内存。const char*
转std::string
: 使用构造函数。char*
转std::string
: 使用构造函数。- 字符数组转
std::string
: 使用构造函数,指定起始地址和长度。 - 字符串拼接: 使用
+=
运算符。 - 使用
std::stringstream
进行转换: 灵活,可以进行多种数据类型转换。 - 使用
std::copy
进行字符数组拷贝: 底层,需要使用插入迭代器。 - 使用
assign
方法进行字符数组赋值: 灵活,可以指定复制的字符数量。
希望这篇文章对你有所帮助。如果你有任何问题或建议,欢迎在评论区留言。 祝你编程愉快!