Как выровнять вывод строки по центру в C

В языке C можно выводить данные с заданной фактической длиной, например для чисел это будет выглядеть так printf("|%5d|", 7); и вывод будет выглядеть так | 7|, так он равняет по правому краю, можно выровнять по левому краю, если поставить минус printf("|%-4d|", 7); будет так |7 |. А можно как-то выровнять по центру, чтобы было вот так | 7 | ?


Ответы (1 шт):

Автор решения: eanmos

Из коробки printf так не умеет, придется писать что-то свое:

int
print_centered_string_to_stream(FILE *stream, const char *s, unsigned int width)
{
    const size_t len = strlen(s);

    /* If the length of the string is greater than the width
     * just print the original string. */
    if (len >= width)
        return fprintf(stream, "%s", s);

    /* Calculate the padding. */
    const unsigned int p = (len >= width) ? 0 : (width - len) / 2;

    return fprintf(stream, "%*.*s%s%*.*s", p, p, " ", s, p, p, " ");
}

Однако GNU C Library позволяет добавлять свои спецификаторы для printf. Ради интереса можно попробовать добавить свой спецификатор, который будет выводить строку по центру.

Для добавления нового спецификатора используется функция register_printf_specifier. Мы должны передать ей три аргумента: сам символ спецификатора, функция вывода, и функция, которая даст printf информацию о типе аргументов:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <printf.h>

int
print_centered_string_to_stream(FILE *stream, const char *s, unsigned int width)
{
    const size_t len = strlen(s);

    /* If the length of the string is greater than the width
     * just print the original string. */
    if (len >= width)
        return fprintf(stream, "%s\n", s);

    /* Calculate the padding. */
    const unsigned int p = (len >= width) ? 0 : (width - len) / 2;

    return fprintf(stream, "%*.*s%s%*.*s", p, p, " ", s, p, p, " ");
}

int
printf_centered_string(FILE *stream, const struct printf_info *info, const void *const *args)
{
    const char *s = *((const char **) (args[0]));
    return print_centered_string_to_stream(stream, s, info->width);
}

int
printf_centered_string_arginfo(const struct printf_info *info, size_t n, int *argtypes, int *size)
{
    if (n > 0)
        argtypes[0] = PA_POINTER;

    return 1;
}

int
main(void)
{
    register_printf_specifier('Q', printf_centered_string, printf_centered_string_arginfo);

    printf("|%40Q|\n", "Hello, World");
    printf("|%80Q|\n", "Hello, World");
    printf("|%25Q|\n", "Hello, World");
}


Обратите внимание, что в документации GNU используется устаревшая функция register_printf_function.

→ Ссылка