如何将字符串的内容打印为“字符串文字源”
Posted
技术标签:
【中文标题】如何将字符串的内容打印为“字符串文字源”【英文标题】:How to print the content of a string as "sting literal source" 【发布时间】:2021-03-05 21:52:19 【问题描述】:假设s
是
a
b
c
const std::string s =
std::cout << R"( s )" << std::endl;
如何std::cout
原始文字中的字符串内容?我的意思是 cout
以这种格式返回值:"a\nb\nc"
。
我需要将一个非常大的文本转换为std::string
。
我不能使用 fileread,因为我需要在 src 中定义它的值。
【问题讨论】:
可能是***.com/questions/9435667/…的欺骗 尝试使用内存查看窗口(粘贴地址)可以向下翻页,直到用完地址空间。 您的标题非常具有误导性。你想要的是一个文本,其中转义序列被打印为转义序列而不是扩展。为此,您必须用转义序列替换有问题的字符(回车符、制表符等)。 您尝试使用原始字符串文字违背了原始字符串文字的预期用途。原始字符串文字正是括号内的字符 没有替换 (在您的示例中,空格后跟字符's'
后跟空格)。您对问题的第二个措辞,即您声明希望看到一个反斜杠后跟字符 'n'
,更准确。
请不要将其称为“原始文字”,因为该术语在 C++ 中具有含义,而该含义不适用于您的目标。
【参考方案1】:
您需要做的是扫描字符串,并用可打印的转义序列替换所有出现的您感兴趣的字符(例如回车、制表符等),然后打印这个新文本。
这里有一些粗略的概念证明:
std::string escape(std::string_view src)
std::string ret;
ret.reserve(src.size() * 2); // at worst, the string consists solely of escapable symbols
static constexpr std::array escapable = std::make_pair('\t', 't'),
std::make_pair('\n', 'n'); // add more chars as needed, note that the array is sorted
for (const char ch: src)
std::pair search_pairch, ' ';
auto esc_char = std::equal_range(escapable.begin(), escapable.end(), search_pair, [](auto& a, auto& b) return a.first < b.first; );
if (esc_char.first != escapable.end())
ret.push_back('\\');
ret.push_back(esc_char.first->second);
else
ret.push_back(ch);
return ret;
现在,你可以使用它了:
const std::string str = "A\nbub\tfuf\n";
std::cout << escape(str) << "\n";
sn-p 上方打印A\nbub\tfuf\n
【讨论】:
嗨,谢尔盖,我的脚本有错误:i.imgur.com/AT4Fhbq.png【参考方案2】:您可能会对JSON 规范感兴趣。
您可以考虑使用诸如jsoncpp 之类的开源 C++ 库以 JSON 格式序列化您的数据
您也可以考虑在yaml-cpp 库中使用一些YAML 格式
您可能会对生成 C++ 胶水代码的SWIG 工具感兴趣。
您可以考虑使用像XDR 这样的二进制数据格式。
您应该指定(在纸上,用铅笔)您的数据格式为EBNF 符号,并使用ANTLR 或GNU bison 生成解析器(打印机更容易编码)
RefPerSys 项目(一个开源符号人工智能系统,GPLv3+ 许可)以文本格式保存数据。如果您遵守 GPL 许可,您可以借用一些代码在您的应用程序中重复使用。
还要查看Qt 或POCO 框架,但请注意DWORD64
不是标准 C++ 类型。请参阅 this C++ reference 并阅读最新的 C++ 标准(如 n3337 或更好)。
考虑生成 C++ 序列化代码
使用GNU m4 或GPP(或您自己的)等工具。
Pitrat 的书 Artificial Beings: the Conscience of a Conscious Machine (ISBN-13: 978-1848211018) 应该会给你宝贵的洞察力和直觉。
【讨论】:
【参考方案3】:您可以像这样将该文本文件加载到std::string
中:
将文本存储在文件中,例如mystring.txt,作为 R"(raw_characters)"
格式的原始字符串文字:
R"(Run.M128A XmmRegisters[16];
BYTE Reserved4[96];", Run.CONTEXT64 := " DWORD64 P1Home;
DWORD64 P2Home;
...
)"
#将文件包含在一个字符串中:
namespace
const std::string mystring =
#include "mystring.txt"
;
您的 IDE 可能会将其标记为语法错误,但事实并非如此。您正在做的是在编译时将文件的内容直接加载到字符串中。
最后打印字符串:
std::cout << mystring << std::endl;
为什么不直接将转义后的字符串保存在文件中?
无论如何,这里有一个“转义”字符的函数:
#include <iostream>
#include <string>
#include <unordered_map>
std::string replace_all(const std::string &mystring)
const std::unordered_map<char, std::string> lookup =
'\n', "\\n", '\t', "\\t", '"', "\\\"" ;
std::string new_string;
new_string.reserve(mystring.length() * 2);
for (auto c : mystring)
auto it = lookup.find(c);
if (it != lookup.end())
new_string += it->second;
else
new_string += c;
return new_string;
int main()
std::string mystring = R"(Run.M128A XmmRegisters[16];
BYTE Reserved4[96];", Run.CONTEXT64 := " DWORD64 P1Home;
DWORD64 P2Home;
DWORD64 P3Home;
DWORD64 P4Home;
DWORD64 P5Home;
DWORD64 P6Home;)";
auto new_string = replace_all(mystring);
std::cout << new_string << std::endl;
return 0;
这是demo。
【讨论】:
@Frank Thtat 是您的 IDE,认为存在语法错误,但您正在做的是将文件内容直接包含到您的字符串中。你试过编译吗? 已编译,但不会将其打印为原始/文字i.imgur.com/tmaNoaO.png @Frank 查看我的更新。抱歉,我没有意识到你想转义字符。我使用地图查找要替换的字符。您可以根据需要添加。 感谢您抽出宝贵时间@jignatius,只有一个问题,脚本没有转义引号 我已更改此行添加"
是否正确? std::unordered_map<char, std::string> lookup = '\"', "\\\"", '\n', "\\n", '\t', "\\t" ;
以上是关于如何将字符串的内容打印为“字符串文字源”的主要内容,如果未能解决你的问题,请参考以下文章