Reputation: 129
I have written the function, don't know it that's correct but how do I return true and false using if condition?
Function bool save_book(Book, char)** Input Parameters: A pointer to a Book and a string representing a file name. Return Value: Return true if the book's contents were stored to a file successfully. Otherwise false. Note This function should create or open a file based on the file name and store each Line of the book in it.
Below is my code
bool save_book(Book *b, char* fileName){
FILE *filePointer = fopen(fileName,"w");
for (int i = 0; i < pBook->lineCount; i++)
{
fprintf(filePointer, "%s", b->lines[i]);
}
fclose(filePointer);
return true;
}
this is the struct I am using:
typedef struct _Book
{
int characterCount;
int lineCount;
int maxLineCount;
char **lines;
}Book;
Upvotes: 1
Views: 2517
Reputation: 165546
You have to check every individual I/O operation.
To make it fun, they all return different things on error. fopen
will return NULL. fprintf
will return a negative number. fclose
will return EOF.
Here it is annotated with a short list of what might go wrong at each step.
bool save_book(Book *b, char* fileName) {
// Maybe the directory doesn't exist.
// Maybe you don't have permission.
// Maybe there's a disallowed character.
// Maybe the disk is full.
// Maybe it's a network drive and there's a network error.
// Maybe the drive got unmounted.
FILE *filePointer = fopen(fileName,"w");
if( filePointer == NULL ) {
return false;
}
for (int i = 0; i < b->lineCount; i++)
{
// Maybe the disk is full.
// Maybe it's a network drive and there's a network error.
// Maybe the drive got unmounted.
if( fprintf(filePointer, "%s", b->lines[i]) < 0 ) {
// Even though the filePointer variable will be automatically freed
// the underlying file handle will not be automatically closed.
// There's a limit to how many open file handles one can have open.
// No need to check for error, we know something has already gone wrong.
fclose(filePointer);
return false;
}
}
// Maybe the disk is full.
// Maybe it's a network drive and there's a network error.
// Maybe the drive got unmounted.
if( fclose(filePointer) != 0 ) {
return false;
}
return true;
}
In reality you probably don't need to check fprintf
, checking fclose
should catch the same errors. But if you're writing a very large and expensive file you might want to know if you ran out of disk space sooner rather than later.
You can also optionally print the error. Each of those functions will set the global errno
on failure. You can turn this into a human readable string with strerror
.
if( filePointer == NULL ) {
fprintf(stderr, "Error while opening '%s' for writing: %s", fileName, strerror(errno));
return false;
}
Note that rather than checking for an exact error code, I tend to check for that which is not the success code. Rather than if( fclose(filePointer) == EOF )
I've checked for if( fclose(filePointer) != 0 )
, the lack of a success code. This is a defense programming practice just in case the error is severe enough that it can't even return its correct error code (extremely unlikely in standard library code) or I didn't read the spec quite right.
Upvotes: 2