Cでは、長いprintfステートメントを複数の行に分割できますか?


86

私は次のステートメントを持っています:

printf("name: %s\targs: %s\tvalue %d\tarraysize %d\n", sp->name, sp->args, sp->value, sp->arraysize);

解散したいです。以下を試しましたが、うまくいきません。

printf("name: %s\t
args: %s\t
value %d\t
arraysize %d\n", 
sp->name, 
sp->args, 
sp->value, 
sp->arraysize);

どうすれば分割できますか?


1
いくつかの良い提案がありますが、どちらも4つの別々のprintf()呼び出しほど明確でも保守可能でもありません。
クリフォード

@Clifford:C ++を記述して、coutの見栄えを良くすることができます。
テスト

回答:


173

文字列リテラルを複数の行に分割する場合は、次のように、各行に1つずつ、複数の文字列を連結できます。

printf("name: %s\t"
"args: %s\t"
"value %d\t"
"arraysize %d\n", 
sp->name, 
sp->args, 
sp->value, 
sp->arraysize);

85
2つの文字列間の空白が連結であるというあまり知られていないCの事実を説明するためにコメントするだけです。
Brian Postow

2
@Lundin各変数とその値をそれぞれの行に明確に表すと、私にとってはるかに読みやすくなります。すべての変数と値を1行にまとめるIDEのデバッガーを想像できますか?できません。(はい、各文字列の間に改行文字が挿入されないことはわかっていますが、ソースコードの可読性をデバッガーの変数の可読性と比較しています)
byxor 2017

この連結はプリプロセッサによって行われますか?
debuti 2017

21

Cコンパイラは、次のように、隣接する文字列リテラルを1つに接着できます。

printf("foo: %s "
       "bar: %d", foo, bar);

プリプロセッサは、CR(または、Windowslandの場合はCR / LF)をカウントせずに、行の最後の文字としてバックスラッシュを使用できます。

printf("foo %s \
bar: %d", foo, bar);

6
最初のものはすでに提案されていますが、2番目のものは'\'のに空白があると壊れてしまうという事実に悩まされています。発生時に困惑する可能性のあるバグ。
クリフォード

1
これらの2つの例はどちらも、Cプリプロセッサとはまったく関係がありません。
ダンモールディング

@Dan私のcppは/を理解しているようです(上記の私の編集を参照)。これが標準的な動作かどうかはわかりません。
sigjuice 2009年

@Dan隣接するリテラルの結合は、プリプロセッサまたはコンパイラのいずれかで実行できますが(実際のコンパイル前の最終段階)、行継続の処理はプリプロセッサによって実行されます。そうしないと、複数行のマクロを実装できないためです。また、ここを参照してください- gcc.gnu.org/onlinedocs/cpp/Initial-processing.html
qrdl

2
@qrdl:私の悪い、あなたは2番目のものについて正しいです。行の継続は常にプリプロセッサによって行われます。時々、私はすべてを知っているわけでないことを思い出させる必要があります;)しかし、通常の場合、コンパイラは文字列リテラルを結合すると思います。
ダンモールディング

20

その他のフォーマットオプション:

printf("name: %s\targs: %s\tvalue %d\tarraysize %d\n", 
        a,        b,        c,        d);

printf("name: %s\targs: %s\tvalue %d\tarraysize %d\n", 
              a,        b,        c,            d);

printf("name: %s\t"      "args: %s\t"      "value %d\t"      "arraysize %d\n", 
        very_long_name_a, very_long_name_b, very_long_name_c, very_long_name_d);

テーマにバリエーションを追加できます。printf()変換スペシフィサーとそれぞれの変数がすべて「nicely」に並んでいるという考え方です(「nicely」の値によっては)。


ここでは機能的なものはありませんが、これまでに見たことのない斬新なアイデアです。私はそれが好きです、素晴らしいコメント@pmg!
rpj 2009年

3

Cで複雑な関数を分割するデファクトスタンダードの方法は、引数ごとです。

printf("name: %s\targs: %s\tvalue %d\tarraysize %d\n", 
       sp->name, 
       sp->args, 
       sp->value, 
       sp->arraysize);

または、次の場合:

const char format_str[] = "name: %s\targs: %s\tvalue %d\tarraysize %d\n";
...
printf(format_str, 
       sp->name, 
       sp->args, 
       sp->value, 
       sp->arraysize);

文字列を分割したり、\C行を分割するために使用したりしないでください。このようなコードはすぐに完全に読み取り不能/保守不能になります。


3

printf上記のように1つのステートメントを使用して文字列リテラルを出力することは、優れたプログラミング手法ではないと思います。むしろ、以下のコードを使用できます。

printf("name: %s\t",sp->name);
printf("args: %s\t",sp->args);
printf("value: %s\t",sp->value);
printf("arraysize: %s\t",sp->name); 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.