Как форматировать строки с помощью printf (), чтобы получить на выходе одинаковую длину?

97

У меня есть две функции: одна создает такие сообщения, Starting initialization...а другая проверяет коды возврата и выходные данные "Ok", "Warning"или "Error". Однако получаемый результат имеет разную длину:

Starting initialization...Ok.
Checking init scripts...Ok.

Как я могу получить что-то подобное:

Starting initialization...       Ok.
Checking init scripts...         Ok.
Психоделия
источник

Ответы:

164

Вы можете указать ширину в строковых полях, например

printf("%-20s", "initialization...");

а затем все, что напечатано с этим полем, будет заполнено пробелами до указанной вами ширины.

-Левый оправдывает текст в этой области.

Карл Смотрич
источник
130
Увы, я недостаточно умен, чтобы считать так высоко. Тем не менее, я верю, что спрашивающий достаточно умен, чтобы экстраполировать из моего примера :)
Карл Смотрич
3
как насчет оправданного права? В K&R не упоминаются никакие флаги
Ungeheuer
9
По умолчанию используется выравнивание по правому краю Без a -ваши данные будут выровнены по правому краю в поле, ширину которого вы указали.
Карл Смотрич
25

printfпозволяет форматировать с помощью спецификаторов ширины. например


printf( "%-30s %s\n", "Starting initialization...", "Ok." );

Вы можете использовать спецификатор отрицательной ширины, чтобы указать выравнивание по левому краю, поскольку по умолчанию используется выравнивание по правому краю.

PP.
источник
20

Кроме того, если вам нужна гибкость в выборе width, вы можете выбрать один из следующих двух форматов (с усечением или без него):

int width = 30;
//no truncation uses %-*s
printf( "%-*s %s\n", width, "Starting initialization...", "Ok." );
// output is "Starting initialization...     Ok."

//truncated to the specified width uses %-.*s
printf( "%-.*s %s\n", width, "Starting initialization...", "Ok." ); 
// output is "Starting initialization... Ok."
жизненный баланс
источник
13

Также есть %nмодификатор, который может помочь в определенных обстоятельствах. Он возвращает столбец, в котором до сих пор находилась строка. Пример: вы хотите написать несколько строк, которые находятся в пределах ширины первой строки, как таблица.

int width1, width2;
int values[6][2];
printf("|%s%n|%s%n|\n", header1, &width1, header2, &width2);

for(i=0; i<6; i++)
   printf("|%*d|%*d|\n", width1, values[i][0], width2, values[i][1]);

напечатает 2 колонки одинаковой ширины по длине любых двух строк header1и header2может иметь. Я не знаю, есть ли у всех реализаций, %nно у Solaris и Linux есть.

Патрик Шлютер
источник
Это решение работает, но любой, кто воспользуется этим и вставит это в свой код, должен осознавать риск возникновения уязвимостей памяти .
Мэтью Коул,
0

Существует также довольно низкотехнологичное решение - подсчет вручную добавлять пробелы, чтобы ваши сообщения выстраивались в линию. Ничто не мешает вам включать несколько конечных пробелов в строки сообщения.

Карл Смотрич
источник
-2

Начните с использования вкладок, \ t модификатора символа . Он переместится в фиксированное место (столбцы, терминальный жаргон). Однако это не помогает, если есть различия, превышающие ширину столбца (4 символа, если я правильно помню).

Чтобы исправить это, напишите свой "OK / NOK", используя фиксированное количество табуляций (5? 6?, Попробуйте), затем верните ( \ r ) без новой строки и напишите свое сообщение.

jpinto3912
источник
5
Всегда существует опасность, что строка длиннее позиции табуляции, что приведет к неправильному выравниванию итоговой табуляции и текста.
пп.
Не совсем ... сначала напишите закладки OK / NOK, затем / r, теперь напишите фразу, теперь / n. Фраза могла перезаписать OK / NOK. Но твой путь лучше, я не знал о негативном оправдании.
jpinto3912