Reputation: 4028
I could use some help understanding something puzzling to me. It concerns the position of of fopen() to read out a file.
Following code (C compiled with gcc 4.5.2):
#include <stdlib.h>
#include <stdio.h>
void try_fopen(FILE* f_handle, const char* f_name, const char* mode) {
f_handle = fopen(f_name, mode);
if( f_handle == NULL ) {
fprintf(stderr, "Error: Unable to open '%s'.", f_name);
exit(EXIT_FAILURE);
}
}
int cnt_ones(FILE* pFile) {
int c;
int n = 0;
do {
c = fgetc (pFile);
if (c == '1') n++;
} while (c != EOF);
return n;
}
Why is it that putting the fopen in a function gives a Segfault:
int main (int argc, char** argv) {
FILE * pFile;
try_fopen(pFile, argv[1], "r"); // Gives a Segfault
printf ("The file contains %d ones.\n", cnt_ones(pFile) );
fclose (pFile);
return 0;
}
While putting it into the main (along with the if doesn't):
int main (int argc, char** argv) {
FILE * pFile;
pFile = fopen(argv[1], "r"); // While this doesn't give a Segfault
if( pFile == NULL ) {
fprintf(stderr, "Error: Unable to open '%s'.", argv[1]);
exit(EXIT_FAILURE);
}
printf ("The file contains %d sign characters.\n", cnt_ones(pFile) );
fclose (pFile);
return 0;
}
Upvotes: 0
Views: 703
Reputation: 24895
The reason is simple, when you pass FILE* to function, it's updation will be lost as it is passed by Value. Try passing FILE ** to the function and it will work. Refer to Binyamin Sharet's answer above for the code snippet
The reason for this can be understood by reading this link
Or
You can change the function try_open to return FILE * as the return value.
FILE *try_fopen(const char* f_name, const char* mode)
{
FILE *f_handle = NULL;
*f_handle = fopen(f_name, mode);
if( *f_handle == NULL )
{
fprintf(stderr, "Error: Unable to open '%s'.", f_name);
exit(0);
}
}
//In the main function.
FILE *pFile = try_fopen(argv[1], "r");
Upvotes: 0
Reputation: 4589
You can either do :
File * fp;
try_fopen( &fp,.....); /* void try_fopen (FILE ** fp,....) */
or the following :
File * fp = try_fopen("file name"); /* FILE * try_fopen (const char * file_name,...) */
Upvotes: 1
Reputation: 73443
Because the pointer pFile
is passed by value to the function try_open
. The value modified inside the function is not available in the main
. To solve this, you need to pass the address of the pointer to the function, so try_open
would accept FILE**
and assign the result of fopen
to *pFile
. While calling this function you should pass the address of pFile
using &pFile
.
Upvotes: 1
Reputation: 137322
C is pass by value, not by reference, so you need to pass the pointer to pFile
, otherwise you don't change it outside of the function scope:
void try_fopen(FILE** f_handle, const char* f_name, const char* mode) {
*f_handle = fopen(f_name, mode);
if( *f_handle == NULL ) {
fprintf(stderr, "Error: Unable to open '%s'.", f_name);
exit(EXIT_FAILURE);
}
}
// ...
try_fopen(&pFile, argv[1], "r");
Upvotes: 4