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
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.
% 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.
The OP is computing a format string from parametric sizes. Given the arguments, the string will contain %5s %10s %10s, which can be used with either printf or scanf:
printf("%5s %10s %10s", "A", "B", "C");
outputs:
A B C
char a[6], b[11], c[11];
scanf("%5s %10s %10s", a, b, c);
will read 3 strings into a, b, c but limits the number of characters read for each string to prevent buffer overflow.
Note however that for the printf case, it is not necessary to compute the string as posted, since you could have used:
printf("%5s %*s %*s", "A", BUFFSIZE / 10, "B", BUFFSIZE / 10, "C");
Unfortunately, scanf() attaches different semantics to the * format modifier and it is not possible to specify the maximum number of characters to store with an argument, only with digits in the format string, hence need for a separate formatting step.
Related
it is simple version just for ask, i have this program
wchar_t c;
wprintf(L"input\n");
wscanf(L"%d", &c);
wprintf(L"output\n");
wprintf(L"%lc", towlower(c));
and this input/output
if i input "W" there output "?", with another characters i have the same situation.
in the line wscanf(L"%d", &c);, you passed %d as format specifier. So wscanf() is searching for an integer, but you are passing a character instead. Changing to %c will solve it.
See the specification in the wscanf(3) manpage:
d Matches an optionally signed decimal integer, whose format is the same
as expected for the subject sequence of wcstol() with the value 10 for
the base argument. In the absence of a size modifier, the application
shall ensure that the corresponding argument is a pointer to int.
...
c Matches a sequence of wide characters of exactly the number specified
by the field width (1 if no field width is present in the conversion
specification).
For a school assignment, I have to read in a string that has at least one but up to three variables(named command, one, and two). There is always a character at the beginning of the string, but it may or may not be followed by integers. The format could be like any of the following:
i 5 17
i 3
p
d 4
I am using fgets to read the string from the file, but I'm having trouble processing it. I've been trying to use sscanf, but I'm getting segfaults reading in a string that only has one or two variables instead of three.
Is there a different function I should be using?
Or is there a way to format sscanf to do what I need?
I've tried sscanf(buffer, "%c %d %d", command, one, two) and several variations with no luck.
sscanf is probably up to this task, depending on the exact requirements and ranges of inputs.
The key here is is that the scanf family functions returns a useful value which indicates how many conversions were made. This can be less than zero: the value EOF (a negative value) can be returned if the end of the input occurs or an I/O error, before the first conversion is even attempted.
Note that the %c conversion specifier doesn't produce a null-terminated string. By default, it reads only one character and stores it through the argument pointer. E.g.
char ch;
sscanf("abc", "%c", &ch);
this will write the character 'a' into ch.
Unless you have an iron-clad assurance that the first field is always one character wide, it's probably better to read it as a string with %s. Always use a maximum width with %s not to overflow the destination buffer. For instance:
char field1[64]; /* one larger than field width, for terminating null */
sscanf(..., "%63s", field1, ...);
sscanf doesn't perform any overflow checks on integers. If %d is used to scan a large negative or positive value that doesn't fit into int, the behavior is simply undefined according to ISO C. So, just like with %s, %d is best used with a field width limitation. For instance, %4d for reading a four digit year. Four decimal digits will not overflow int.
I'm parsing a string (a char*) and I'm using sscanf to parse numbers from the string into doubles, like so:
// char* expression;
double value = 0;
sscanf(expression, "%lf", &value);
This works great, but I would then like to continue parsing the string through conventional means. I need to know how many characters have been parsed by sscanf so that I may resume my manual parsing from the new offset.
Obviously, the easiest way would be to somehow calculate the number of characters that sscanf parses, but if there's no simple way to do that, I am open to alternative double parsing options. However, I'm currently using sscanf because it's fast, simple, and readable. Either way, I just need a way to evaluate the double and continue parsing after it.
You can use the format specifier %n and provide an additional int * argument to sscanf():
int pos;
sscanf(expression, "%lf%n", &value, &pos);
Description for format specifier n from the C99 standard:
No input is consumed. The corresponding argument shall be a pointer to
signed integer into which is to be written the number of characters read from the input stream so far by this call to the fscanf function. Execution of a %n directive does not increment the assignment count returned at the completion of execution of the fscanf function. No argument is converted, but one is consumed. If the conversion specification includes an assignment suppressing character or a field width, the behavior is undefined.
Always check the return value of sscanf() to ensure that assignments were made, and subsequent code does not mistakenly process variables whose values were unchanged:
/* Number of assignments made is returned,
which in this case must be 1. */
if (1 == sscanf(expression, "%lf%n", &value, &pos))
{
/* Use 'value' and 'pos'. */
}
int i, j, k;
char s[20];
if (sscanf(somevar, "%d %19s %d%n", &i, s, &j, &k) != 3)
...something went wrong...
The variable k contains the character count up to the point where the end of the integer stored in j was scanned.
Note that the %n is not counted in the successful conversions. You can use %n several times in the format string if you need to.
#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?
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.
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.
In some code that I have to maintain, I have seen a format specifier %*s . Can anybody tell me what this is and why it is used?
An example of its usage is like:
fprintf(outFile, "\n%*s", indent, "");
It's used to specify, in a dynamic way, what the width of the field is:
The width is not specified in the format string, but as an additional
integer value argument preceding the
argument that has to be formatted.
so "indent" specifies how much space to allocate for the string that follows it in the parameter list.
So,
printf("%*s", 5, "");
is the same as
printf("%5s", "");
It's a nice way to put some spaces in your file, avoiding a loop.
Don't use "%*s" on a buffer which is not NULL terminated (packed) thinking that it will print only "length" field.
The format specifier %4s outputs a String in a field width of 4—that is, printf displays the value with at least 4 character positions.
If the value to be output is less than 4 character positions wide, the value is right justified in the field by default.
If the value is greater than 4 character positions wide, the field width expands to accommodate the appropriate number of characters.
To left justify the value, use a negative integer to specify the field width.
References: Java™ How To Program (Early Objects), Tenth Edition
When used in printf and fprintf:
printf("%*s", 4, myValue); is equivalent to printf("%4s", myValue);
It displays the variable with minimum width, rest right-justified spaces. To left-justify the value, use a negative integer.
When used in scanf and sscanf:
/* sscanf example */
#include <stdio.h>
int main ()
{
char sentence []="Rudolph is 12 years old";
char str [20];
int i;
sscanf (sentence,"%s %*s %d",str,&i);
printf ("%s -> %d\n",str,i);
return 0;
}
Output:
Rudolph -> 12
It is used to ignore a string.
* Causes fprintf to pad the output until it is n characters wide, where n is an integer value stored in the a function argument just preceding that represented by the modified type.
printf("%*d", 5, 10) //will result in "10" being printed with a width of 5.
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.
e.g: printf("%*s", 4, myValue); is equivelant to printf("%4s", myValue);.