2017-08-16 101 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