Do ferrors carry through multiple writes? - c

Does the ferror in this example check check both fprintfs for error, or just the second one?
FILE * myout;
if ((myout = fopen("Assignment 11.txt", "a")) != NULL)
{
fprintf(myout, "First print ", str1);
fprintf(myout, "Second print", str1);
if (ferror(myout))
fprintf(stderr, "Error printing to file!");
fclose(myout);
}

If an error occurs, it won't be reset unless clearerr is called on your stream, so yes, an error occuring on any of both writes is recorded.
from ferror manual page:
The function ferror() tests the error indicator for the stream pointed to by stream, returning nonzero if it is set. The error indicator can only be reset by the clearerr() function.
But you could also simply use fprintf return code to see if something went wrong:
If an output error is encountered, a negative value is returned.
(fprintf manual page)
Like this (Thanks Jonathan for pointing out the errors in the original post):
if (fprintf(myout, "First print %s\n", str1)<0) fprintf(stderr, "Error printing to file #1!");
if (fprintf(myout, "Second print %s\n", str1)<0) fprintf(stderr, "Error printing to file #2!");

Related

Segmentation Fault when reading from file - fgets()

Trying to read from a file to use in a small game I've created. I'm using the fgets function. It's returning a Segmentation Fault, not sure why.
The file it's reading, just contains "20 10" in a txt file as this is the map size.
My readfile function is shown below
if (argc == 2) {
f = fopen("map.txt", "r");
if (NULL == f) {
printf("File cannot be opened.");
}
while (fgets(fileRead, 50, f) != NULL) {
printf("%s", fileRead);
}
fclose(f);
}
The if (argc == 2) can be ignored, this is just to make this section run, as I'm modifying a file so just running this function by satisfying that if statement.
I am fairly new to C, so apologies if I'm missing something minor. Worth noting I'm programming in C89 and using the -Wall -ansi -pedantic compile options, as this is University work and the tutors want us to do C89.
EDIT:
char userInput, fileRead[50];
FILE* f;
Declaration of variables.
Assuming that your problem is indeed in your posted code and not somewhere else in the program, then I believe that your problem is caused by the following issue:
After calling fopen, you check the return value of the function immediately afterwards, to verify that it succeeded. However, if it doesn't succeed and it returns NULL, all you do is print an error message to stdout but continue execution as if it succeeded. This will cause fgets to be called with NULL as the stream argument, which will invoke undefined behavior and probably cause your segmentation fault.
In the comments section, you raised the following objection to this explanation:
However it doesn't print the error message anyway and still segmentation faults, so I think the problem isn't here?
This objection of yours is flawed, for the following reason:
When a segmentation fault occurs, execution of the program is immediately halted. The content of the output buffer is not flushed. This means that output can get lost when a segmentation fault happens. This is probably what is happening in your case.
If you want to ensure that the output actually gets printed even in the case of a segmentation fault, you should flush the output buffer by calling fflush( stdout ); immediately after the print statement. Alternatively, you can print to stderr instead of stdout. In constrast to stdout, the stream stderr is unbuffered by default, so that it does not have this problem.
You can test whether my suspicion is correct by changing the line
printf("File cannot be opened.");
to
printf("File cannot be opened.");
fflush( stdout );
or to:
fprintf( stderr, "File cannot be opened." );
If the error message now gets printed, then this probably means that my suspicion was correct.
In any case, I recommend that you change the lines
if (NULL == f) {
printf("File cannot be opened.");
}
to the following:
if (NULL == f) {
fprintf( stderr, "File cannot be opened." );
exit( EXIT_FAILURE );
}
That way, the program will exit immediately if an occur occurs, instead of continuing execution.
Please note that the code posted above requires you to #include <stdlib.h>.

fscanf - How to know if EOF means end of file or reading/another error?

I have a question about I/O in C language, how can I make a difference to know if the lecture of my file has ended or if the data can't be read (or has a problem) as in the both cases, fscanf returns EOF ?
Don´t rely only on the return value of fscanf(), rely beside this one on feof() and ferror() after the call to fscanf():
FILE* file;
if((file == fopen("file.txt","r")) == NULL)
{
fprintf(stderr, "File could not be opened!");
return EXIT_FAILURE;
}
char buf;
/******************************************************************************/
while(fscanf(file,"%c",buf) == 1) { // checks if an error was happen, else
// iterate to catching characters.
/* handling of read character */
}
if(ferror(file)) // checks if an I/O error occurred.
{
// I/O error handling
fprintf(stderr,"Input/Output error at reading file!");
clearerr(file);
// Further actions
}
else if(feof(file)) // checks if the end of the file is reached.
{
// end of file handling
fprintf(stderr,"Reached End of File!");
clearerr(file);
// Further actions
}
/******************************************************************************/
if(fclose(file) != 0)
{
fprintf(stderr, "File could not be closed properly!");
return EXIT_FAILURE;
}
As per fscanf() return value:
ISO/IEC 9899:2017
§ 7.21.6.2 - 16 - The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
EOF is a macro with the value of -1, by itself it's not distinguishable as for the reasons why it occurs.
For this distinction § 7.21.6.2 - 19 recommends the use of feof() for end-of-file and ferror() for I/O error:
EXAMPLE 3 To accept repeatedly from stdin a quantity, a unit of measure, and an item name:
#include<stdio.h>
/*...*/
int count; floatquant;
charunits[21], item[21];
do {
count = fscanf(stdin, "%f%20sof%20s", &quant, units, item);
fscanf(stdin,"%*[^\n]");
} while(!feof(stdin) && !ferror(stdin));
My usual approach when reading formated input, is to check the inputed values. For a sample input of 2 integers you can do something like:
int a, b;
FILE* file;
//open file to read
while(fscanf(file, "%d %d", &a, &b) == 2){ //read each 2 integers in the file, stop when condition fails, i.e. there are nothing else to read or the read input is not an integer
//...handle inputs
}
This kind of read is safe and addresses all failure scenarios since it works for bad input and for "end of file".

fprintf crashes my program when it meets a \n

I am trying to make a report in a .txt file, but when my fprintf meets a \n it crashes. This is my code concerning the opening of the file and crashing:
FILE *f;
f = fopen("estructuras.txt", "w");
fprintf(f, "");
printf("3"); //This is the last thing I see.
fprintf(f, "TEXT TO INPUT\n")
fclose(f);
The problem is you didn't check whether the file opened. If it failed, it will return NULL and that will do bad things to fprintf.
Your first fprintf(f, ""); is a no-op. Printing an empty string does nothing, so that "works" (though I doubt that's guaranteed). printf("3"); does to stdout and is unaffected by the failed fopen. fprintf(f, "TEXT TO INPUT\n") finally tries to print to NULL and pukes.
All system calls have to be checked. They all have different return values on error. fopen returns NULL and the error lies in errno. There's many ways to do fopen error handling, here's one that I like which gives the user information to debug the problem.
#include <string.h> // for strerror()
#include <errno.h> // for errno
#include <stdio.h>
#include <stdlib.h>
int main(){
// Put the filename in a variable so it can be used in the
// error message without needing to be copied.
char file[] = "estructuras.txt";
FILE *fp = fopen(file, "w");
if( fp == NULL ) {
// Display the filename, what you were doing with it, and why it wouldn't open.
fprintf(stderr, "Could not open '%s' for writing: %s\n", file, strerror(errno));
exit(-1);
}
}
strerror(errno) turns the numeric errno error code into a human readable string. There are quotes around the filename in case extra whitespace snuck in.
So you'll get an error like Could not open 'estructuras.txt': No such file or directory.

Does EOF set errno?

I always struggle with return values of system calls - they are just so inconsistent!
Normally I check if they are NULL or -1 and then call perror. However, for fgets, the man page says:
gets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read.
which means the return value NULL is not necessarily an error - it can also be EOF. Is errno set when the end of file is reached? Can I still call perror in this case?
If not, what is the common way to tell if the call returned an error versus EOF. I want to use perror with NULL string for errors and a custom string for EOF.
Use ferror and feof to distinguish between error and EOF. There's no general way to find out exactly what the error was, if there was an error, but you can tell that there was one.
Standard C (f)gets (and (f)getc) are not required to set errno, although a conforming library implementation can set errno to a non-zero value pretty much at will.
Posix does requires that (f)get{c,s} set errno on read errors, but that only helps you after you have determined that there was a read error (by calling ferror). It's also important to remember that library functions never set errno to 0, but may set errno to a non-zero value even if no error occurs. So you cannot test errno as a replacement for checking the error return of any library function, including fgets. And since end-of-file is not an error, errno will (probably) not be modified on EOF, so its value in that case is meaningless.
According to fputs own documentation, yes, EOF does set errno. The man pages infer it indirectly as opposed to stating it outright, which hopefully will be amended. The function fputs returns an integer that will either be positive on success or EOF on failure. So the key to error handling fputs is to setup a code block that checks the return value of fputs as it is being called. The following is a snippet of how I've been taught to handle fputs errors.
if (fputs(buffer, stdout) == EOF)
{
fprintf(stderr, "fputs returned EOF: %s\n", strerror(errno));
// .. and now do whatever cleanup you need to do.
// or be lazy and exit(-1)
}
Here I am writing the contents of buffer to standard output and checking to see if fputs returns EOF. EOF indicates an error code was set, so as long as you follow the documentation on the man pages for fputs, you should be able to create a bunch of if statements to check the various error codes errno can be set to.
(1) What is buffer? Some character array I declared elsewhere.
(2) What does fprintf do? It prints output to a passed in file descriptor, which is in this case standard error (stderr... it prints to console like stdout, but for errors).
(3) What is strerror? It is a function defined in the string.h header that prints error information for the passed in error code. It has information for every single error code that errno can be set to. The header string.h should NOT be confused with strings.h, which is a BSD linux header file that does not contain strerror(3).
Edit: Ok, I messed up. You were looking for an answer on fgets, not fputs.
To check for an error on fgets, do the following
if (fgets(buffer, BUF_SIZE, myFile) == NULL)
{
// print out error as a string to stderr
fprintf(stderr, "fgets error occurred: %s\n", strerror(errno));
// do cleanup
}
// special: you also need to check errno AFTER the if statement...
The thing is, the only way you are getting an error on this is if the stream becomes unreadable, which is either due to permissions or trying to read something that is in write mode. In the case of a network, it may be possible for something to cut off your connection in the middle of reading, in which case you need to check the error code after the fgets if statement as well. But it will set the error code if something went wrong.
At least that is if the man pages are correct. See the linux man pages for more details. Only error code that can be set is the "I can't read this thing" code, which is errno == EBADF

When should I use perror("...") and fprintf(stderr, "...")?

Reading the man pages and some code did not really help me in
understanding the difference between - or better, when I should use - perror("...") or fprintf(stderr, "...").
Calling perror will give you the interpreted value of errno, which is a thread-local error value written to by POSIX syscalls (i.e., every thread has it's own value for errno). For instance, if you made a call to open(), and there was an error generated (i.e., it returned -1), you could then call perror immediately afterwards to see what the actual error was. Keep in mind that if you call other syscalls in the meantime, then the value in errno will be written over, and calling perror won't be of any use in diagnosing your issue if an error was generated by an earlier syscall.
fprintf(stderr, ...) on the other-hand can be used to print your own custom error messages. By printing to stderr, you avoid your error reporting output being mixed with "normal" output that should be going to stdout.
Keep in mind that fprintf(stderr, "%s\n", strerror(errno)) is similar to perror(NULL) since a call to strerror(errno) will generate the printed string value for errno, and you can then combined that with any other custom error message via fprintf.
They do rather different things.
You use perror() to print a message to stderr that corresponds to errno. You use fprintf() to print anything to stderr, or any other stream. perror() is a very specialized printing function:
perror(str);
is equivalent to
if (str)
fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
fprintf(stderr, "%s\n", strerror(errno));
perror(const char *s): prints the string you give it followed by a string that describes the current value of errno.
stderr: it's an output stream used to pipe your own error messages to (defaults to the terminal).
Relevant:
char *strerror(int errnum): give it an error number, and it'll return the associated error string.
perror() always writes to stderr;
strerr(), used together with fprintf(), can write to any output - including stderr but not exclusively.
fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")
Furthermore, perror imposes its own text formating "text: error description"
Perror function take more time to perform execution call goes from user space to kernal space wheras fprintf calls goest to api to kernal

Resources