-1

In C programming whenever I use fgetc(file) to read all the chars until the end of the file it works. But when I use the similar fscanf(file, "%c") function it prints strange characters. Code:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char c;
    FILE * file = fopen("D\\filename.txt", "r");
    while (c != EOF) {
        fscanf(file, "%c", &c);
        printf("%c", c);
    }
    return 0;
}

But when I use fgetc instead of fscanf, it works. And it prints each character which is present in the file.

Can anybody answer why it works like this?

Shreevardhan
  • 12,233
  • 3
  • 36
  • 50
  • 1
    Did you read some documentation on [fgetc(3)](http://man7.org/linux/man-pages/man3/fgetc.3.html) & [fscanf(3)](http://man7.org/linux/man-pages/man3/fscanf.3.html)? BTW C and C++ are different languages. In C++, you'll often use [`operator >>`](http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt) – Basile Starynkevitch Jun 13 '15 at 20:44
  • Please edit your question to improve it. Code chunks should be on separate line, each starting with four spaces. – Basile Starynkevitch Jun 13 '15 at 20:45
  • 2
    BTW your code is profoundly wrong: if you enable all warnings with a good compiler (like [GCC](http://gcc.gnu.org/) to be invoked as `gcc -Wall -Wextra -g` ) you'll get enough warnings to find easily your mistake. – Basile Starynkevitch Jun 13 '15 at 20:54
  • 1
    one thing to notice, other than the incorrect syntax of the fscanf() statement, is that fscanf() will not proceed past any white space (tab, space, newline) so will continually fail to input anything once any white space is encountered (it will not input the white space) – user3629249 Jun 13 '15 at 21:07
  • @user3629249: with `%c` the `fscanf` function won't skip spaces. – Basile Starynkevitch Jun 13 '15 at 21:08
  • This question is probably better on StackOverflow. – Basile Starynkevitch Jun 13 '15 at 21:10
  • @user3629249: To read the first non-whitespace character, you need a blank space in the format string: `fscanf( file, " %c", &c );` – John Bode Jun 16 '15 at 20:01
  • Don't edit your code (to add new instructions inside it, changing its meaning). Ask new questions. But really, give up learning C and learn Scheme & SICP first. – Basile Starynkevitch Jun 30 '15 at 11:51
  • I'm voting to close the question (it is unclear...) because it has changed so much. – Basile Starynkevitch Jun 30 '15 at 12:17

1 Answers1

6

Notice that

c=fscanf(file,"%c");

is undefined behavior (here I am explaining why you should be afraid of it, even when a program seems to apparently "work"), and every good C compiler (e.g. GCC to be invoked as gcc -Wall -Wextra -g) should warn you about that (if you enable all warnings). When coding in C you should also learn how to use the debugger (e.g. gdb).

You should read documentation of fscanf(3). You probably want to code

char c= '\0';
if (fscanf(file, "%c", &c) <= 0) break;

You'll better take the habit of initializing every variable; a good optimizing compiler would remove that initialization if it is useless, and would often warn you about unitialized variables otherwise.

Notice that using fgetc(3) in your case is probably preferable. Then you need to declare c as an integer, not a character, and code:

do {
  int c=fgetc(file);
  if (c==EOF) break;
} while (!feof(file));

Notice that in the above loop the feof(file) would never be true (because fgetc would have given EOF before), so you'll better replace while(!feof(file)) with while(true)

It is simpler to read (by other developers, or even yourself in a couple of months) working on the same code, and it is very probably faster. Most implementations of fscanf are based somehow on fgetc or a very related thing.

Also, take the good habit of testing your input. The input file might not be as you expect.

On most recent systems, the encoding is today UTF-8. Be aware that some (human language) characters could be encoded in several bytes (e.g. French accentuated e letter é, or Russian yery letterЫ, or even the Euro sign , or the mathematical for all sign , letters or glyphs in other languages, etc....). You probably should consider using some UTF-8 library (e.g. libunistring) if you care about that (and you should care about UTF-8 in serious software!).

Nota Bene: If you are young and learning programming, better (IMNSHO) learn Scheme with SICP, using e.g. Racket before learning C or Java. C is really not for beginners IMHO.

PS the character type (often a byte) is char in lower cases.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • fgetc is more preferable.Thanks!But why fscanf is printing is strange chars i don't know. – Agraj Milind Jun 30 '15 at 11:37
  • The standard `fscanf` does not print anything. But you should initialize your variables! – Basile Starynkevitch Jun 30 '15 at 11:41
  • Better learn [Scheme](http://www.schemers.org/) with [SICP](http://mitpress.mit.edu/sicp/), using [Racket](http://racket-lang.org/) before learning C or Java. C is not for beginners IMHO. – Basile Starynkevitch Jun 30 '15 at 11:47
  • My strong opinion is that you should not learn C at first. Scheme is much better to learn programming. And you'll need to learn *several* programming languages (but IMHO you should start with Scheme & SICP). – Basile Starynkevitch Jun 30 '15 at 11:54