PerlのようなC ++で複数行のプレーンテキストの定数リテラルを作成する方法はありますか?たぶん#include
、ファイルを解析する際の解析トリックですか?私はそれを考えることができませんが、男の子、それはいいでしょう。C ++ 0xになることは知っています。
PerlのようなC ++で複数行のプレーンテキストの定数リテラルを作成する方法はありますか?たぶん#include
、ファイルを解析する際の解析トリックですか?私はそれを考えることができませんが、男の子、それはいいでしょう。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.";
インデントは引用符の中にないため、問題ではありません。
埋め込まれた改行をエスケープするように注意している限り、これを行うこともできます。そうしないと、私の最初の答えがしたように、コンパイルされません:
const char * text2 = 「一方で、私は狂ってしまいました\ そして実際にリテラルを数行に渡らせます、\ 各行の\を引用することを気にすることなく コンテンツ。これは機能しますが、インデントすることはできません。 ";
繰り返しになりますが、バックスラッシュは各行の終わりにあることに注意してください。バックスラッシュは行の終わりの直前になければならず、ソースの改行をエスケープしているため、すべてが改行がないかのように動作します。バックスラッシュがあった場所の文字列に改行が入りません。このフォームでは、インデントが文字列の一部になり、ランダムなスペースで文字化けするため、テキストをインデントすることはできません。
C ++ 11では、生の文字列リテラルがあります。シェルの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"( ... )";
引用符のすぐ内側にある括弧がまだ必要です。
#if 0
… #endif
を使用します。巣も。
#define MULTILINE(...) #__VA_ARGS__
括弧内のすべてを消費します。
任意の数の連続する空白文字を1つのスペースに置き換えます。
\n
改行が必要な場合は追加できます
` (and hence
\ nは) is copied literally, but
「`に変換される\"
。だから、のMULTILINE(1, "2" \3)
利回り"1, \"2\" \3"
。
複数行の文字列を入力するためのおそらく便利な方法は、マクロを使用することです。これは、引用符と括弧がバランスが取れており、「トップレベル」のコンマが含まれていない場合にのみ機能します。
#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__
ように、の使用を許可します,
。
#define MULTILINE(...) #__VA_ARGS__
文字列にコンマを含める場合に使用できます。
\n
とを含む\r
)が取り除かれます。これは、場合によっては便利で、他の場合には致命的です。
これを行うこともできます:
const char *longString = R""""(
This is
a very
long
string
)"""";
char longString[] = R""""( This is a very long string )"""";
動作します。明らかに、私にとっても動作します。
オンスの経験は理論のトンの価値があるので、私はのための小さなテストプログラムを試しました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__
、生の文字列リテラルの必要性を見た理由を説明していると思います。
@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の短いコメントは、初めて読んだときに私から飛び出さなかったので、自分でこれを発見する必要がありました。うまくいけば、私は数分他の人を救った。
// 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";