If you want to open multiple files in C language and write
How should I write down the error handling?
I thought about the following, but in the second file open
The processing of an error is disgusting.
int func1 (char*fname1, char*fname2)
{
FILE*fp1;
FILE*fp2;
if(((fp1=fopen(fname1,"w"))==NULL)
{
fprintf(stderr, "fname1 open error.\n");
return-1;
}
if((fp2=fopen(fname2, "w"))==NULL)
{
fprintf(stderr, "fname2 open error.\n");
fclose(fp1);// This is disgusting
return-1;
}
intret;
ret = func2(fp1,fp2); // The action of writing to a file
fclose(fp1);
fclose(fp2);
if(ret!=0)
{
fprintf(stderr, "error occurred in func2.\n";
return-1;
}
return 0;
}
In this case, goto
can be used to write beautifully, so if there is no problem using it, how about writing as follows?
int func1 (char*fname1, char*fname2)
{
intr = 0; // Used for return value
FILE*fp1 = NULL;
FILE*fp2 = NULL;
if(((fp1=fopen(fname1,"w"))==NULL)
{
fprintf(stderr, "fname1 open error.\n");
r = -1;
goto cleanup;
}
if((fp2=fopen(fname2, "w"))==NULL)
{
fprintf(stderr, "fname2 open error.\n");
r = -1;
goto cleanup;
}
intret;
ret = func2(fp1,fp2); // The action of writing to a file
if(ret!=0)
{
fprintf(stderr, "error occurred in func2.\n";
r = -1;
goto cleanup;
}
US>cleanup
if(fp1!=NULL){
fclose(fp1);
}
if(fp2!=NULL){
fclose(fp2);
}
return;
}
I also use goto
, but it's a shame that you can't use goto
in any pattern.
FILE*fp1=fopen(fname1,"w");
FILE* fp2 = fopen(fname2, "w");
if(fp1==NULL||fp2==NULL)
{
(fp1 == NULL)?fprintf(stderr, "fname1 open error.\n")—fclose(fp1);
(fp2==NULL)?fprintf(stderr, "fname2 open error.\n")—fclose(fp2);
return-1;
}
// file processing
・・・
fclose(fp1);
fclose(fp2);
It's almost the same as Kyosuke Kameda's answer, but there's also a way to not make NULL
decisions during cleanup.
int func1 (char*fname1, char*fname2)
{
intr = 0;
FILE*fp1;
FILE*fp2;
if(((fp1=fopen(fname1,"w"))==NULL)
{
fprintf(stderr, "fname1 open error.\n");
r = -1;
goto err_open1;
}
if((fp2=fopen(fname2, "w"))==NULL)
{
fprintf(stderr, "fname2 open error.\n");
r = -1;
goto err_open2;
}
intret = func2(fp1,fp2); // The action of writing to a file
if(ret!=0)
{
fprintf(stderr, "error occurred in func2.\n";
r = -1;
gotoerr_func2;
}
// cleanup
err_func2:
fclose(fp2);
err_open2:
fclose(fp1);
err_open1:
return;
}
Each action that requires error determination
hoge cleanup action;
err_hoge:
It's a group of things like that
In this way, the order in which fp1
and fp2
are closed is reversed from the original
It is necessary to, but from experience, it is often better to release files and memory in reverse order of opening and securing them.
If you have to close it in order of the original, this method may be a drawback.
The direct attack method can also be implemented using the cleanup
attribute in the GCC proprietary extension.Please be careful when using it as it is not available with other compilers.
Quoted from Wikipedia article "Resource Acquisition Is Initialization"
static inline void fclose(FILE**fp) { if(*fp)fclose(*fp);}
#define_cleanup_fclose___attribute_((cleanup(fclose)))))
void example_usage(){
_cleanup_fclose_FILE* logfile=fopen("logfile.txt", "w+");
fputs("hello logfile!", logfile);
}
© 2024 OneMinuteCode. All rights reserved.