Centering strings with printf()
By default, printf()
seems to align strings to the right.
printf("%10s %20s %20s\n", "col1", "col2", "col3");
/* col1 col2 col3 */
I can also align text to the left like this:
printf("%-10s %-20s %-20s", "开发者_运维知识库col1", "col2", "col3");
Is there a quick way to center text? Or do I have to write a function that turns a string like test
into (space)(space)test(space)(space)
if the text width for that column is 8?
printf by itself can't do the trick, but you could play with the "indirect" width, which specifies the width by reading it from an argument. Lets' try this (ok, not perfect)
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;
}
@GiuseppeGuerrini's was helpful, by suggesting how to use print format specifiers and dividing the whitespace. Unfortunately, it can truncate text.
The following solves the problem of truncation (assuming the field specified is actually large enough to hold the text).
void centerText(char *text, int fieldWidth) {
int padlen = (fieldWidth - strlen(text)) / 2;
printf("%*s%s%*s\n", padLen, "", text, padlen, "");
}
There is no printf()
format specifier to centre text.
You will need to write your own function or locate a library which provides the functionality that you're looking for.
You may try write own function for this problem.
/**
* 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;
}
Results:
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!!!
Ill drop my 2 cents after dealing with similar issue of trying to center a table headers in a row with printf.
The following macros will need to be printed before/after the text and will align regardless of the length of the text itself. Notice that if we have odd length strings, we will not align as should(because the normal devision will result in missing space). Therefor a round up is needed, and I think this is the elegant way to solve that issue:
#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))
Usage example:
printf("%*s%*s" , CALC_CENTER_POSITION_PREV(MY_COLUMN_WIDTH, "Header")
, "Header"
, CALC_CENTER_POSITION_POST(MY_COLUMN_WIDTH, "Header"), "");
Yes, you will either have to write your own function that returns " test " etc, e.g.
printf("%s %s %s", center("col1", 10), center("col2", 20), center("col3", 20));
Or you have a center_print function, something like the following:
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);
}
}
A more compact version of PADYMKO's function above (which still leaks memory):
char *str_center(char str[], unsigned int new_length, char placeholder)
{
size_t str_length = strlen(str);
char *buffer;
/*------------------------------------------------------------------
* If a new length is less or equal length of the original string,
* returns the original string
*------------------------------------------------------------------*/
if (new_length <= str_length)
{
return(str);
}
buffer = malloc(sizeof(char) * (new_length + 1));
memset(buffer, placeholder, new_length);
buffer[new_length] = '\0';
bcopy(str, buffer + (( new_length - str_length) / 2), str_length);
return(buffer);
}
This sets the whole of newly allocated buffer to the padding character, null terminates that, and then drops the string to be centred into the middle of the buffer - no loops, or keeping track of where to copy to..
If you want to be able to use a printf()
format string for that and you accept to be limited to the GNU clib, you can extend printf()
with your own conversion specifier for centering a string with. Add the conversion specifier with register_printf_function()
.
See here for the documentation: https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html
The other answers already provide you with a solution on how to manually print a string in the center, which you still need when using your own conversion specifier.
You can use either of the following two options:
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, "");
The output is:
Name1(center)
Name2(center)
精彩评论