I'm trying to understand when the stdio function clearerr() should be used.
For example, if I fread() or fwrite() on a valid FILE* and get a short count and ferror is true, what can I do?
From what I've read so far, fread() and fwrite() are robust and will block and/or retry (if there are locks and/or interrupts which could happen in lower level functions) so there never seems any point in using clearerr() because fread or fwrite errors will be so catastrophic there is no point in trying to recover.
Additionally, ferror() only tells me that there is an error, not what the error is.
#define SZ 1024
FILE* fp = fopen( "foo", "r" );
if ( fp ) {
char b[SZ];
int ch_count = fread( b, sizeof(char), SZ, fp );
if ( ch_count != SZ && ferror( fp ) ) {
// how would clearerr() be used. I don't know?
// ....
// should I drop through here to fclose? (when I've got an ferror)
}
fclose( fp );
}
There is at least one real world use case for clearerr: when you want to mimic tail -f on a file that is not opened in exclusive mode. That means that another (or many other) process(es) write at the end of a file, and one process repeatedly reads even after having reached the end of file in order to look whether new data has arrived. In that case, could would look like:
for (;;) {
if (NULL == fgets(line, sizeof(line), fd)) {
sleep(n);
clearerr(fd); // reset EOF condition
}
else {
fputs(line, fdout);
}
}
Functions that set the error status of a FILE (as reported by ferror) do not clear it even if later called successfully. Likewise if you encounter the end of file while reading, it will not be cleared automatically even if the file later has more data available.
Basically this means that if you are using ferror to check for an error state and you have some way of recovering from it, the ferror will keep indicating an error until you use clearerr.
In your example, if you just use the return value of fread as the condition for terminating the read (i.e., EOF and any type of error are considered final), there is no need to clearerr: just fall through to fclose (and perhaps use ferror to determine whether to print an error message).
On the other hand, if the FILE is in fact a stream on which read can later succeed, and you detect (or assume) that specific condition and retry, you should clearerr before retrying or you will keep seeing the old error condition on future attempts.
Likewise, as pointed out in comments, clearerr also clears the end of file state, so this also applies when using feof to check for the end of file. (Note, however, that you generally shouldn't use !feof(file) as the loop condition when reading.)
clearerr() clears the error and EOF flags from a stream.
Say FILE were like this:
typedef struct {
int fd;
char *buf;
int error;
int eof;
} FILE;
FILE *file;
This would set file->error and file->eof to 0.
Some reasons for doing this include file I/O, such as when a file gives EOF, but then another program (or another thread, etc.) appends to it. If you clear the error after doing this, you can have your program act as sort of a tail -f-substitute.
clearerr() clears both the error and end-of-file flags.
A pedantic use of clearerr():
// Return -1 on end-of-file
// Return -2 on rare file error
// Else return the unsigned char value
int my_get_quandry() {
// At this point, the file end-of-file flag may be set.
// At this point, the file file error flag may be set.
// They may both be set.
// Attempt to read another
int ch = fgetc();
if (ch != EOF) {
return ch;
}
// Now was the EOF due to a end-of file or error?
// feof() is true if end-of-file just occurred OR if end-of-file was set earlier
// ferror() is true if error just occurred OR if error was set earlier
// If only one feof() or ferror() is true, we know why EOF just occurred,
// Yet if both set, we do not know.
...?
}
Use clearerr()
// Return -1 on end-of-file
// Return -2 on rare file error
// Else return the unsigned char value
int my_get_crystal() {
clearerr(stdin);
// Attempt to read another
int ch = fgetc();
if (ch != EOF) {
return ch;
}
// Now EOF due to at most one reason
if (feof(stdin)) return -1;
if (ferror(stdin)) return -2;
// if code reaches this point, it is due to the odd-ball platform of `char` having the
// same range as `int`. But let us leave that platform for another day.
return ch;
}
Related
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".
I'm a bit new to C, but basically I have a problem where I need to read '-1' from a file. Sadly this means I run into a premature ending of the file, because the EOF constant is also -1 in my compiler.
What sort of work arounds would there be for this? Is there another function I can use to read it that will change the EOF to something I can work with?
Thanks in advance.
The code since people are asking for it
int read() {
int returnVal; // The value which we return
// Open the file if it isn't already opened
if (file == NULL) {
file = fopen(filename, "r");
}
// Read the number from the file
fscanf(file, "%i", &returnVal);
// Return this number
return returnVal;
}
This number is then later compared to EOF.
Okay this is probably bad practice, but I changed the code to the following
int readValue() {
int returnVal; // The value which we return
// Open the file if it isn't already opened
if (file == NULL) {
file = fopen(filename, "r");
}
// Read the number from the file
fscanf(file, "%i", &returnVal);
if (feof(file)) {
fclose(file);
return -1000;
}
// Return this number
return returnVal;
}
Because I knew I would never read any such number from my file (they range from about [-300, 300]. Thanks for all your help guys!
The return value of fscanf is NOT the value that was read, but rather it is the number of items successfully read, or EOF if an error occurred.
The problem is that your read function doesn't distinguish between a successful read and an error condition. You should change it to accept a int * as a parameter that scanf writes into, and the function should return something like 0 on a successful read and -1 on error. You can use the return value of scanf as the basis of what your function returns.
Also, there's a system call named read, so you should really name it something else. And don't forget to fclose(file) at the end of the function, otherwise you're leaking file descriptors.
Does feof() checks for eof for the current position of filepointer or checks for the position next to current filepointer?
Thanks for your help !
Every FILE stream has an internal flag that indicates whether the caller has tried to read past the end of the file already. feof returns that flag. The flag does not indicate whether the current file position is as the end of the file, only whether a previous read has tried to read past the end of the file.
As an example, let's walk through what happens, when reading through a file containing two bytes.
f = fopen(filename, "r"); // file is opened
assert(!feof(f)); // eof flag is not set
c1 = getc(f); // read first byte, one byte remaining
assert(!feof(f)); // eof flag is not set
c2 = getc(f); // read second byte, no bytes remaining
assert(!feof(f)); // eof flag is not set
c3 = getc(f); // try to read past end of the file
assert(feof(f)); // now, eof flag is set
This is why the following is the wrong way to use eof when reading through a file:
f = fopen(filename, "r");
while (!feof(f)) {
c = getc(f);
putchar(c);
}
Because of the way feof works, the end-of-file flag is only set once getc
tries to read past the end of the file. getc will then return EOF, which is
not a character, and the loop construction causes putchar to try to write it
out, resulting in an error or garbage output.
Every C standard library input method returns an indication of success or
failure: getc returns the special value EOF if it tried to read past the
end of the file, or if there was an error while reading. The special value is
the same for end-of-file and error, and this is where the proper way to use
feof comes in: you can use it to distinguish between end-of-file and error
situations.
f = fopen(filename, "r");
c = getc(f);
if (c == EOF) {
if (feof(f))
printf("it was end-of-file\n");
else
printf("it was error\n");
}
There is another internal flag for FILE objects for error situations:
ferror. It is often clearer to test for errors instead of "not end of file".
An idiomatic way to read through a file in C is like this:
f = fopen(filename, "r");
while ((c = getc(f)) != EOF) {
putchar(c);
}
if (ferror(f)) {
perror(filename):
exit(EXIT_FAILURE);
}
fclose(f);
(Some error checking has been elided from examples here, for brevity.)
The feof function is fairly rarely useful.
You can get a better understanding of how feof works, by knowing how it's implemented. Here is a simplified version of how the 7th Edition Unix stdio library implements feof. Modern libraries are very similar, adding code offering thread-safety, increased efficiency, and a cleaner implementation.
extern struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
char _flag;
char _file;
} _iob[_NFILE];
#define _IOEOF 020
#define feof(p) (((p)->_flag&_IOEOF)!=0)
#define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
int
_filbuf(FILE *iop)
{
iop->_ptr = iop->_base;
iop->_cnt = read(fileno(iop), iop->_ptr, BUFSIZ);
if (iop->_cnt == 0) {
iop->_flag |= _IOEOF;
return(EOF);
}
return(*iop->_ptr++ & 0377);
}
The stdio library maintains with each file a structure containing an internal buffer pointed by _base. The current character in the buffer is pointed by _ptr and the number of characters available is contained in _cnt. The getc macro, which is the base for a lot of higher-level functionality, like scanf, tries to return a character from the buffer. If the buffer is empty, it will call _filbuf to fill it. _filbuf in turn will call read. If read returns 0, which means that no more data is available, _filbuf will set the _IOEOF flag, which feof checks each time you call it to return true.
As you can understand from the above, feof will return true the first time you try to read a character past the end of the file (or a library function tries in your behalf). This has subtle implications on the behavior of various functions. Consider a file containing a single character: the digit 1. After you read that character with getc, feof will return false, because the _IOEOF flag is unset; nobody has yet tried to read past the end of the file. Calling getc again will result in a call to read, the setting of the _IOEOF flag, and this will cause feof to return true. However, after reading the number from the same file using fscanf("%d", &n), feof will immediately return true, because fscanf will have tried to read additional digits of the integer.
I want to read a file in a specific format, so I use fscanf_s and a while loop. But as soon as fscanf_s is processed, the program crashes with an access violation (0xC0000005).
Here's the code:
FILE *fp;
errno_t err = fopen_s(&fp, "C:\\data.txt", "r");
if (err != 0)
return 0;
int minSpeed = 0;
int maxSpeed = 0;
char axis = '#';
while(!feof(fp))
{
int result = fscanf_s(fp, "%c;%d-%d\n", &axis, &minSpeed, &maxSpeed);
if (result != 3)
continue;
}
fclose(fp);
The content of the file is line based, for example:
-;10000-20000
X;500-1000
S;2000-2400
Can somebody help me?
Apparently, fscanf_s() needs a size parameter after the address of the variable
fscanf_s(fp, "%c;%d-%d\n", &axis, 1, &minSpeed, &maxSpeed);
/* extra 1 for the size of the ^^^ axis array */
But I suggest you do not use the *_s functions: they are worse than the plainly named functions --- they require the same checks and make you feel safe when you aren't. I suggest you don't use them because of false sense of security and the fact they are not available on many implementations making your programs work only in a limited subset of possible machines.
Use plain fscanf()
fscanf(fp, "%c;%d-%d\n", &axis, &minSpeed, &maxSpeed);
/* fscanf(fp, "%1c;%d-%d\n", &axis, &minSpeed, &maxSpeed); */
/* default 1 ^^^ same as for fscanf_s */
And your use of feof() is wrong.
The fscanf() returns EOF when there is an error (end-of-file or matching failure or read error ...).
You can use feof() to determine why fscanf() failed, not to check whether it would fail on the next time it is called.
/* pseudo-code */
while (1) {
chk = fscanf();
if (chk == EOF) break;
if (chk < NUMBER_OF_EXPECTED_CONVERSIONS) {
/* ... conversion failures */
} else {
/* ... all ok */
}
}
if (feof()) /* failed because end-of-file reached */;
if (ferror()) /* failed because of stream error */;
If you believe the file (data.txt) exists, your application is probably not running with a current directory set to where the file is. This would cause fopen_s() to fail.
While doing filing im stuck here.The condition of the while loop is not working.The compiler says cannot convert int to FILE*.
while(pFile!=EOF);
Should i typecase the pFile to int?I tried that but it did not worked.Thanks in advance.
The complete code is:
int main()
{
char ch;
char name[20];
FILE *pFile;
int score;
pFile=fopen("database.txt","r");
if(pFile!=NULL)
{
while(pFile!=EOF);
{
fscanf(pFile,"%c",ch);
}
}
else
printf("Cant open the file.......");
fclose(pFile);
return 0;
}
First, you do not want to use while (!feof(pFile)) -- ever! Doing so will almost inevitably lead to an error where the last data you read from the file appears to be read twice. It's possible to make it work correctly, but only by adding another check in the middle of the loop to exit when EOF is reached -- in which case, the loop condition itself will never be used (i.e., the other check is the one that will actually do the job of exiting the loop).
What you normally do want to do is check for EOF as you read the data. Different functions indicate EOF in different ways. fgets signals failure (including EOF) by returning NULL. Most others (getc, fgetc, etc.) do return EOF, so you typically end up with something like this:
int ch; // Note, this should be int, NOT char
while (EOF != (ch=getc(pFile)))
process(ch);
or:
char buffer[MAX_LINE_SIZE];
while (fgets(buffer, sizeof(buffer), pFile))
process(buffer);
With scanf, checking for success is a little more complex -- it returns the number of successful conversions, so you want to make sure that matches what you expected. For example:
while (1 == fscanf(fPfile, "%d", &input_number))
process(input_number);
In this case I've used 1 because I specified 1 conversion in the format string. It's also possible, however, for conversion to fail for reasons other than EOF, so if this failes, you'll frequently want to check feof(pFile). If it returns false, do something like reading the remainder of the line, showing it to the user in a warning message, and then continuing to read the rest of the file.
It depends what pFile and EOF are defined as, but I will asssume that pFile is a *FILE, and EOF is from stdio.h. Then I guess you should do something like:
#include <stdlib.h>
#include <stdio.h>
#define FILENAME "file.txt"
int main(void) {
FILE *pFile;
int ch;
pFile = fopen(FILENAME,"r");
if (pFile) {
while ((ch = getc(pFile)) != EOF) {
printf("Read one character: %c\n", ch);
}
close(pFile);
return EXIT_SUCCESS;
} else {
printf("Unable to open file: '%s'\n", FILENAME);
return EXIT_FAILURE;
}
}
which yields
$ echo "abc" > file.txt
$ /tmp/fileread
Read one character: a
Read one character: b
Read one character: c
Read one character:
# last character being a linefeed
Assuming pFile is your file handle, this doesn't change as you read from the file. EOF is returned by e.g. fgetc(). See e.g. http://www.drpaulcarter.com/cs/common-c-errors.php#4.2 for common ways to solve this.
here is correct way:
c = getc(pFile);
while (c != EOF) {
/* Echo the file to stdout */
putchar(c);
c = getc(pFile);
}
if (feof(pFile))
puts("End of file was reached.");
else if (ferror(pFile))
puts("There was an error reading from the stream.");
else
/*NOTREACHED*/
puts("getc() failed in a non-conforming way.");
fclose(pFile);
pFile is a pointer to a file. EOF is usually defined as -1, a signed integer.
What you should do is fopen, make sure pFile != NULL, then call some function on the file handle until that function returns EOF. A pointer will (or rather, should) never be EOF. But a function acting on that pointer may return EOF.
I'm guessing you want to keep looping while you haven't hit end-of-file. In that case, you are looking for this:
while (!feof(pFile))
{
...
}
That said, this is still not quite correct. feof will only return true once it tries to read beyond the end of the file. This means feof can return false and yet there is no more data to read. You should really try your operation and only check for end of file if it fails:
char buffer[SIZE];
while (fgets(buffer, sizeof(buffer), pFile))
{
...
}
if (!feof(pFile))
{
// fgets failed for some reason *other* then end-of-file
}