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


415

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


1
一般的に、文字列リテラルをコードに埋め込むことは望ましくありません。I18NおよびL10Nの場合、実行時にロードされる構成ファイルに文字列リテラルを配置することをお勧めします。
マーティンヨーク

45
文字列リテラルをコードに入れても問題ない場合は十分にあります。文字列を使用してユーザーに表示しない場合。例:SQLステートメント、ファイル名、レジストリキー名、実行されるコマンドライン、...
mmmmmmmm

2
@Martin:ただし、知っておくと役に立ちます。たとえば、複雑な正規表現を分割するためにやったことがあります。
Boojum

回答:


591

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

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 =
  「一方で、私は狂ってしまいました\
そして実際にリテラルを数行に渡らせます、\
各行の\を引用することを気にすることなく
コンテンツ。これは機能しますが、インデントすることはできません。 ";

繰り返しになりますが、バックスラッシュは各行の終わりにあることに注意してください。バックスラッシュは行の終わりの直前になければならず、ソースの改行をエスケープしているため、すべてが改行がないかのように動作します。バックスラッシュがあった場所の文字列に改行が入りません。このフォームでは、インデントが文字列の一部になり、ランダムなスペースで文字化けするため、テキストをインデントすることはできません。


3
私は以前、最初のオプションは実装次第である可能性があると言われましたが、その構文を尊重しないコンパイラーをまだ見つけていません。
Jason Mock、

28
@ジェイソン:C89以前のコンパイラの一部である必要はありませんでしたが、C89で定義されているため、基本的にあらゆる場所でサポートされています。
ジョナサンレフラー、

4
また、c ++ 98で複数行にフォーマットされた文字列が本当に必要な場合は、引用符で囲まれた各文字列フラグメントの終了スペースを\ nに置き換えます。C ++ 11の未加工リテラルは、今でも私のお気に入りです。
emsr

3
@unwindソース行の最後の改行は文字列の一部ではなく、スキップされることに注意してください。文字列の一部として改行が必要な場合は、行の終わりに\ n \が必要です。
hyde

2
Microsoft Visual Studioに厄介なバグがあります。行末でバックスラッシュを使用すると、文字列内のテキストが自動的にインデントされます。
パロタ2014年

408

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

引用符のすぐ内側にある括弧がまだ必要です。


24
これは私が本当に望んでいることです。引用符、バックスラッシュN、エスケープを回避し、実際の文字列に改行を表示する機能です。これは、埋め込みコード(シェーダーやLuaなど)に便利です。残念ながら、まだC ++-0xをすべて使用しているわけではありません。:-(
mlepage

2
私は埋め込みSQLとPythonスクリプトについてこれを自分で考えていました。たぶんgccがC ++ 98モードでそれをすり抜けさせてくれればいいのにと思っていましたが、残念ながらできません。
emsr

3
私はclangとgccに慣れています。このコンパイラでは、C ++ 0xまたはc ++ 11のフラグを設定する必要があります。Lookin na MSのWebサイトは、未加工のリテラルがまだないようです。C ++の機能が実装されると、MSが新しいコンパイラの更新をより早くリリースすることを理解しています。Visual C ++コンパイラ2012年11月CTP [ microsoft.com/en-us/download/details.aspx?id=35515]で最新の最先端を探してください。
emsr 2013年

5
@rsethc コードブロックをコメント化するには、#if 0#endifを使用します。巣も。
bobbogo 2017

1
ヴォゴンの詩に触発されました!
Thane Plummer、

27

#define MULTILINE(...) #__VA_ARGS__
括弧内のすべてを消費します。
任意の数の連続する空白文字を1つのスペースに置き換えます。


1
\n改行が必要な場合は追加できます
Simon

ことを注意` (and hence \ nは) is copied literally, but 「`に変換される\"。だから、のMULTILINE(1, "2" \3)利回り"1, \"2\" \3"
アンドレアス・スピンドラー

@AndreasSpindler引用符と円記号は、文字列または文字リテラルトークン内にある限り、(追加の)円記号によってエスケープされます。あなたのポイントが何であるかわからない。一致しない引用符(二重または単一)を持つことは違法であるため、収縮が機能しないか、とにかく奇数になり、おそらく最大の欠点です。とにかく+1。「本物のプログラマー」は常に収縮をペアで使用し、間に改行を挿入しないので、単一引用符のバランスが取れます。
Potatoswatter 2013年

ポイントは、「括弧内はすべて消費する」と書いたということです。
Andreas Spindler 2013年

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__ように、の使用を許可します,


いくつかのluaコードスニペットをc ++に含めたいプロジェクトの場合、結局、小さなpythonスクリプトを作成して、複数行の文字列を入力して、c ++ソースファイルを生成させました。
bcmpinc 2012

ユニットテスト用にcolladaファイルから巨大な複数行のフロートリスト文字列を追加するのに最適です。どこにでも引用するのは面倒でしたが、コピー&ペーストのソリューションが必要でした。
ソイレントグラハム

7
#define MULTILINE(...) #__VA_ARGS__文字列にコンマを含める場合に使用できます。
Simon

2
これにより、ほとんどすべての余白(すべて\nとを含む\r)が取り除かれます。これは、場合によっては便利で、他の場合には致命的です。
BCS

17

これを行うこともできます:

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

2
おかげで、これは素晴らしいです。Cでもchar longString[] = R""""( This is a very long string )""""; 動作します。明らかに、私にとっても動作します。
struggling_learner

2
これは文字列を新しい行で開始および終了しますか?
Tim MB

1
それはだ、生の文字列リテラル。C ++ 11以降で使用可能です。
ミコラサン

15

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

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

@unwindの回答とどう違うのですか?
Sisir

1
@Sisirリラックスする2分前に投稿しました。
エリック

その部分が欠けていることをお詫びします。私の+1
Sisir

10

オンスの経験は理論のトンの価値があるので、私はのための小さなテストプログラムを試しました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

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


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

コードスニペットだけでなく、解答に説明を追加してください
Geordie

-1

オプション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()を使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.