Можно ли в 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);
qrdl
источник
6
Первый уже предлагался, второй страдает тем, что он ломается, если после '\' есть пробелы ; ошибка, которая может сбивать с толку, когда она возникает.
Клиффорд
1
Ни один из этих двух примеров не имеет ничего общего с препроцессором C.
Дэн Молдинг
@Dan, мой cpp, кажется, понимает / (см. Мою правку выше). Я не уверен, что это стандартное поведение.
sigjuice
@Dan В то время как объединение соседних литералов может быть выполнено с помощью препроцессора или компилятора (на последнем этапе перед фактической компиляцией), обработка продолжения строки выполняется препроцессором, потому что в противном случае многострочные макросы не могут быть реализованы. Также см. Здесь - gcc.gnu.org/onlinedocs/cpp/Initial-processing.html
qrdl
2
@qrdl: Плохо, по поводу второго вы правы. Продолжение строки всегда выполняется препроцессором. Иногда мне нужно напоминать, что я не всезнайка;) Я все же думаю, что в обычном случае компилятор присоединяет строковые литералы.
Дэн Молдинг
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
источник
Здесь нет ничего функционального, но новая идея, которую я никогда раньше не видел. Нравится, отличный комментарий @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); 
Антуан Мабула
источник