问题
I saw on this website that this: fscanf(fin, "%[^\n]", &p);
could be used for reading from my input file(fin
) into that char type pointer(*p
) all the characters until the first enter hit. At some inputs it works properly, but at others it doesn't.
This is the input I should process and I cannot:
(((zahar 100 ou 3) 5 unt 100 nuca 200) 4 (lapte 200 cacao 50 zahar 100)3)20
This is my whole code:
#include <string.h>
#include <stdio.h>
FILE *fin, *fout;
int main()
{
fin = fopen("reteta.in", "r");
fout = fopen("reteta.out", "w");
char *p;
p = new char[1001]();
fscanf(fin, "%[^\n]", &p);
fprintf(fout, "%s", &p);
return 0;
}
回答1:
The %[
notation introduces something called a "scanset" which is somewhat like a regular expression (but not as powerful).
In your specific example it means the format specifier instructs scanf
to keep scanning characters that match anything except an \n
(encountering a non-matching character will terminate the scan).
From the C11 standard:
The conversion specifier includes all subsequent characters in the format string, up to and including the matching right bracket (]). The characters between the brackets (the scanlist) compose the scanset, unless the character after the left bracket is a circumflex (^), in which case the scanset contains all characters that do not appear in the scanlist between the circumflex and the right bracket.
Even comparing it to a regular expression is stretching it: the standard simply says it: "Matches a nonempty sequence of characters from a set of expected characters".
The real problem with your code, spotted by Jonathan Leffler is this:
fscanf(fin, "%[^\n]", &p);
^
Drop the &
since you want to pass p, not "the address of p".
回答2:
% introduces a format-specifier, [
means it's a scan-set and opens it, ^
at the first position in the scan set reverses from "match all in" to "match all not in", \n
is the new-line character, and ]
closes the scan-set.
Thus, it means: Match indefinitely many characters which are not \n
and put them into the char[]
pointed to by the argument.
That argument thus must have type char*
.&p
is exactly one address-of too much, and the buffer pointed to by it (new char[1001]
) is infinite orders of magnitude too small.
Restrict the length of the match (by putting 1000 between the scanset and the %
).
Alternatively, and far better, use fgets.
Other points:
Your buffer should be stack-allocated, as it is small enough:
char buf[1001];
Alternatively, at least use a smart-pointer so you don't forget to
delete []
it:std::unique_ptr<char> p = new char[1001];
- Why do you value-initialize it? That's superfluous. Use
new char[1001]
instead ofnew char[1001]()
. - Don't forget to check the return-value of fscanf, it should be the number of assignments on success.
- C++ (and C99) has an implicit
return 0;
at the end ofmain
. - You really should close all files you opened (fopen->fclose).
来源:https://stackoverflow.com/questions/26597624/what-does-n-mean-in-a-scanf-format-string