Czy w C można podzielić długą instrukcję printf na wiele linii?


86

Mam następujące oświadczenie:

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

Chcę to zerwać. Próbowałem wykonać następujące czynności, ale to nie działa.

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

Jak mogę to rozbić?


1
Podano kilka dobrych sugestii, ale żadna z nich nie może być tak jasna ani łatwa do utrzymania, jak tylko cztery oddzielne wywołania printf ().
Clifford

@Clifford: wtedy mógłbyś napisać C ++, żeby cout wyglądał lepiej dla ciebie.
Przetestuj

Odpowiedzi:


173

Jeśli chcesz podzielić literał ciągu na wiele wierszy, możesz połączyć wiele ciągów razem, po jednym w każdym wierszu, na przykład:

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

85
tylko komentując, aby wyjaśnić mało znany fakt w C, że białe znaki między dwoma ciągami znaków to konkatenacja.
Brian Postow

2
@Lundin Posiadanie każdej zmiennej i jej wartości jasno przedstawionej w osobnym wierszu jest dla mnie znacznie łatwiejsze do odczytania. Czy możesz sobie wyobrazić debugera w środowisku IDE, który umieszcza wszystkie zmienne i wartości w jednym wierszu? Nie mogę. (Tak, wiem, że nie umieszcza znaków nowej linii między każdym ciągiem, ale porównuję czytelność kodu źródłowego z czytelnością zmiennych w debugerze)
byxor.

Czy ta konkatenacja jest wykonywana przez preprocesor?
debiut

21

Kompilator C może skleić sąsiednie literały ciągów w jeden, na przykład

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

Preprocesor może użyć odwrotnego ukośnika jako ostatniego znaku linii, nie licząc CR (lub CR / LF, jeśli jesteś z Windowsland):

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

6
Pierwsza została już zasugerowana, druga cierpi z powodu tego, że pęka, jeśli po znaku „\” występuje spacja ; błąd, który może być kłopotliwy, gdy się pojawi.
Clifford,

1
Żaden z tych dwóch przykładów nie ma nic wspólnego z preprocesorem C.
Dan Molding

@Dan, mój CPP wydaje się rozumieć / (zobacz moją edycję powyżej). Nie jestem pewien, czy jest to standardowe zachowanie.
sigjuice

@Dan Podczas gdy łączenie sąsiednich literałów może odbywać się za pomocą preprocesora lub kompilatora (na ostatnim etapie przed właściwą kompilacją), obsługa kontynuacji linii jest wykonywana przez preprocesor, ponieważ w przeciwnym razie makra wielowierszowe nie mogą zostać zaimplementowane. Zobacz także tutaj - gcc.gnu.org/onlinedocs/cpp/Initial-processing.html
qrdl

2
@qrdl: Mój błąd, masz rację co do drugiego. Kontynuacja linii jest zawsze wykonywana przez preprocesor. Czasami muszę być przypomniał, że jestem nie know-it-all;) ja nadal uważam, że w normalnym przypadku kompilator dołącza literały ciągów znaków, choć.
Dan Molding

20

Tylko kilka innych opcji formatowania:

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

Możesz dodać warianty motywu. Chodzi o to, że printf()speficiers konwersji i odpowiednie zmienne są wszystkie ustawione w jednej linii „ładnie” (dla niektórych wartości „ładnie”).


Nie ma tu nic funkcjonalnego, ale nowatorski pomysł, którego nigdy wcześniej nie widziałem. Podoba mi się, świetny komentarz @pmg!
rpj

3

De facto standardowy sposób dzielenia złożonych funkcji w C jest na argument:

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

Lub jeśli chcesz:

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

Nie powinieneś rozdzielać łańcucha ani używać go \do łamania linii C. Taki kod szybko staje się całkowicie nieczytelny / nie do utrzymania.


3

Nie sądzę, aby użycie jednej printfinstrukcji do wydrukowania literałów łańcuchowych, jak widać powyżej, jest dobrą praktyką programistyczną; można raczej użyć fragmentu kodu poniżej:

printf("name: %s\t",sp->name);
printf("args: %s\t",sp->args);
printf("value: %s\t",sp->value);
printf("arraysize: %s\t",sp->name); 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.