有什么方法可以在 C++ 中使用多行纯文本常量文字,à la Perl?也许一些
#include
ing 文件的解析技巧?我想不出一个,但是男孩,那会很好。我知道它会在 C++0x 中。
嗯......有点。最简单的方法是使用编译器连接相邻字符串文字的事实:
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.";
缩进并不重要,因为它不在引号内。
你也可以这样做,只要你注意逃避嵌入的换行符。如果不这样做,就像我的第一个答案一样,将无法编译:
常量字符 *text2 = “另一方面,在这里,我疯了\ 并真正让文字跨越几行,\ 无需费心引用每一行的 \ 内容。这行得通,但你不能缩进。";
再次注意每行末尾的那些反斜杠,它们必须紧接在行结束之前,它们正在转义源代码中的换行符,这样一切就好像换行符不存在一样。您不会在字符串中有反斜杠的位置换行。使用这种形式,你显然不能缩进文本,因为缩进会成为字符串的一部分,用随机空格来混淆它。
在 C++11 中,你有原始字符串文字。有点像 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";
保留字符串中的所有空格和缩进以及换行符。
这些也可以是 utf-8|16|32 或 wchar_t(带有通常的前缀)。
我应该指出这里实际上不需要转义序列 V0G0N。它的存在将允许将 )" 放入字符串中。换句话说,我可以放
"(by Prostetnic Vogon Jeltz; see p. 56/57)"
(注意额外的引号)并且上面的字符串仍然是正确的。否则我也可以使用
const char * vogon_poem = R"( ... )";
引号内的括号仍然需要。
你也可以这样做:
const char *longString = R""""(
This is
a very
long
string
)"""";
#define MULTILINE(...) #__VA_ARGS__
输入多行字符串的一种可能方便的方法是使用宏。这仅在引号和括号平衡且不包含“顶级”逗号的情况下有效:
#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);
使用 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.]]
请注意,
,
不能出现在字符串中,除非它包含在括号或引号内。单引号是可能的,但会产生编译器警告。
编辑:如评论中所述,
#define MULTI_LINE_STRING(...) #__VA_ARGS__
允许使用,
.
你可以这样做:
const char *text = "This is my string it is "
"very long";
只是为了阐明@emsr 在@unwind 的回答中的评论,如果一个人不够幸运,没有一个 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 的简短评论并没有引起我的注意,所以我必须自己去发现它。希望我已经为其他人节省了几分钟。
因为一盎司的经验值得一吨的理论,我尝试了一个小测试程序
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 filename
编译此片段以重现。
#__VA_ARGS__
背后的技巧是__VA_ARGS__
不处理逗号分隔符。所以你可以将它传递给字符串化运算符。修剪前导和尾随空格,然后将单词之间的空格(包括换行符)压缩为一个空格。括号需要平衡。我认为这些缺点解释了为什么 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";
Option 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. 如果你的项目中没有Boost,你可以在现代C++中使用
std::string_view()
。