我有一个定义,其中包含一个路径(没有转义序列),如下所示:
// 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
答案 0 :(得分:2)
您生成的原始字符串的语法不正确。
这是正确的:
#define PATH R"(c:\blah\blah\file.cfg)"
检查CPP参考的(6)
语法格式:
前缀(可选)R“分隔符(raw_characters)分隔符”(6)
请参阅:string literal
答案 1 :(得分:2)
您可以使用预处理器的stringify-operator #
,它不仅将参数封装在双引号中,还会转义字符串中的“普通”反斜杠。然后 - 在运行时 - 切断stringify引入的额外双引号。
所以这个想法如下:
以某种方式将PATH
字符串化为"c:\blah\blah\file.cfg"
"\"c:\\blah\\blah\\file.cfg\""
。注意字符串本身
包含双引号作为第一个和最后一个字符。
在运行时,使用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