Sep 8, 2016

C Programming #89: printf - %n specifier

C Programming #89: printf - %n specifier

This article explains format specifier %n which can be used in printf. Already other format specifiers are covered C Programming #87: stdio - printf, scanf and C Programming #88: stdio - insane formating in printf.


All format specifier used in printf will result in printing something on stdout, except %n. %n gets the number of characters printed till then to stdout and assigns to variable. Since it modifies the variable we need to pass the address of the variable.

Lets take a small example of printing the dialogues from the movie inception in the following format.

Dominick Cobb: [holding Saito's gun in his lap] 
               You came prepared.

Saito: Not even my head of security knows about 
       this apartment. How did you find out?

Dominick Cobb: Very difficult for a man in your 
               position to keep a love nest 
               like this secret, particularly 
               when there's a married woman 
               involved.

Saito: She would never

Dominick Cobb: Yet, here we are.

Say all the dialogues are placed in array of struct. We need to fold the lines after 48 characters. Note we need to give enough space after the name of character is printed.

#include <stdio.h>
#define TOTAL_WIDTH 48
typedef struct dialogue_tag
{
   char *ch; /* Character Name */
   char *se; /* Dialogue Sentence */
}dialogue_t;
int main()
{ 
   dialogue_t inception[5] = 
     { {"Dominick Cobb",
        "[holding Saito's gun in his lap] You came prepared."},
       {"Saito", 
        "Not even my head of security knows about this apartment."
        "How did you find out?"},
       {"Dominick Cobb",
        "Very difficult for a man in your position to keep a love nest" 
        "like this secret, particularly"
        "when there's a married woman "
        "involved."},
       {"Saito", "She would never",},
       {"Dominick Cobb", "Yet, here we are."}};
   int i, j;
   int width, diag_width;

   for(i = 0; i < 5; i++) {
      printf("%s : %n", inception[i].ch, &width);
      diag_width = TOTAL_WIDTH - width;
      for(j = 0; j < (strlen(inception[i].se) / diag_width); j++) {
        printf("%.*s", diag_width, inception[i].se + j*diag_width);
        printf("\n%*s", width, "");
      }
      printf("%.*s\n", diag_width, inception[i].se + j*diag_width);
      printf("\n");
   }

   return 0;
}
Dominick Cobb : [holding Saito's gun in his lap]
                 You came prepared.

Saito : Not even my head of security knows about
         this apartment.How did you find out?

Dominick Cobb : Very difficult for a man in your
                 position to keep a love nest lik
                e this secret, particularly when 
                there's a married woman involved
                .

Saito : She would never

Dominick Cobb : Yet, here we are.

Output could be improved a lot, it is pretty ok compared to size of program. Note to print only 10 characters in a string we could use the following construct.

printf("%.10s", temp);

Now if the number of characters to be printed in variable, then following construct can be used.

printf("%.*s", width, temp);

Above construct is used in above program.

No comments :

Post a Comment