C++ 中字符串与常见类型的转换总结

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()。

相关推荐
我命由我123451 小时前
Python 开发 - Python 虚拟环境
运维·开发语言·后端·python·http·https·java-ee
c#上位机1 小时前
C#上位机项目实战——exe项目调试更改dll中源代码
开发语言·c#
梦影_1 小时前
MySQL进阶教程(一)—— 储存过程与触发器(上)
开发语言·数据库·后端·sql·mysql·中间件
云和数据.ChenGuang1 小时前
LLM大模型对接本地Ollama部署模型
开发语言·人工智能·python·langchain
等我调个Bug1 小时前
C++智能指针通俗讲解
开发语言·c++
黑化旺仔1 小时前
【OC】Runtime:类元数据、加载初始化与消息派发
开发语言·macos·ios·objective-c
Felven2 小时前
C. Removing Smallest Multiples
c语言·开发语言
云和数据.ChenGuang2 小时前
光哥说Python 循环导入(Circular Import)深度解析:成因、排查与解决方案
开发语言·前端·人工智能·python·langchain
星夜离尘562 小时前
MATLAB 工程实验:滞回加持续时间报警,把 UNKNOWN 留在状态机里
开发语言·matlab