有没有办法有多行纯文本,常量字面量在c++, à la Perl?也许是使用#include文件的一些解析技巧?我想不出一个,但那太好了。我知道是c++ 0x。


当前回答

由于一盎司的经验胜过一吨的理论,我尝试了一个关于MULTILINE的小测试程序:

#define MULTILINE(...) #__VA_ARGS__

const char *mstr[] =
{
    MULTILINE(1, 2, 3),       // "1, 2, 3"
    MULTILINE(1,2,3),         // "1,2,3"
    MULTILINE(1 , 2 , 3),     // "1 , 2 , 3"
    MULTILINE( 1 , 2 , 3 ),   // "1 , 2 , 3"
    MULTILINE((1,  2,  3)),   // "(1,  2,  3)"
    MULTILINE(1
              2
              3),             // "1 2 3"
    MULTILINE(1\n2\n3\n),     // "1\n2\n3\n"
    MULTILINE(1\n
              2\n
              3\n),           // "1\n 2\n 3\n"
    MULTILINE(1, "2" \3)      // "1, \"2\" \3"
};

用cpp -P -std=c++11的文件名来编译这个片段。

#__VA_ARGS__背后的技巧是__VA_ARGS__不处理逗号分隔符。你可以把它传递给字符串化操作符。开头和结尾的空格被修剪,单词之间的空格(包括换行)被压缩为一个空格。括号需要平衡。我认为这些缺点解释了为什么c++ 11的设计者,尽管有#__VA_ARGS__,看到了原始字符串字面量的需求。

其他回答

在c++ 11中,你有原始字符串字面值。有点像这里-文本在shell和脚本语言,如Python、Perl和Ruby。

const char * vogon_poem = R"V0G0N(
             O freddled gruntbuggly thy micturations are to me
                 As plured gabbleblochits on a lurgid bee.
              Groop, I implore thee my foonting turlingdromes.   
           And hooptiously drangle me with crinkly bindlewurdles,
Or I will rend thee in the gobberwarts with my blurlecruncheon, see if I don't.

                (by Prostetnic Vogon Jeltz; see p. 56/57)
)V0G0N";

字符串中的所有空格、缩进和换行符都被保留。

这些也可以是utf-8|16|32或wchar_t(带有常用的前缀)。

我应该指出,这里实际上不需要转义序列V0G0N。它的存在将允许将)“放入字符串中。换句话说,我可以把

                "(by Prostetnic Vogon Jeltz; see p. 56/57)"

(注意额外的引号)和上面的字符串仍然是正确的。否则我还不如用

const char * vogon_poem = R"( ... )";

引号内的括号仍然是需要的。

#定义MULTILINE(…)#__VA_ARGS__ 消耗括号之间的所有东西。 将任意数量的连续空白字符替换为单个空格。

嗯…排序的。最简单的方法是使用相邻的字符串字面值由编译器连接的事实:

const char *text =
  "This text is pretty long, but will be "
  "concatenated into just a single string. "
  "The disadvantage is that you have to quote "
  "each part, and newlines must be literal as "
  "usual.";

缩进并不重要,因为它不在引号内。

你也可以这样做,只要你注意转义嵌入的换行符。如果不这样做,就像我的第一个答案一样,将无法编译:

const char *text2 =
  "Here, on the other hand, I've gone crazy \
and really let the literal span several lines, \
without bothering with quoting each line's \
content. This works, but you can't indent.";

同样,注意每行末尾的反斜杠,它们必须在行结束之前,它们在源文件中转义换行符,这样就好像换行符不存在一样。你不会在有反斜杠的位置得到换行符。使用这种形式,您显然不能缩进文本,因为缩进将成为字符串的一部分,用随机空格混淆它。

选项1。使用boost库,可以如下所示声明字符串

const boost::string_view helpText = "This is very long help text.\n"
      "Also more text is here\n"
      "And here\n"

// Pass help text here
setHelpText(helpText);

第二个选项。如果boost在你的项目中不可用,你可以在现代c++中使用std::string_view()。

为了在@unwind的回答中稍微说明一下@emsr的注释,如果一个人不够幸运,没有c++ 11编译器(比如GCC 4.2.1),并且他想在字符串中嵌入换行符(char *或类字符串),他可以这样写:

const char *text =
  "This text is pretty long, but will be\n"
  "concatenated into just a single string.\n"
  "The disadvantage is that you have to quote\n"
  "each part, and newlines must be literal as\n"
  "usual.";

很明显,这是真的,但是@emsr的简短评论在我第一次读到这篇文章时并没有跳入我的脑海,所以我必须自己去发现。希望我为其他人节省了几分钟时间。