web-dev-qa-db-ja.com

C ++複数行文字列リテラル

Perlのように、C++で複数行のプレーンテキストの定数リテラルを使用する方法はありますか?たぶん、ファイルを#includeingするための構文解析のトリックがありますか?私はそれについて考えることができません、しかし男の子、それはいいでしょう。 C++ 0xになるでしょう。

355
rlbond

ええと…。最も簡単な方法は、隣接する文字列リテラルがコンパイラによって連結されているという事実を使用することです。

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 = 
 "一方、ここで私は頭がおかしくなりました\ 
そして実際にリテラルを数行に渡らせます、\ 
各行の\ 
の内容を引用することで面倒になります。これはうまくいきますが、インデントすることはできません。 "; 

繰り返しになりますが、各行の終わりにある円記号に注意してください。それらは行末の直前になければなりません。それらはソース内の改行をエスケープしています。バックスラッシュがあった場所では、文字列に改行は付きません。この形式では、インデントは文字列の一部になり、ランダムなスペースで文字化けするので、明らかにテキストをインデントすることはできません。

520
unwind

C++ 11では、生の文字列リテラルがあります。 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"( ... )";

引用符の中にある親はまだ必要です。

315
emsr

#define MULTILINE(...) #__VA_ARGS__
括弧内のすべてを消費します。
任意の数の連続した空白文字を単一の空白に置き換えます。

25

複数行の文字列を入力するためのおそらく便利な方法はマクロを使うことです。これは、引用符と括弧のバランスが取れていて、「最上位」コンマが含まれていない場合にのみ機能します。

#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__では,を使用できます。

23
bcmpinc

あなたはこれをすることができます:

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

1オンスの経験は1トンの理論に値するので、私は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__がコンマ区切り文字を処理しないことです。そのため、それを文字列化演算子に渡すことができます。先頭と末尾のスペースは切り捨てられ、単語間のスペース(改行を含む)は1つのスペースに圧縮されます。括弧のバランスをとる必要があります。 #__VA_ARGS__にもかかわらずC++ 11の設計者が生の文字列リテラルの必要性を見た理由はこれらの欠点が説明すると思います。

9

C++ 11コンパイラ(GCC 4.2.1など)を持つのに十分な幸運ではなく、文字列に改行を埋め込みたい場合(@ char *のいずれか)、@ unwindの回答の@ emsrのコメントを少し説明するだけです。またはクラス文字列)、このようなものを書くことができます:

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の短いコメントは私がこれを初めて読んだとき私に飛び出さなかったので、私は私自身のためにこれを発見しなければなりませんでした。うまくいけば、私は数分他の人を救った。

7
CXJ

またこれをすることができます:

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