enuliver
enuliver

Reputation: 33

General questions about scanf and fscanf in C programming language

If I'm not wrong, library function int fscanf(FILE *stream, const char *format, ...) works exactly the same as function int scanf(const char *format, ...) except that it requires stream selection. For example if I wanted to read two ints from standard input the code would look something like this.

int first_number; 
int second_number; 
scanf("%d%d", &first_number, &second_number);

There's no point of me adding newline character in between format specifiers even though the second number is entered in next line of input? Function just looks for next decimal integer right? What happens when I enter two characters instead of ints? Why the function sometimes doesn't work if there's a space between format specifiers?

In addition to that. When reading from file with fscanf(..), lets says the txt file contains next lines:

P6
255
1920 1080

Do I need to specify next line characters in fscanf(..)? I read it like this.

FILE *input = ..
char type[2];
int tr;
int width; int height;
fscanf(input, "%s\n", &type);
fscanf(input, "%d\n" &tr);
fscanf(input, "%d %d\n", &width, &height)

Is there a need for \n to signal next line? Can fscanf(..) anyhow affect any other functions for reading files like fread()? Or is it a good practice to just stick to one function through the whole file?

Upvotes: 1

Views: 403

Answers (2)

John Bode
John Bode

Reputation: 123458

The %d conversion specifier tells scanf and fscanf to skip over any leading whitespace, then read up to the first non-digit character, so you don’t need to put a newline between the two %d in the scanf call - in fact, if you do that, it means you have to have a newline between your inputs, not just blanks.

Most conversion specifiers skip over leading whitespace - the only ones that don’t are %c and %[, so you’ll want to be careful when using them.

Upvotes: 1

chux
chux

Reputation: 153338

scanf(...) operates like fscanf(stdin, ....).

Unless '\n', ' ', or other white spaces are inside a "%[...]", as part of a format for *scanf(), scanning functions the same as if ' ', '\t' '\n' was used. (Also for '\v, '\r, '\f.)

// All function the same.
fscanf(input, "%d\n" &tr);
fscanf(input, "%d " &tr);
fscanf(input, "%d\t" &tr);

There's no point of me adding newline character in between format specifiers even though the second number is entered in next line of input?

All format specifiers except "%n", "^[...]", "%c" consume optional leading white-spaces. With "%d" the is no need other than style to code a leading white-space in the format.


Function just looks for next decimal integer right?

Simply: yes.


What happens when I enter two characters instead of ints?

Scanning stops. The first non-numeric input remains in stdin as well as any following input. The *scanf() return value reflects the incomplete scan.


Why the function sometimes doesn't work if there's a space between format specifiers?

Need example. Having spaces between specifiers is not an issue unless the following specifier is one of "%n", "^[...]", "%c".


When reading from file with fscanf(..), .... Do I need to specify next line characters in fscanf(..)?

No. fscanf() is not line orientated. Use fgets() to read lines. fscanf() is challenging to use to read a line. Something like

char buf[100];
int cnt = fscanf(f, "%99[^\n]", buf);
if (cnt == 0) {
  buf[0] = 0;
}
if (cnt != EOF) {
  cnt = fscanf(f, "%*1[^\n]");
}

I read it like this. ... fscanf(input, "%s\n", &type); fscanf(input, "%d\n" &tr); ....

"it" as in a line is not read properly as "%s", "%d", "\n" all read consume 0, 1, 2, ... '\n' and other white-spaces. They do not read a line nor just the 1 character of the format.

Further "\n" does not complete upon reading 1 '\n', but continues reading all white-spaces until a non-white-space is detected (or end-of-file). Do not append such to the end of a format to read the rest of the line.

If want to read the trailing '\n', code could use int cnt = fscanf(input, "%d%*1[\n]" &tr);, but code will not know if it succeeded in reading the trailing '\n' after the int. It will have simply read it if it was there. Could use other formats, but really, using fgets() to read a line is better.


Is there a need for \n to signal next line?

No, as a format "\n" reads 0 or more whites-spaces, not just new-lines.


Can fscanf(..) anyhow affect any other functions for reading files like fread()?

Yes. All input function affect what is available next for other input functions. Mixing fread() and fscanf() is challenging to get right.


is it a good practice to just stick to one function through the whole file?

It certainly is simpler. I recommend to use input functions as building blocks for a helper function to handle your file input.


Tip: Read lines with fgets(), then parse. Set fscanf() aside until you understand why it has so much trouble with unexpected input.

Upvotes: 2

Related Questions