C++ 中字符串与常见类型的转换,核心方案可以按"是否推荐新代码使用"来划分。最通用的选择是 std::stoi 系列(字符串转数值)与 std::to_string(数值转字符串) ,它们兼顾了易用性与类型安全;若追求极致性能(如解析大量数据),则用 C++17 的 std::from_chars / std::to_chars。
一、基本方法
字符串 ⇄ 数值(整数、浮点数)
字符串 → 数值
| 目标类型 | 推荐方法(通用) | 高性能方法 (C++17) |
|---|---|---|
int / long / long long |
std::stoi / std::stol / std::stoll |
std::from_chars |
float / double |
std::stof / std::stod |
std::from_chars |
通用方案 (std::stoX)
使用简单,遇到非法输入或溢出时会抛出异常,便于错误处理。
cpp
#include <string>
#include <iostream>
std::string s = "123";
try {
int n = std::stoi(s); // 转换 "123" 为 int
} catch (const std::invalid_argument& e) {
// 处理无法转换的情况
} catch (const std::out_of_range& e) {
// 处理数值越界的情况
}
注意 :
stoi只转换开头有效的数字部分。例如std::stoi("12abc")会返回12,不会报错。如果要求整个字符串必须全是数字,需利用pos参数检查转换结束的位置。
高性能方案 (std::from_chars)
不抛异常、不分配内存,速度快,适合对性能敏感的场景。它通过返回结果结构体来报告状态,且默认不识别前导 + 号和空白字符。
cpp
#include <charconv>
#include <string_view>
std::string_view sv = "123";
int n = 0;
auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), n);
if (ec == std::errc()) {
// 转换成功,n 已赋值
}
数值 → 字符串
| 源类型 | 推荐方法(通用) | 高性能方法 (C++17) |
|---|---|---|
| 所有数值类型 | std::to_string |
std::to_chars |
通用方案 (std::to_string)
一行代码即可完成转换,非常方便。
cpp
#include <string>
std::string s = std::to_string(42); // "42"
注意 :
to_string对于浮点数的格式化精度可能不符合预期(例如可能只保留 6 位小数),且其行为可能受全局 C 区域设置影响。
高性能方案 (std::to_chars)
与 from_chars 对应,同样不抛异常、无内存分配。你需要自己提供一个字符缓冲区,函数会将结果写入其中(结果不以空字符结尾)。
cpp
#include <charconv>
#include <array>
std::array<char, 10> buf{};
auto [ptr, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), 42);
// 转换成功的话,[buf.data(), ptr) 区间就是结果
字符串 ⇄ bool
C++ 标准并未提供直接将 bool 与 std::string 互转的函数,通常需要手动处理或借助流/格式化库。
bool → 字符串
- 手动转换(最简单) :
std::string s = b ? "true" : "false";。 - 流转换(可控制格式) :使用
std::ostringstream,默认输出"1"/"0";加上std::boolalpha则输出"true"/"false"。 - C++20
std::format:std::format("{}", b)会得到"true"或"false"。
字符串 → bool
标准库没有直接函数。如果需要严格解析,通常需要自己判断字符串内容(例如比较是否等于 "true" 或 "1")。如果只是想利用流的转换,要注意 std::istringstream 配合 >> 默认只能把 0 和 1 读成布尔值,读不了 "true"。
字符串 ⇄ char* (C 风格字符串)
这主要涉及与 C 语言接口交互,属于视图/拷贝操作,而非类型转换。
std::string → const char*
使用 c_str() 或 data() 成员函数,返回指向内部缓冲区的指针。
cpp
std::string s = "hello";
const char* p = s.c_str();
关键警告 :返回的指针在
std::string对象被修改或销毁后会失效。不要 长期保存这个指针,也不要返回局部string的c_str()。
const char* → std::string
直接利用 std::string 的构造函数即可。
cpp
const char* p = "hello";
std::string s(p);
总结与选择建议
- 日常编码 :无脑用
std::stoi/std::to_string。代码清晰,异常机制让错误处理更直观。 - 性能敏感场景 (如日志解析、网络协议、游戏引擎):用
std::from_chars/std::to_chars。这是目前标准库中最高效的方案。 - 需要格式化控制 (如指定浮点精度、进制、或输出
true/false):考虑std::format(C++20)或std::stringstream。 - 与 C 接口交互 :
string转const char*用c_str(),反向直接用构造函数。务必注意c_str()指针的生命周期。
下面是 C++ 字符串与常见数据类型转换相关函数的表格总结,按转换方向分类。
二、字符串 → 数值(转出为数字)
| 函数 | 返回类型 | 所属头文件 | 标准版本 | 错误处理方式 | 是否识别空白/正负号 | 备注 |
|---|---|---|---|---|---|---|
std::stoi |
int |
<string> |
C++11 | 抛 invalid_argument / out_of_range |
是 | 支持进制参数 |
std::stol |
long |
<string> |
C++11 | 同上 | 是 | |
std::stoll |
long long |
<string> |
C++11 | 同上 | 是 | |
std::stoul |
unsigned long |
<string> |
C++11 | 同上 | 是 | 负号会回绕 |
std::stoull |
unsigned long long |
<string> |
C++11 | 同上 | 是 | |
std::stof |
float |
<string> |
C++11 | 同上 | 是 | |
std::stod |
double |
<string> |
C++11 | 同上 | 是 | |
std::stold |
long double |
<string> |
C++11 | 同上 | 是 | |
std::from_chars |
任意整型/浮点 | <charconv> |
C++17 | 返回 errc 错误码 |
否(不跳空白) | 性能最优,无分配 |
atoi |
int |
<cstdlib> |
C | 无 | 是 | 溢出未定义 |
atol |
long |
<cstdlib> |
C | 无 | 是 | |
atoll |
long long |
<cstdlib> |
C++11 | 无 | 是 | |
atof |
double |
<cstdlib> |
C | 无 | 是 | 无 float/long double 版本 |
strtol |
long |
<cstdlib> |
C | 通过 endptr + errno |
是 | 可指定进制 |
strtoll |
long long |
<cstdlib> |
C++11 | 同上 | 是 | |
strtoul / strtoull |
无符号 | <cstdlib> |
C/C++11 | 同上 | 是 | |
strtof / strtod / strtold |
浮点 | <cstdlib> |
C/C++11 | 同上 | 是 | |
sscanf / std::istringstream >> |
多种 | <cstdio> / <sstream> |
C/C++ | 返回值/流状态 | 是 | 通用但较慢 |
三、数值 → 字符串(转为文本)
| 函数 | 输入类型 | 所属头文件 | 标准版本 | 特点 | 备注 |
|---|---|---|---|---|---|
std::to_string |
所有整型/浮点 | <string> |
C++11 | 简单,有内存分配 | 浮点精度固定 6 位,受 locale 影响 |
std::to_chars |
任意整型/浮点 | <charconv> |
C++17 | 高性能,无分配 | 结果不以 \0 结尾,需自备缓冲区 |
std::ostringstream << |
任意(含自定义) | <sstream> |
C++98 | 可格式化 | 较慢,但灵活(精度、进制、boolalpha) |
std::format |
任意 | <format> |
C++20 | 现代格式化 | 需编译器支持 |
sprintf / snprintf |
多种 | <cstdio> |
C | C 风格格式化 | 注意缓冲区溢出 |
std::to_string 的替代 std::format |
数值 | <format> |
C++20 | 精度/宽度可控 | 推荐新代码 |
四、字符串 ↔ bool
| 方向 | 方法 | 说明 |
|---|---|---|
bool → string |
b ? "true" : "false" |
最直接 |
bool → string |
ostringstream + std::boolalpha |
输出 true/false,否则 1/0 |
bool → string |
std::format("{}", b) |
C++20,输出 true/false |
string → bool |
手动判断(比较 "true"/"1" 等) |
标准库无直接函数 |
string → bool |
istringstream >> b |
只能读 0/1,不能读 "true" |
五、字符串 ↔ char*(C 风格)
| 方向 | 方法 | 头文件 | 注意 |
|---|---|---|---|
std::string → const char* |
s.c_str() |
<string> |
指针随 string 修改/销毁失效 |
std::string → char*(只读视图) |
s.data() |
<string> |
C++17 起返回非 const 也可写(但勿越界) |
std::string → char*(可写拷贝) |
手动 strcpy 到缓冲区 |
<cstring> |
需自行管理内存 |
const char* → std::string |
std::string(p) |
<string> |
直接构造 |
char[] → std::string |
std::string(arr) |
<string> |
依赖 \0 结尾 |
std::string → C 接口 |
s.c_str() 传给 printf、fopen 等 |
--- | 不要长期保存指针 |
六、字符串 ↔ 其他常见类型
| 方向 | 方法 | 说明 |
|---|---|---|
string → char(单字符) |
s[0] / s.at(0) / s.front() |
需保证非空 |
char → string |
std::string(1, c) 或 string s; s += c; |
|
string → wstring |
std::wstring_convert(C++17 弃用)或手动转换 |
编码问题,建议用第三方库 |
string → 枚举 |
手动映射表 / std::map<string, Enum> |
无标准函数 |
string → 自定义类型 |
自定义 operator>> 或解析函数 |
|
| 数值 → 指定进制字符串 | std::to_chars(..., base) / std::format("{:x}", n) |
to_string 不支持进制 |
七、按需求速查
| 需求 | 首选 | 备选 |
|---|---|---|
| 一般字符串转 int | std::stoi |
from_chars(性能)/ strtol(C 风格) |
| 一般 int 转字符串 | std::to_string |
to_chars / format |
| 高性能批量解析 | std::from_chars |
--- |
| 高性能批量输出 | std::to_chars |
--- |
| 需要格式化(精度/进制/对齐) | std::format(C++20) |
ostringstream / snprintf |
| 兼容老代码 / C++98 | atoi / strtol / stringstream |
--- |
| 与 C 接口交互 | c_str() / 构造函数 |
data() |
| 错误必须可检测 | stoi 系列(异常)/ from_chars(错误码) |
strtol(endptr) |
一句话总结 :日常用 std::stoi + std::to_string;性能敏感用 std::from_chars + std::to_chars;格式化需求用 std::format;与 C 交互用 c_str()。