Fopen和Fclose是我的源文件中的包装函数,用于在打开文件时检查错误。当我运行我的程序时,它说有一个Fopen错误。我认为没有理由在文件打开期间出错。
很抱歉长代码。
#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");
}
}
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;
}
答案 0 :(得分:1)
您应该在perror
和Fopen
中添加Fclose
,以便它描述包装函数失败的原因。
fopen
的Linux手册页指出它可能因以下原因而失败:
提供的模式无效
如果在malloc
内调用的fopen
函数失败
如果open
中使用的fopen
功能失败。
答案 1 :(得分:1)
你当然应该尝试前面评论中指出的perror事情,但在查看你的代码之后我认为你应该再次检查文件被打开的模式。
要以“r”模式打开文件,必须先存在,否则fopen将返回错误。您还没有指出您在fopen中遇到故障的位置,但最好检查所有文件操作的返回值以及内存分配操作。
以下是检查返回值(跳过额外变量部分)有点俗气的方法:
FILE * fp = NULL;
if((fp = fopen(test.txt,“r”))== NULL) { printf(“fopen failed”); 返回FALSE // - 1或任何你想要返回的失败案例; }
否则 { //你的代码 }
答案 2 :(得分:0)
如果你不介意在格式化的限制范围内工作,你可以使用perror()
,或者你可以做相同的事情:
fprintf(stderr, "Failed to open %s (%d: %s)\n", filename, errno, strerror(errno));
在功能报告失败后,您应该只查看errno
。它也可以在成功的函数之后设置。例如,在Solaris上,如果输出不是'tty',则在成功打印操作后,您将经常在errno
中找到ENOTTY - 因为它检查输出文件描述符是否为tty且实际上不是。但功能成功了。
如果代码中的函数调用多于我所显示的行,最好在早期保留errno
- 因为它被其他函数篡改(全局的许多缺点之一)变量)。所以,我经常写:
{
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));
}
好吧,我写的逻辑相当于那个;我有一个报告错误的库,所以我实际上写了:
err_sysrem("failed to open %s for reading", file_name);
包中的所有功能都从err_
开始。函数err_sysrem()
是备注(不退出)并包含系统错误信息 - errno
和strerror(errno)
。如果我改为呼叫err_syserr()
,它将终止该计划,err_remark()
将不包含来自errno
的信息,err_error()
也不会。我发现功能提供的简洁有益。这些功能都自动包含消息开头的程序名称;您可以将其配置为包括时间戳或PID或其他信息。您可以在err_setarg0(argv[0]);
中使用main()
来设置程序名称;当然,你可以随时改变它。