在C++程序开发中,处理包含引号的字符串是经常遇到的场景,比如生成带引号的CSV字段、拼接包含字符串参数的命令、解析带引号的配置文件内容等,都需要对引号进行正确的转义或者还原操作。传统的手动转义方式需要逐个判断字符并添加反斜杠,不仅代码繁琐还容易遗漏边界情况,而标准库提供的std::quoted工具可以简化这一过程。

std::quoted的基本用法
std::quoted是C++14引入的标准库工具,定义在<iostream>头文件中,主要作用是给字符串添加引号包裹,并对字符串内部的引号进行转义,或者将转义后的带引号字符串还原为原始内容。
给字符串添加引号并转义内部引号
当需要将普通字符串转换为被引号包裹且内部引号正确转义的格式时,可以直接使用std::quoted包裹字符串,输出时会自动处理。
#include <iostream>
#include <iomanip> // std::quoted定义在这里
#include <string>
int main() {
std::string raw_str = "Hello "World""; // 原始字符串包含内部双引号
// 输出带转义后的带引号字符串
std::cout << std::quoted(raw_str) << std::endl;
return 0;
}
上述代码的输出结果是"Hello "World"",可以看到原始字符串被外层双引号包裹,内部的双引号也被自动添加了反斜杠转义,不需要手动拼接转义字符。
还原转义后的带引号字符串
std::quoted还可以配合输入流使用,将转义后的带引号字符串还原为原始内容,这在解析带引号的输入数据时非常实用。
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
int main() {
std::string escaped_str = ""Hello \"World\"""; // 转义后的带引号字符串
std::string result;
std::stringstream ss(escaped_str);
// 从流中读取并还原字符串
ss >> std::quoted(result);
std::cout << result << std::endl; // 输出 Hello "World"
return 0;
}
std::quoted的自定义参数
std::quoted支持自定义包裹引号、转义字符,默认使用双引号作为包裹符,反斜杠作为转义符,也可以根据需求修改。
#include <iostream>
#include <iomanip>
#include <string>
int main() {
std::string str = "It's a test"; // 包含单引号的字符串
// 使用单引号作为包裹符,反斜杠作为转义符
std::cout << std::quoted(str, ''', '\') << std::endl;
return 0;
}
上述代码输出结果是'It's a test',可以看到包裹符变成了单引号,内部的单引号也被正确转义。
其他C++引号转义方法
除了使用std::quoted,还有一些常见的引号转义方式,适用于不同的场景。
手动转义拼接
在C++11之前没有std::quoted的时候,很多开发者会手动拼接转义字符,这种方式适合简单的固定场景,但灵活性差。
#include <iostream>
#include <string>
std::string manual_escape(const std::string& s) {
std::string res = """;
for (char c : s) {
if (c == '"') {
res += '\'; // 转义双引号
}
res += c;
}
res += """;
return res;
}
int main() {
std::string str = "test "demo"";
std::cout << manual_escape(str) << std::endl;
return 0;
}
使用字符串替换函数
可以通过遍历字符串,将内部的引号替换为转义后的形式,这种方式比完全手动拼接更简洁,但需要自己处理边界情况。
#include <iostream>
#include <string>
#include <algorithm>
std::string replace_escape(const std::string& s) {
std::string res = s;
// 将每个双引号替换为转义后的双引号
std::string::size_type pos = 0;
while ((pos = res.find('"', pos)) != std::string::npos) {
res.replace(pos, 1, "\"");
pos += 2; // 跳过替换后的两个字符
}
return """ + res + """;
}
int main() {
std::string str = "hello "c++"";
std::cout << replace_escape(str) << std::endl;
return 0;
}
不同转义方法的对比
以下是几种常见引号转义方式的特点对比:
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| std::quoted | 标准库支持,无需手动处理转义逻辑,支持自定义参数,输入输出流通用 | 需要C++14及以上标准 | 大多数带引号字符串的转义和还原场景 |
| 手动转义拼接 | 无标准版本限制,逻辑直观 | 代码冗余,容易出错,扩展性差 | 简单的固定格式转义需求 |
| 字符串替换函数 | 比手动拼接更简洁,可复用 | 需要自己处理替换逻辑,容易遗漏边界情况 | 不支持C++14的旧项目简单场景 |
使用注意事项
- std::quoted仅支持char类型的字符串,对于wchar_t、char16_t、char32_t等宽字符类型,需要使用对应的std::quoted重载版本,定义在<locale>头文件中。
- 当使用std::quoted还原字符串时,输入流中的字符串必须符合转义格式,否则还原结果可能不符合预期。
- 手动转义时要注意转义字符本身的处理,比如反斜杠也需要转义为两个反斜杠,避免逻辑错误。
总的来说,在支持C++14及以上的项目中,优先使用std::quoted处理带引号字符串,既能减少代码量,也能降低出错概率,让字符串处理逻辑更清晰。
std::quotedC++引号转义带引号字符串处理修改时间:2026-07-15 07:57:30