0

Look here, those two programms should be equivalent in my opinion. But obviously they aren't, as the first programm works and the second doesn't. Can someone explain to me, why fgets() doesn't do the job?

// FIRST PROGRAM : WORKS FINE #include <stdio.h> #include <stdlib.h> int main() { FILE *stream; char fileName[67]; scanf("%s", fileName); printf("%s", fileName); stream = fopen(fileName, "r"); char ch; if(stream){ ch = fgetc(stream); while(!feof(stream)){ putchar(ch); ch = fgetc(stream); } fclose(stream); } } // SECOND PROGRAM: DOES NOT WORK #include <stdio.h> #include <stdlib.h> int main() { FILE *stream; char fileName[67]; fgets(fileName, 67, stdin); printf("%s", fileName); stream = fopen(fileName, "r"); char ch; if(stream){ ch = fgetc(stream); while(!feof(stream)){ putchar(ch); ch = fgetc(stream); } fclose(stream); } } 

I enter "test.txt" into the console both times and press enter then. Of course test.txt exists in the right directory

6
  • 6
    fgets() retains the newline entered, please remove it. Commented Nov 18, 2015 at 10:32
  • What does "the second program does not work" mean exactly? Commented Nov 18, 2015 at 10:33
  • 1
    ... you can check this by changing your print statement to printf("[%s]", dateiname); then you can see the newline is there. Commented Nov 18, 2015 at 10:34
  • means i enter "test.txt" and the first block of code will open and read whatever is in test.txt und the second block will just do nothing Commented Nov 18, 2015 at 10:35
  • Thanks to Weather Vane (thank you! ) i can see, that fgets() adds a new line to the filename. Can you tell me how to avoid that fgets() adds the new line, althought its nessecary pressing the enter button to confirm the text entered? Commented Nov 18, 2015 at 10:41

2 Answers 2

4

The reason is that fgets() retains the newline entered. You can verify it is there by altering your print statement to

printf("[%s]", filename); 

when the ] will appear on the next line. You can remove the trailing newline like this

#include <string.h> ... filename [ strcspn(filename, "\r\n") ] = 0; 
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you Mister Vane, you saved me a lot of time!
@Weather Vane: I think you are right with your diagnosis of the problem but I am not so sure about your suggested cure! Have you considered what happens if your strcspn() trick is applied to a string which does not contain a CRLF? (Or indeed if the line terminator is not \r\n on the OP's system?)
@AAT it is completely safe. If not found, the string length is returned, so it overwrites the existing terminator.
@AAT the newline does not have to be both of those. Any match will do, now please read the man page for strcspn, it is not strstr()!!
@WeatherVane - many apologies, you are quite right! I was indeed thinking about strstr() and I should have read the man page (or MSDN) first. I am happy to fully endorse your answer.
1

The main problem you experienced is correctly solved by Weather Vane, but I want to point another problem with your code: the loops for reading and writing the contents of the file are incorrect. Testing the end of file with feof(stream) leads to incorrect behaviour most of the time. In your case, a read error from stream will cause your program to loop endlessly, writing 0xFF bytes to stdout.

There is a much simpler and idiomatic way to implement this loop:

if (stream) { int ch; while ((ch = fgetc(stream)) != EOF) { putchar(ch); } fclose(stream); } 

As you can see, it is simpler and correctly tests for EOF at the right time, when input fails. It stores the return value of fgetc() into an int variable capable of holding all possible return values from fgetc(). Using an int is necessary because comparing a char value to EOF either always fails if the char type is unsigned or potentially gives false positives if char is signed and has value '\377'.

3 Comments

i thank you for correcting my code. i am stunned somehow, as i have found the feof(stream) -way to solve the task in a computer science book that is used at my university. I do not yet get the full picture of the problem that you describe but the code you wrote works with my programm and i am glad that you shared this with me!
This was one of those rare occasions where feof() was being used correctly, checking after the file read and not before, but you are right about detecting errors, which are flagged by the EOF from fgetc()
@Weather Vane: that's what I meant by most of the time. Just like strncpy, feof is almost never the right tool for the job. scanf is next on the list of mostly misused C library functions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.