C++ 多行字符串文字
Posted
技术标签:
【中文标题】C++ 多行字符串文字【英文标题】:C++ multiline string literal 【发布时间】:2010-11-11 06:33:17 【问题描述】:有什么方法可以在 C++ 中使用多行纯文本常量文字,就像 Perl 一样?也许#include
ing 文件的一些解析技巧?我想不出一个,但是男孩,那会很好。我知道它会在 C++0x 中。
【问题讨论】:
通常您不想将字符串文字嵌入到代码中。对于 I18N 和 L10N,最好将字符串文字放入在运行时加载的配置文件中。 有足够多的情况将字符串文字放入代码中不是问题:如果字符串不用于向用户表示它;即:SQL 语句、文件名、注册表项名称、要执行的命令行... @Martin:但是,知道它仍然很有用。例如,我这样做是为了分解复杂的正则表达式。 【参考方案1】:嗯……有点。最简单的方法是使用编译器连接相邻字符串文字的事实:
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 = “在这里,另一方面,我已经疯了\ 真的让文字跨越几行,\ 无需费心引用每一行的 \ 内容。这行得通,但你不能缩进。";再次注意每行末尾的反斜杠,它们必须在行结束之前,它们正在转义源代码中的换行符,因此一切都好像换行符不存在一样。在有反斜杠的位置,字符串中不会出现换行符。使用这种形式,你显然不能缩进文本,因为缩进会成为字符串的一部分,用随机空格乱码。
【讨论】:
过去有人告诉我,第一个选项可以由实现决定,但是我还没有找到不支持该语法的编译器。 @Jason:它不一定是 C89 之前的编译器的一部分,但它是在 C89 中定义的,因此基本上在所有地方都受到支持。 另外,如果您真的希望在 c++98 中将字符串格式化为多行,只需将 \n 替换为每个带引号的字符串片段上的终止空间。 C++11 原始文字仍然是我的最爱。 @unwind 请注意,源代码行末尾的换行符不是字符串的一部分,它只是被跳过了。如果要将换行符作为字符串的一部分,则需要在行尾添加 \n\。 Microsoft Visual Studio 中存在严重的错误。如果在行尾使用反斜杠,它会自动缩进字符串中的文本。【参考方案2】:在 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"( ... )";
引号内的括号仍然需要。
【讨论】:
这真的是我想要的,能够避免引号、反斜杠-Ns、转义,并且在实际字符串中仍然出现换行符。这对于嵌入式代码(例如着色器或 Lua)很方便。不幸的是,我们还没有全部使用 C++-0x。 :-( 我自己正在考虑将这个用于嵌入式 SQL 和 Python 脚本。如果 gcc 可以让它在 C++98 模式下通过,我希望为你着想,但是,唉,不。 我比较习惯clang和gcc。在此编译器中,您必须为 C++0x 或 c++11 设置一个标志。看看一个 MS 网站,看起来他们还没有原始文字。我知道随着 C++ 功能的实现,MS 将更快地发布新的编译器更新。查找 Visual C++ 编译器 2012 年 11 月 CTP [microsoft.com/en-us/download/details.aspx?id=35515] 了解最新前沿。 @rsethc 只需使用#if 0
... #endif
注释掉代码块。巢也。
我的多行字符串总是使用V0G0N,因为我永远记不住这个语法,所以我总是查找这个答案,然后我总是觉得很有趣。【参考方案3】:
您也可以这样做:
const char *longString = R""""(
This is
a very
long
string
)"""";
【讨论】:
谢谢,这太棒了,甚至在 C 中也可以工作。显然,char longString[] = R""""( This is a very long string )"""";
对我也有效。
这是否以新行开始和结束字符串?
这是一个raw string literal。从 C++11 开始可用。
与 Arduino 一起工作!现在我可以轻松地提供嵌入式网页了!
@emsr 的一个很好的变体表明他的答案看起来不像 PERL 而更像 Python。【参考方案4】:
#define MULTILINE(...) #__VA_ARGS__
使用括号之间的所有内容。
用一个空格替换任意数量的连续空白字符。
【讨论】:
如果需要换行符可以加\n
请注意` (and hence
\n) is copied literally, but
"` 被转换为\"
。所以MULTILINE(1, "2" \3)
产生"1, \"2\" \3"
。
@AndreasSpindler 只要引号和反斜杠出现在字符串或字符文字标记内,它们就会被(附加)反斜杠转义。不知道你的意思是什么。有一个不匹配的引号(双引号或单引号)是非法的,所以收缩不起作用,或者无论如何都是奇数,这可能是最大的缺点。无论如何+1。 “真正的程序员”总是成对使用缩略词,中间没有换行符,因此单引号是平衡的。
关键是他写了“括号之间的东西”。【参考方案5】:
输入多行字符串的一种可能方便的方法是使用宏。这仅在引号和括号平衡且不包含“***”逗号时才有效:
#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.]]
请注意,,
不能在字符串中,除非它包含在括号或引号中。可以使用单引号,但会产生编译器警告。
编辑:如 cmets 中所述,#define MULTI_LINE_STRING(...) #__VA_ARGS__
允许使用 ,
。
【讨论】:
对于一个我想在 c++ 中包含一些 lua 代码 sn-ps 的项目,我最终编写了一个小的 python 脚本,在其中我输入了多行字符串,并让它生成一个 c++ 源代码文件。 非常适合我,从 collada 文件中添加一个巨大的多行浮动列表字符串以进行单元测试。我不想到处加上引号,我需要一个复制和粘贴解决方案。 如果你想让你的字符串包含逗号,你可以使用#define MULTILINE(...) #__VA_ARGS__
。
请注意,这会去除大部分多余的空白(包括所有\n
和\r
),这对某些情况很方便,但对另一些情况却是致命的。【参考方案6】:
你可以这样做:
const char *text = "This is my string it is "
"very long";
【讨论】:
与@unwind 的回答有何不同? @Sisir 我在放松前 2 分钟发布了它。【参考方案7】:只是为了澄清@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 的简短评论并没有引起我的注意,因此我必须自己发现这一点。希望我已经救了别人几分钟。
【讨论】:
【参考方案8】:由于一盎司的经验值得大量的理论,我为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__
,却看到了对原始字符串文字的需求。
【讨论】:
【参考方案9】:// 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";
【讨论】:
请在您的答案中添加解释,而不仅仅是代码 sn-ps【参考方案10】:选项 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);
选项 2。如果您的项目中没有 boost 可用,您可以在现代 C++ 中使用 std::string_view()。
【讨论】:
以上是关于C++ 多行字符串文字的主要内容,如果未能解决你的问题,请参考以下文章