如何将字符串的内容打印为“字符串文字源”

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&lt;char, std::string&gt; lookup = '\"', "\\\"", '\n', "\\n", '\t', "\\t" ;

以上是关于如何将字符串的内容打印为“字符串文字源”的主要内容,如果未能解决你的问题,请参考以下文章

将向量的整数内容打印为字符串会导致分段错误 [关闭]

如何打印 TextArea 的内容?

如何将二维字符串数组打印为字符串

如何将字符串转换为 uint32_t [重复]

如何在Java中向后打印多个字符串

如何将 HTML 转换为字符串 android 并打印该字符串