2017-08-16 60 views
2

我有这样一个定义,包括路径(没有转义序列):在预处理定义字符替换

// 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

+1

\等等实际上是\ B,接着啦。这完全是一个不同的性格。没有办法从\\ –

+5

如果您完全可以控制您的构建系统,那么在运行编译器之前对代码生成脚本的输出进行后处理可能会更容易。 –

+1

更正脚本将是最好的解决方案,如果这是不可能的,后处理是下一个最好的解决方案恕我直言 –

回答

2

你产生不正确的语法为原始字符串。

下面是正确的:

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

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

前缀(可选)R “定界符(raw_characters)定界符”(6)

参见:string literal

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

1

您可以使用预处理器的stringify运算符#,该运算符不仅将参数封装在双引号中,而且还在字符串中转义“普通”反斜杠。然后 - 在运行时切断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