Центрирование строк с помощью printf () - PullRequest
22 голосов
/ 17 марта 2010

По умолчанию printf(), кажется, выравнивает строки вправо.

printf("%10s %20s %20s\n", "col1", "col2", "col3");
/*       col1                 col2                 col3 */

Я также могу выровнять текст по левому краю так:

printf("%-10s %-20s %-20s", "col1", "col2", "col3");

Есть ли быстрый способ центрировать текст? Или мне нужно написать функцию, которая превращает строку типа test в (space)(space)test(space)(space), если ширина текста для этого столбца равна 8?

Ответы [ 7 ]

29 голосов
/ 17 марта 2010

printf сама по себе не может добиться цели, но вы можете поиграть с «косвенной» шириной, которая определяет ширину, считывая ее из аргумента. Давайте попробуем это (хорошо, не идеально)

void f(char *s)
{
        printf("---%*s%*s---\n",10+strlen(s)/2,s,10-strlen(s)/2,"");
}
int main(int argc, char **argv)
{
        f("uno");
        f("quattro");
        return 0;
}
6 голосов
/ 25 ноября 2018

@ GiuseppeGuerrini's был полезен, предлагая, как использовать спецификаторы формата печати и разделяя пробел. К сожалению, он может усекать текст.

Следующее решает проблему усечения (при условии, что указанное поле на самом деле достаточно велико, чтобы вместить текст).

void centerText(char *text, int fieldWidth) {
    int padlen = (fieldWidth - strlen(text)) / 2;
    printf(%*s%s%*s\n", padLen, "", text, padlen, "");
} 
2 голосов
/ 15 февраля 2017

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

/**
 * Returns a sting "str" centered in string of a length width "new_length".
 * Padding is done using the specified fill character "placeholder".
 */
char *
str_center(char str[], unsigned int new_length, char placeholder)
{
    size_t str_length = strlen(str);

    // if a new length is less or equal length of the original string, returns the original string
    if (new_length <= str_length)
        return str;

    char *buffer;
    unsigned int i, total_rest_length;

    buffer = malloc(sizeof(char) * new_length);

    // length of a wrapper of the original string
    total_rest_length = new_length - str_length;

    // write a prefix to buffer
    i = 0;
    while (i < (total_rest_length / 2)) {
        buffer[i] = placeholder;
        ++i;
    }
    buffer[i + 1] = '\0';

    // write the original string
    strcat(buffer, str);

    // write a postfix to the buffer
    i += str_length;
    while (i < new_length) {
        buffer[i] = placeholder;
        ++i;
    }
    buffer[i + 1] = '\0';

    return buffer;
}

Результаты:

puts(str_center("A", 0, '-')); // A
puts(str_center("A", 1, '-')); // A
puts(str_center("A", 10, '-')); // ----A-----
puts(str_center("text", 10, '*')); // ***text***
puts(str_center("The C programming language", 26, '!')); // The C programming language
puts(str_center("The C programming language", 27, '!')); // The C programming language!
puts(str_center("The C programming language", 28, '!')); // !The C programming language!
puts(str_center("The C programming language", 29, '!')); // !The C programming language!!
puts(str_center("The C programming language", 30, '!')); // !!The C programming language!!
puts(str_center("The C programming language", 31, '!')); // !!The C programming language!!!
2 голосов
/ 17 марта 2010

Нет спецификатора формата printf() для центрирования текста.

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

0 голосов
/ 09 декабря 2018

Я потерял 2 цента после того, как столкнулся с похожей проблемой, связанной с попыткой центрировать заголовки таблицы подряд с помощью printf.

Следующие макросы необходимо будет напечатать до / после текста и выровнять независимо от длины самого текста. Обратите внимание, что если у нас есть строки нечетной длины, мы не выровняем как следует (потому что нормальное отклонение приведет к отсутствию пробела). Для этого требуется сводка, и я думаю, что это элегантный способ решить эту проблему:

#define CALC_CENTER_POSITION_PREV(WIDTH, STR) (((WIDTH + ((int)strlen(STR))) % 2) \
       ? ((WIDTH + ((int)strlen(STR)) + 1)/2) : ((WIDTH + ((int)strlen(STR)))/2))
#define CALC_CENTER_POSITION_POST(WIDTH, STR) (((WIDTH - ((int)strlen(STR))) % 2) \
       ? ((WIDTH - ((int)strlen(STR)) - 1)/2) : ((WIDTH - ((int)strlen(STR)))/2))

Пример использования:

printf("%*s%*s" , CALC_CENTER_POSITION_PREV(MY_COLUMN_WIDTH, "Header")
                , "Header"
                , CALC_CENTER_POSITION_POST(MY_COLUMN_WIDTH, "Header"), "");
0 голосов
/ 13 апреля 2015

Вы можете использовать любой из следующих двух вариантов:

char name[] = "Name1";

//Option One
printf("%*s", 40+strlen(name)/2, name, 40-strlen(name)/2, "");
puts("");//skip one line
//Option two
printf("%*s", 40+strlen("Name2")/2, "Name2", 40-strlen("Name2")/2, "");

Вывод:

Name1 (центр)
Name2 (центр)

0 голосов
/ 17 марта 2010

Да, вам придется написать собственную функцию, которая возвращает «тест» и т. Д., Например,

printf("%s %s %s", center("col1", 10), center("col2", 20), center("col3", 20));

Или у вас есть функция center_print, например:

void center_print(const char *s, int width)
{
        int length = strlen(s);
        int i;
        for (i=0; i<=(width-length)/2; i++) {
                fputs(" ", stdout);
        }
        fputs(s, stdout);
        i += length;
        for (; i<=width; i++) {
                fputs(" ", stdout);
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...