web-dev-qa-db-fra.com

Centrer des chaînes avec printf ()

Par défaut, printf() semble aligner les chaînes à droite.

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

Je peux aussi aligner le texte à gauche comme ceci:

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

Existe-t-il un moyen rapide de centrer le texte? Ou dois-je écrire une fonction qui transforme une chaîne telle que test en (space)(space)test(space)(space) si la largeur du texte pour cette colonne est 8?

20
Pieter

printf par lui-même ne peut pas faire l'affaire, mais vous pouvez jouer avec la largeur "indirecte", qui spécifie la largeur en la lisant à partir d'un argument. Essayons ceci (ok, pas parfait)

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;
}
28
Giuseppe Guerrini

@ GiuseppeGuerrini a été utile, en suggérant comment utiliser les spécificateurs de format d'impression et en divisant les espaces. Malheureusement, cela peut tronquer du texte.

Ce qui suit résout le problème de la troncature (à condition que le champ spécifié soit suffisamment grand pour contenir le texte). 

void centerText(char *text, int fieldWidth) {
    int padlen = (fieldWidth - strlen(text)) / 2;
    printf(%*s%s%*s\n", padLen, "", text, padlen, "");
} 
4
clearlight

Il n'y a pas de spécificateur de format printf() pour centrer le texte.

Vous devrez écrire votre propre fonction ou localiser une bibliothèque fournissant les fonctionnalités que vous recherchez.

1
Convict

Vous pouvez essayer d’écrire votre propre fonction pour ce problème.

/**
 * 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;
}

Résultats:

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!!!
1
Seti Volkylany

Ill drop 2 cent après avoir eu à faire avec le même problème d'essayer de centrer les en-têtes d'une table dans une rangée avec printf.

Les macros suivantes devront être imprimées avant/après le texte et s'aligneront quelle que soit la longueur du texte lui-même . Notez que si nous avons des chaînes de longueur impaire, nous n'alignerons pas comme il se doit (car la déviation normale entraînera Il faut donc procéder à un tour d’horizon, et je pense que c’est la manière élégante de résoudre ce problème:

#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))

Exemple d'utilisation:

printf("%*s%*s" , CALC_CENTER_POSITION_PREV(MY_COLUMN_WIDTH, "Header")
                , "Header"
                , CALC_CENTER_POSITION_POST(MY_COLUMN_WIDTH, "Header"), "");
0
Sielar

Oui, vous devrez soit écrire votre propre fonction qui renvoie "test", par exemple.

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

Ou vous avez une fonction center_print, quelque chose comme:

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);
        }
}
0
hlovdal