So, I want to read some input in two integer variables with fscanf
, the input must be
INTEGER
ONE SPACE
INTEGER
\n
So for example a file could be like that:
235 190\n
And what I want to do is checking if there is any new line before the first integer or the second, then throw an exception if that's the case:
So basically what you do with fscanf
for that case would be just to do like:
FILE *somefile;
[...]
int w, h;
if (fscanf(somefile, "%d%d") == EOF)
return (1);
But this method does not provide checking if there is a new line between the integers
(for example if there is INTEGER
NEW_LINE
INTEGER
it will still read the second)
as it skips all spaces before seeing a digit, so what I managed to do is more close but still wrong:
FILE *somefile;
int w, h;
char check[2];
if (fscanf(somefile, "%d%c%d%c", &w, check, &h, check + 1) == EOF)
return (-1);
if (check[0] != ' ' || check[1] != '\n')
return (-1);
So after I did that I realized that the %c
before the %d
just reads one character, so if there is a space then a new line between the two, it will continue reading the file wrongly and won't detect an error.
Now I wonder if there is a way to skip all spaces like when using " %c"
, while knowing if we skipped a \n
. Thanks for your help.
PS: I know we can use fgets
and strtol
but it would be too easy, in this project I can only use fscanf
to parse the file.
if there is a way to skip all spaces
I can only use fscanf to parse the file.
Let us assume ungetc()
is not allowed - which makes things harder.
"%d"
happily consumes all (0 or more) leading white-spaces including '\n'
without notice.
Use fscanf("%[...]")
to find leading white-spaces first. The usual suspects are " \t\n\r\f\v"
.
// Consume leading whitespaces
// Return
// 1: \n or EOF found
// 0: not found
int EatLeadingWS(FILE *f) {
int count;
char space[2];
while ((count = fscanf("%1[ \t\n\r\f\v]", space)) == 1) {
if (space[0] == '\n') return 1;
}
return count == EOF;
}
Alternative: use "%c"
and isspace()
, but then we need a way to put non white-spaces back.
Then look for white-spaces before "%d"
int some_int;
if (EatLeadingWS(f) == 0) {
int count;
if ((count = fscanf("%d", &some_int)) == 1) {
printf("int %d found before a \\n\n", some_int);
}
}
Another alternative is to use char buf[100]; fscanf("%99[^\n]", buf)
to read most of the line and then parse the string with sscanf(buf, "%d%1[ ]%d" ....