In a group assignment, we have to read input which only consist of the (small) letters a-z and the characters have a max length of 255. I wanted to check with getchar and ASCII, but my partner found a solution using sprintf and scanf, which I do not totally understand:
#include <stdio.h>
int main() {
int result = 0;
unsigned int length = 255;
char input[257];
result = readInput(input, &length);
return 1;
}
int readInput(char *output, int *length) {
char format_pattern[15];
sprintf(format_pattern, "%%%u[^\n]%%n", *length);
printf("Max allowed length is %d\n",*length);
scanf(format_pattern, output, length);
printf("Input length is %d\n",*length);
return 1;
}
Output:
Max allowed length is 255
testinput
Input length is 9
How does the format pattern in sprintf and scanf work?
Especially the three %%%
before u
and the two %%
before n
- I tried changing this to %u[^\n]%n
because two ##
would escape the ´%´, but then I get an error so they have to be there.
The only things I figured out are:
the %n
can read the characters before it, e.g.:
int var;
printf("Some Text before%n and after",&var);
printf("characters before percent n = %d\n", var);
Output: Some Text before and aftercharacters before percent n = 16
but in my big example above there isn't a pointer variable, where the
amount of text could be stored since *length
is for %%%u
?
The [^\n] means something like "read till new Line"
I googled a lot but did not find a similiar example - could somebody help me?
Your partner is using sprintf()
to dynamically create a format string for scanf()
. This is a bit tricky, because the printf
and scanf
functions use mostly the same formatting language. The reason for the dynamic format creation appears to be to insert a configurable field width into the format. That's clever, but overcomplicated and wholly unnecessary.
How does the format pattern in sprintf and scanf work? Especially the three %%% before u and the two %% before n
%%%u
is actually two directives. The first %%
causes printf
to emit a single %
character, and that leaves %u
, which I think you recognize. Similarly, the %%n
is one directive (%%
, as described above) plus a literal 'n' character, which is emitted as-is. The overall sprintf
call prepares a format string something like "%255[^\n]%n"
.
How, then, does the resulting format work with scanf
? You should probably read its documentation, available all over, such as here. That one happens to be for the GLIBC implementation, but you're not using anything non-standard, so it should explain everything you need to know about your particular format. Specifically, the 255 that you go to such trouble to introduce is a maximum field width for a field consisting of characters in the "scanset" described by [^\n]
-- every character except newline. The %n
does not consume any input; instead, it stores the number of characters so far read by that scanf
call.
For your purposes, I see absolutely no reason to generate the scanf
format dynamically. You are given a maximum field width, so you might as well use it in a literal format string. Even if you wanted a maximum field width specified at runtime, scanf()
has a better mechanism than dynamically writing format strings, involving passing the wanted field width as an argument.
Bonus hint: the code you posted is terribly mixed up about where to use *length
and where just length
in your printf
and scanf
calls. Where you want to output its value, you must pass the value (length
). Where you want scanf
to modify the value, you must pass the address where the new value should be stored (*length
).