Kann in C eine lange printf-Anweisung in mehrere Zeilen unterteilt werden?

85

Ich habe die folgende Aussage:

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

Ich möchte es auflösen. Ich habe Folgendes versucht, aber es funktioniert nicht.

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

Wie kann ich es auflösen?

Neuromant
quelle
1
Einige gute Vorschläge, aber keiner von ihnen ist möglicherweise so klar oder wartbar wie nur vier separate printf () -Aufrufe.
Clifford
@ Clifford: Dann könnten Sie C ++ schreiben, damit Cout für Sie besser aussieht.
Test

Antworten:

170

Wenn Sie ein Zeichenfolgenliteral in mehrere Zeilen aufteilen möchten, können Sie mehrere Zeichenfolgen miteinander verketten, eine in jeder Zeile, wie folgt:

printf("name: %s\t"
"args: %s\t"
"value %d\t"
"arraysize %d\n", 
sp->name, 
sp->args, 
sp->value, 
sp->arraysize);
James McNellis
quelle
85
Nur ein Kommentar, um die wenig bekannte C-Tatsache zu erklären, dass Leerzeichen zwischen zwei Zeichenfolgen eine Verkettung sind.
Brian Postow
2
@Lundin Es ist für mich viel einfacher, jede Variable und ihren Wert klar in einer eigenen Zeile darzustellen. Können Sie sich einen Debugger in einer IDE vorstellen, der alle Variablen und Werte in einer einzigen Zeile zusammenfasst? Ich kann nicht (Ja, ich weiß, dass es keine Zeilenumbrüche zwischen die einzelnen Zeichenfolgen setzt, aber ich vergleiche die Lesbarkeit des Quellcodes mit der Lesbarkeit von Variablen in einem Debugger.)
byxor
Wird diese Verkettung vom Präprozessor vorgenommen?
Debüt
20

Nur einige andere Formatierungsoptionen:

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);

Sie können Variationen zum Thema hinzufügen. Die Idee ist, dass die printf()Konvertierungsspezifizierer und die jeweiligen Variablen alle "schön" ausgerichtet sind (für einige Werte von "schön").

pmg
quelle
Hier funktioniert nichts, aber eine neuartige Idee, die ich noch nie gesehen habe. Ich mag es, toller Kommentar @pmg!
RPJ
19

Der C-Compiler kann benachbarte String-Literale wie folgt zu einem zusammenfügen

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

Der Präprozessor kann einen Backslash als letztes Zeichen der Zeile verwenden, ohne CR (oder CR / LF, wenn Sie aus Windowsland stammen):

printf("foo %s \
bar: %d", foo, bar);
qrdl
quelle
6
Das erste wurde bereits vorgeschlagen, das zweite leidet unter der Tatsache, dass es bricht, wenn nach dem '\' ein Leerzeichen steht ; Ein Fehler, der verwirrend sein kann, wenn er auftritt.
Clifford
1
Keines dieser beiden Beispiele hat etwas mit dem C-Präprozessor zu tun.
Dan Moulding
@ Dan mein cpp scheint zu verstehen / (siehe meine Bearbeitung oben). Ich bin mir nicht sicher, ob dies Standardverhalten ist.
Sigjuice
@Dan Während das Verbinden benachbarter Literale entweder mit dem Präprozessor oder dem Compiler (in der letzten Phase vor der eigentlichen Kompilierung) ausgeführt werden kann, wird die Fortsetzung der Verarbeitungszeile vom Präprozessor ausgeführt, da ansonsten mehrzeilige Makros nicht implementiert werden können. Siehe auch hier - gcc.gnu.org/onlinedocs/cpp/Initial-processing.html
qrdl
2
@qrdl: Mein schlechtes, du hast Recht mit dem zweiten. Die Leitungsfortsetzung erfolgt immer durch den Präprozessor. Manchmal muss ich daran erinnert werden, dass ich kein Besserwisser bin ;) Ich denke immer noch, dass der Compiler im Normalfall String-Literale verbindet.
Dan Moulding
3

Die De-facto-Standardmethode zum Aufteilen komplexer Funktionen in C ist pro Argument:

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

Oder wenn Sie so wollen:

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

Sie sollten die Zeichenfolge nicht aufteilen oder \eine C-Linie unterbrechen. Ein solcher Code wird schnell völlig unlesbar / nicht mehr wartbar.

Lundin
quelle
3

Ich denke nicht, dass die Verwendung einer printfAnweisung zum Drucken von Zeichenfolgenliteralen wie oben gezeigt eine gute Programmierpraxis ist. Vielmehr kann man den folgenden Code verwenden:

printf("name: %s\t",sp->name);
printf("args: %s\t",sp->args);
printf("value: %s\t",sp->value);
printf("arraysize: %s\t",sp->name); 
Antoine Maboula
quelle