У 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
Дано кілька хороших пропозицій, але жодна з них не може бути настільки чіткою чи ремонтопридатною, як лише чотири окремі виклики printf ().
Кліффорд,

@Clifford: тоді ти міг написати C ++, щоб cout для тебе виглядав краще.
Тест

Відповіді:


173

Якщо ви хочете розбити рядковий літерал на кілька рядків, ви можете об'єднати кілька рядків разом, по одному в кожному рядку, приблизно так:

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

85
просто коментуючи, щоб пояснити маловідомий факт C, що пробіли між двома рядками є конкатенацією.
Брайан Постов

2
@Lundin Наявність кожної змінної та її значення чітко представлених у власному рядку для мене набагато легше прочитати. Чи можете ви уявити собі налагоджувач в IDE, який розміщує всі змінні та значення в одному рядку? Я не можу. (Так, я знаю, що між кожним рядком не вводяться символи нового рядка, але я порівнюю читабельність вихідного коду із доступністю змінних у налагоджувачі)
byxor

Чи здійснює цю конкатенацію препроцесор?
дебютувати

21

Компілятор C може склеювати сусідні літеральні рядки в один, наприклад

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

Препроцесор може використовувати зворотну косу риску як останній символ рядка, не враховуючи CR (або CR / LF, якщо ви з Windowsland):

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

6
Перший вже запропоновано, другий страждає від того, що він ламається, якщо після '\' є пробіли ; помилка, яка може спантеличити, коли вона виникає.
Кліффорд,

1
Жоден з цих двох прикладів взагалі не має нічого спільного з препроцесором C.
Dan Molding

@Dan мій cpp, схоже, розуміє / (див. Мою редакцію вище). Я не впевнений, що це стандартна поведінка.
sigjuice

@Dan Хоча приєднання сусідніх літералів може виконуватися або препроцесором, або компілятором (на останньому етапі перед фактичною компіляцією), обробка продовження рядка виконується препроцесором, оскільки в іншому випадку багаторядкові макроси не можуть бути реалізовані. Також дивіться тут - gcc.gnu.org/onlinedocs/cpp/Initial-processing.html
qrdl

2
@qrdl: Боже, ти маєш рацію щодо другого. Продовження рядка завжди робиться препроцесором. Іноді мені потрібно нагадати, що я не знаю все;) Я все ще думаю, що в звичайному випадку компілятор приєднується до рядкових літералів.
Dan Molding

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()специфіки перетворення та відповідні змінні вибудовуються в "красиво" (для деяких значень "красиво").


Тут нічого функціонального немає, але нова ідея, яку я ніколи раніше не бачив. Мені це подобається, чудовий коментар @pmg!
rpj

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твердження для друку рядкових літералів, як показано вище, є хорошою практикою програмування; скоріше, можна використовувати шматок коду нижче:

printf("name: %s\t",sp->name);
printf("args: %s\t",sp->args);
printf("value: %s\t",sp->value);
printf("arraysize: %s\t",sp->name); 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.