【问题标题】:Replace characters in preprocessor definition替换预处理器定义中的字符
【发布时间】:2017-08-16 07:09:52
【问题描述】:

我有一个定义,其中包括一个路径(没有转义序列),如下所示:

// Incorrect
#define PATH "c:\blah\blah\file.cfg"

我宁愿这样:

// Corrected
#define PATH "c:\\blah\\blah\\file.cfg"

虽然很遗憾我不能修改宏定义(实际上是生成包含宏的源的脚本......),除了添加前缀。现在我需要打开这个路径中给出的文件。我尝试了这样的 c++11 原始字符串文字:

// Modified definition
#define PATH R"c:\blah\blah\file.cfg"
std::ifstream(PATH); // error: unrecognised escape sequence 

现在的问题是如何使用宏替换所有\

注意事项(如果重要):
编译器:MSVC 14.0
操作系统:Windows 7

【问题讨论】:

  • \blah 实际上是 \b 后跟 lah。这是完全不同的性格。没有办法从那里去 \\
  • 如果您对构建系统有任何控制权,那么在运行编译器之前对代码生成脚本的输出进行后处理可能会更容易。
  • 修正脚本将是最好的解决方案,如果这真的不可能,后处理是下一个最好的解决方案恕我直言

标签: c++ c++11 macros


【解决方案1】:

您生成的原始字符串的语法不正确。

这是正确的:

#define PATH R"(c:\blah\blah\file.cfg)"

在 CPP 参考中检查 (6) 语法格式:

prefix(optional) R "delimiter( raw_characters )delimiter" (6)

见:string literal

示例:http://ideone.com/OZggmK

【讨论】:

    【解决方案2】:

    您可以使用预处理器的字符串化操作符#,它不仅将参数封装在双引号中,还可以转义字符串中的“普通”反斜杠。然后 - 在运行时 - 切断由 stringify 引入的额外双引号。

    所以思路如下:

    1. 以某种方式将PATH 字符串化,使"c:\blah\blah\file.cfg" 变为 "\"c:\\blah\\blah\\file.cfg\""。注意字符串本身 然后包含双引号作为第一个和最后一个字符。

    2. 在运行时,使用substr 削减(不需要的)之间的值 双引号

    有点棘手的是对本身作为宏提供的值进行字符串化。为此,您可以使用带有可变参数的宏(随着这些参数的扩展)。 所以完整的代码如下所示:

    #define PATH "c:\blah\blah\file.cfg"
    
    #define STRINGIFY_HELPER(A) #A
    #define STRINGIFY(...) STRINGIFY_HELPER(__VA_ARGS__)
    #define NORMALIZEPATH(P) string(STRINGIFY(P)).substr(1,strlen(STRINGIFY(P))-2)
    
    int main() {
    
        string filename =  NORMALIZEPATH(PATH);
        cout << "filename: " << filename << endl;
    
        return 0;
    }
    

    输出:

    filename: c:\blah\blah\file.cfg
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 2014-09-07
      • 2022-06-14
      • 1970-01-01
      • 2011-10-23
      相关资源
      最近更新 更多