Fopen and Fclose are wrapper functions in my source file that check for errors when opening the file. when I run my program, it says there was an Fopen error. I see no reason for an error during the file opening.
Sorry for the long code.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "perry.h"
int main(void)
{
void copyStrings(char *infile, char *outfile, char ch);
void compareFiles(char *infile, char *outfile);
char inputfile[80];
char outputfile[80];
char ch;
printf("Enter input filename: ");
scanf("%s", inputfile);
printf("Enter output filename: ");
scanf("%s", outputfile);
printf("Enter a character: ");
scanf(" %c", &ch);
if(!isalpha(ch))
{
printf("Did not enter a letter!");
exit(1);
}
copyStrings(inputfile, outputfile, ch);
compareFiles(inputfile, outputfile);
return 0;
}
void copyStrings(char *infile, char *outfile, char ch)
{
int count;
char *ptr;
char *line;
char linePart[80];
FILE *fin;
FILE *fout;
fin = Fopen(infile, "r");
fout = Fopen(outfile, "w");
while(fgets(line, 80, fin) != NULL)
{
for(ptr=line;ptr<line+strlen(line);ptr++)
{
if(*ptr == ch)
count ++;
}
if(count < 2)
fputs(line, fout);
else
{
memset(linePart, '\0', strlen(line)+1);
line = strchr(line, ch);
strncpy(linePart, line, strchr(line+1, ch) - line + 1);
fputs(linePart, fout);
fprintf(fout, "\n");
开发者_JS百科 }
}
Fclose(fout);
Fclose(fin);
return;
}
void compareFiles(char *infile, char *outfile)
{
int count = 0;
char inputString[80];
char outputString[80];
FILE *fin;
FILE *fout;
fin = Fopen(infile, "r");
fout = Fopen(outfile, "r");
while(fgets(inputString, 80, fin) != NULL)
{
count += 1;
if(strcmp(inputString, fgets(outputString, 80, fout)) == 0)
{
printf("Strings are equal at line %d\n\nBoth strings look like this: %s",
count, inputString);
}
}
Fclose(fout);
Fclose(fin);
return;
}
You should put a perror
in Fopen
and Fclose
, so that it describes why the wrapped function failed.
Linux man page for fopen
states it could fail for these reasons:
provided mode is invalid
if the
malloc
function, called withinfopen
failsif the
open
function used withinfopen
fails.
You should certainly try the perror thing as pointed out in the earlier comment but after looking at your code I think you should check the modes in which files are being opened once again.
To open a file in "r" mode, the must be existing first else fopen will return an error. You have not pointed out where you are facing the failure in fopen, but it always best to check the return values of all the file operations as well as memory allocation operations.
Following is a bit cheesy way to check the return value (skipping the extra variable part) :
FILE *fp = NULL;
if((fp = fopen(test.txt, "r")) == NULL ) { printf("fopen failed"); return FALSE //-1 or whatever you want to return as failure case; }
else { //your code }
You can either use perror()
if you don't mind working within the constraints of its formatting, or you can do the equivalent of:
fprintf(stderr, "Failed to open %s (%d: %s)\n", filename, errno, strerror(errno));
You should only ever look at errno
after a function has reported failure. It may also be set after a function that succeeds. For example, on Solaris, if the output is not a 'tty', you will often find ENOTTY in errno
after a successful print operation - because it checked whether the output file descriptor was a tty and actually it wasn't. But the function succeeded.
If there are any more function calls in your code than in the line I showed, it is best to preserve errno
early on - because it gets tampered with by other functions (one of the many demerits of a global variable). So, I often write:
{
int errnum = errno;
...any other processing...
fprintf(stderr, "%s: failed to open %s for reading (%d: %s)\n",
prog_name, file_name, errnum, strerror(errnum));
}
Well, I write the logical equivalent of that; I have a library that reports errors, so I'd actually write:
err_sysrem("failed to open %s for reading", file_name);
All the functions in the package start err_
. The function err_sysrem()
is a remark (does not exit) and includes the system error information - errno
and strerror(errno)
. If I called err_syserr()
instead, it would terminate the program, and err_remark()
would not include the information from errno
, and neither would err_error()
. I find the brevity provided by the functions beneficial. The functions all automatically include the program name at the start of the message; you can configure it to include time stamps or PIDs or other information too. You use err_setarg0(argv[0]);
in main()
to set the program name; you can, of course, change it at any time.
精彩评论