Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format string with multiple percent signs

I know %% is used to escape actual % signs in a string, so %%%ds will end up with %10s in the following format string, but I don't know why I need %%5s in this string?

After all, there are only two additional arguments (BUFFSIZE / 10).

#define BUFFSIZE 100
char buf[100]={0}
sprintf(buf, "%%5s %%%ds %%%ds", BUFFSIZE / 10, BUFFSIZE / 10);

After running the code above, the buf will contain the string,

%10s %10s 
like image 696
Matt Elson Avatar asked Jun 27 '17 09:06

Matt Elson


People also ask

How do you add a percent sign in string format?

You can do this by using %% in the printf statement. For example, you can write printf(“10%%”) to have the output appear as 10% on the screen.

What is %s in string format?

The %s operator is put where the string is to be specified. The number of values you want to append to a string should be equivalent to the number specified in parentheses after the % operator at the end of the string value.

How do you write a percent sign in a string in Python?

The %s signifies that you want to add string value into the string, it is also used to format numbers in a string. After writing the above code (what does %s mean in python), Ones you will print ” string “ then the output will appear as a “ Variable as string = 20 ”.

What are format specifiers in Python?

Python uses C-style string formatting to create new, formatted strings. The "%" operator is used to format a set of variables enclosed in a "tuple" (a fixed size list), together with a format string, which contains normal text together with "argument specifiers", special symbols like "%s" and "%d".


2 Answers

The purpose is to get a format string to use it in another function that needs a format string like sscanf().

With your code you get: %5s %10s %10s written to your buf, see online, which means it will accept three strings with a length identifier.

%%5s          --> %5s
%%%ds with 10 --> %10s (read it that way: {%%}{%d}{s})

That buffer %5s %10s %10s could now be used in a sscanf() call like shown here.

But there is a best practice to prevent a buffer overflow caused by sscanf() which is also described by Kernighan and Pike in their book The Practice of Programming, see here on SO.


The reason why you maybe can't use %*s may be, see here on SO:

For printf, the * allows you to specify minimum field width through an extra parameter, i.e. printf("%*d", 4, 100); specifies a field width of 4.

For scanf, the * indicates that the field is to be read but ignored, so that i.e. scanf("%*d %d", &i) for the input "12 34" will ignore 12 and read 34 into the integer i.

like image 147
Andre Kampling Avatar answered Sep 29 '22 05:09

Andre Kampling


% in itself is a valid conversion specifier. The prescribed syntax is, as mentioned in C11, chapter §7.21.6.1/P2, (emphasis mine)

Each conversion specification is introduced by the character %. After the %, the following appear in sequence:

  • Zero or more flags [...]

  • An optional minimum field width.

  • An optional precision [...]

  • An optional length modifier [...]

  • A conversion specifier character that specifies the type of conversion to be applied.

Then, from P8, for conversion specifiers

The conversion specifiers and their meanings are:

......

%

A % character is written. No argument is converted. The complete conversion specification shall be %%.

So, based on greedy approach, compiler will group a syntax like

 ....   %%%ds, BUFFSIZE / 10 ....

as

 {%%}{%d}{s}
  ^^--------------------------Replaced as %
      ^^----------------------Actual conversion specification happens, argument is used
         ^^------------------just part of final output

which finally produces

  %Xs    //where X is the value of (BUFFSIZE / 10)

which is a valid format string (%, minimum field width, conversion specifier, all in order), again, to be used later.

like image 36
Sourav Ghosh Avatar answered Sep 29 '22 05:09

Sourav Ghosh