简体   繁体   English

C++ 多行字符串文字

[英]C++ multiline string literal

Is there any way to have multi-line plain-text, constant literals in C++, à la Perl?有没有办法在 C++ 中使用多行纯文本常量文字,如 Perl? Maybe some parsing trick with #include ing a file?也许一些解析技巧与#include一个文件? I can't think of one, but boy, that would be nice.我想不出一个,但是男孩,那会很好。 I know it'll be in C++0x.我知道它会在 C++0x 中。

Well ... Sort of.嗯......有点。 The easiest is to just use the fact that adjacent string literals are concatenated by the compiler:最简单的方法是使用相邻字符串文字由编译器连接的事实:

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.";

The indentation doesn't matter, since it's not inside the quotes.缩进无关紧要,因为它不在引号内。

You can also do this, as long as you take care to escape the embedded newline.您也可以这样做,只要您小心转义嵌入的换行符即可。 Failure to do so, like my first answer did, will not compile:如果不这样做,就像我的第一个答案一样,将无法编译:

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.";

Again, note those backslashes at the end of each line, they must be immediately before the line ends, they are escaping the newline in the source, so that everything acts as if the newline wasn't there.再次注意每行末尾的那些反斜杠,它们必须紧接在行结束之前,它们在源代码中转义换行符,因此一切都好像换行符不存在一样。 You don't get newlines in the string at the locations where you had backslashes.在有反斜杠的位置,您不会在字符串中获得换行符。 With this form, you obviously can't indent the text since the indentation would then become part of the string, garbling it with random spaces.使用这种形式,您显然无法缩进文本,因为缩进将成为字符串的一部分,并用随机空格将其弄乱。

In C++11 you have raw string literals.在 C++11 中,你有原始字符串文字。 Sort of like here-text in shells and script languages like Python and Perl and Ruby.有点像 shell 和脚本语言(如 Python、Perl 和 Ruby)中的 here-text。

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";

All the spaces and indentation and the newlines in the string are preserved.保留字符串中的所有空格和缩进以及换行符。

These can also be utf-8|16|32 or wchar_t (with the usual prefixes).这些也可以是 utf-8|16|32 或 wchar_t(带有通常的前缀)。

I should point out that the escape sequence, V0G0N, is not actually needed here.我应该指出,这里实际上不需要转义序列 V0G0N。 Its presence would allow putting )" inside the string. In other words, I could have put它的存在将允许将 )" 放入字符串中。换句话说,我可以将

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

(note extra quotes) and the string above would still be correct. (注意额外的引号)并且上面的字符串仍然是正确的。 Otherwise I could just as well have used否则我也可以使用

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

The parens just inside the quotes are still needed.仍然需要引号内的括号。

You can also do this:你也可以这样做:

const char *longString = R""""(
This is 
a very 
long 
string
)"""";

#define MULTILINE(...) #__VA_ARGS__
Consumes everything between the parentheses.消耗括号之间的所有内容。
Replaces any number of consecutive whitespace characters by a single space.用一个空格替换任意数量的连续空白字符。

A probably convenient way to enter multi-line strings is by using macro's.输入多行字符串的一种可能方便的方法是使用宏。 This only works if quotes and parentheses are balanced and it does not contain 'top level' comma's:这仅在引号和括号平衡且不包含“顶级”逗号时才有效:

#define MULTI_LINE_STRING(a) #a
const char *text = MULTI_LINE_STRING(
  Using this trick(,) you don't need to use quotes.
  Though newlines and     multiple     white   spaces
  will be replaced by a single whitespace.
);
printf("[[%s]]\n",text);

Compiled with gcc 4.6 or g++ 4.6, this produces: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]用 gcc 4.6 或 g++ 4.6 编译,这会产生: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]] [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]

Note that the , cannot be in the string, unless it is contained within parenthesis or quotes.请注意, ,不能在字符串中,除非它包含在括号或引号中。 Single quotes is possible, but creates compiler warnings.单引号是可能的,但会产生编译器警告。

Edit: As mentioned in the comments, #define MULTI_LINE_STRING(...) #__VA_ARGS__ allows the use of , .编辑:如评论中所述, #define MULTI_LINE_STRING(...) #__VA_ARGS__允许使用,

You can just do this:你可以这样做:

const char *text = "This is my string it is "
     "very long";

Just to elucidate a bit on @emsr's comment in @unwind's answer, if one is not fortunate enough to have a C++11 compiler (say GCC 4.2.1), and one wants to embed the newlines in the string (either char * or class string), one can write something like this:只是为了在@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.";

Very obvious, true, but @emsr's short comment didn't jump out at me when I read this the first time, so I had to discover this for myself.很明显,没错,但是当我第一次读到这篇文章时,@emsr 的简短评论并没有引起我的注意,所以我必须自己发现这一点。 Hopefully, I've saved someone else a few minutes.希望我已经为其他人节省了几分钟。

Since an ounce of experience is worth a ton of theory, I tried a little test program for MULTILINE :由于一盎司的经验值得大量的理论,我尝试了一个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"
};

Compile this fragment with cpp -P -std=c++11 filename to reproduce.使用cpp -P -std=c++11 filename编译此片段以重现。

The trick behind #__VA_ARGS__ is that __VA_ARGS__ does not process the comma separator. #__VA_ARGS__背后的#__VA_ARGS____VA_ARGS__不处理逗号分隔符。 So you can pass it to the stringizing operator.所以你可以将它传递给字符串化操作符。 Leading and trailing spaces are trimmed, and spaces (including newlines) between words are compressed to a single space then.修剪前导和尾随空格,然后将单词之间的空格(包括换行符)压缩为一个空格。 Parentheses need to be balanced.括号需要平衡。 I think these shortcomings explain why the designers of C++11, despite #__VA_ARGS__ , saw the need for raw string literals.我认为这些缺点解释了为什么 C++11 的设计者,尽管#__VA_ARGS__ ,看到了对原始字符串文字的需求。

// C++11. 
std::string index_html=R"html(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>VIPSDK MONITOR</title>
    <meta http-equiv="refresh" content="10">
</head>
<style type="text/css">
</style>
</html>
)html";

You can use string a = "this is line 1" "this is line 2";您可以使用 string a = "this is line 1" "this is line 2";

Option 1. Using boost library, you can declare the string as below选项 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);

Option 2. If boost is not available in your project, you can use std::string_view() in modern C++.选项 2. 如果您的项目中没有 boost,您可以在现代 C++ 中使用 std::string_view() 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM