54
#define SIZE 9
int number=5;
char letters[SIZE]; /* this wont be null-terminated */
... 

char fmt_string[20];
sprintf(fmt_string, "%%d %%%ds", SIZE);
/* fmt_string = "%d %9d"... or it should be */

printf(fmt_string, number, letters);

Is there a better way to do this?

William Entriken
  • 37,208
  • 23
  • 149
  • 195
  • You seem to be building a format string. But you should be assigning the string returned by `sprintf` to `fmt_string` and `fmt_string` shouldn't be in the parameter list. – pavium May 09 '11 at 03:41
  • Is there any particular reason you say that `letters` won't be null-terminated? – Andrew Keeton May 09 '11 at 03:53
  • 1
    @AndrewKeeton this was for a search problem with a large dataset where I couldn't afford the space to hold null characters. – William Entriken Oct 11 '14 at 19:46
  • NOTE: this is a duplicity of http://stackoverflow.com/questions/2239519/is-there-a-way-to-specify-how-many-characters-of-a-string-to-print-out-using-pri – pevik Sep 02 '16 at 08:31

2 Answers2

132

There is no need to construct a special format string. printf allows you to specify the precision using a parameter (that precedes the value) if you use a .* as the precision in the format tag.

For example:

printf ("%d %.*s", number, SIZE, letters);

Note: there is a distinction between width (which is a minimum field width) and precision (which gives the maximum number of characters to be printed). %*s specifies the width, %.s specifies the precision. (and you can also use %*.* but then you need two parameters, one for the width one for the precision)

See also the printf man page (man 3 printf under Linux) and especially the sections on field width and precision:

Instead of a decimal digit string one may write "*" or "*m$" (for some decimal integer m) to specify that the precision is given in the next argument, or in the m-th argument, respectively, which must be of type int.

mah
  • 39,056
  • 9
  • 76
  • 93
Trent
  • 13,249
  • 4
  • 39
  • 36
6

A somewhat unknown function is asprintf. The first parameter is a **char. This function will malloc space for the string so you don't have to do the bookkeeping. Remember to free the string when done.

char *fmt_string;

asprintf(&fmt_string, "%%d %%%ds", SIZE);
printf(fmt_string, number, letters);
free(fmt_string);

is an example of use.

Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
No One in Particular
  • 2,846
  • 4
  • 27
  • 32
  • 3
    Although asprintf is indeed an interesting function, it is important to note that it is a gnu extention. Also, I'm not sure how this addresses the question. – Trent May 09 '11 at 04:20
  • 2
    @Trent, it's true that it started as a GNU extension, but in the mean time [OpenBSD](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/asprintf.3), [FreeBSD](http://www.freebsd.org/cgi/man.cgi?query=asprintf) and [NetBSD](http://netbsd.gw.com/cgi-bin/man-cgi?asprintf) have implemented it. Even [Mac OS X](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/asprintf.3.html) has it now. – Cristian Ciupitu Oct 14 '14 at 01:09