I'm trying to relearn C from dabbling with it about 5 year ago. Specifically, I'm trying to learn how to extract a number of operations from main and make them into a function, with the aim of moving them to a library file next.
This seems to be working:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct arguments {
char *word_file; /* Default name for input file */
} arguments;
int main (int argc, char *argv[]) {
arguments.word_file = "dummy";
FILE *fp;
fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
char word[60];
fgets (word, sizeof(word), fp);
printf("Word is %s\n", word);
}
By the way, 'dummy' is:
$ cat dummy
dog
cat
$
No matter how I try this, it either gives me compile errors, or seg faults when I run it:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct arguments {
char *word_file; /* Default name for input file */
} arguments;
void getfile(FILE *fp) {
fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
}
int main (int argc, char *argv[]) {
arguments.word_file = "dummy";
FILE *fp;
getfile(fp);
char word[60];
fgets (word, sizeof(word), fp);
printf("Word is %s\n", word);
}
I've tried changing from *fp to fp to &fp without success. I'm sure that there's something that I don't understand about file pointers, but can't figure it out.
Thanks for any help and suggestions.
-Kevin
CodePudding user response:
You have two choices
First, have 'getfile' return the file handle (this is the most idiomatic way in c)
FILE *getfile() {
FILE *fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
return fp;
}
and in main
FILE *fp = getfile(fp);
or have getfile update the fp value based , using c-style 'pass by reference'
void getfile(FILE **fp) {
*fp = fopen(arguments.word_file, "r");
if (*fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
}
in main
File *fp = NULL;
getfile(&fp);
CodePudding user response:
fp
shouldn't be an argument to getfile()
, it should be the return value.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct arguments {
char *word_file; /* Default name for input file */
} arguments;
FILE *getfile() {
FILE *fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
return fp;
}
int main (int argc, char *argv[]) {
arguments.word_file = "dummy";
FILE *file_ptr;
file_ptr = getfile();
char word[60];
fgets (word, sizeof(word), file_ptr);
printf("Word is %s\n", word);
}
If there's some reason you really need to pass it as a parameter, see Changing address contained by pointer using function
CodePudding user response:
The problem is that the pointer fp
is passed to the function getfile
by value.
getfile(fp);
That is the function deals with a copy of the value of the passed pointer fp
. So changing the copy in the function does not reflect on the value of the original pointer.
You need to pass the pointer by reference.
In C passing by reference means passing an object indirectly through a pointer to it. Dereferencing the pointer you can get a direct access to the original object.
So declare and define the function like
void getfile(FILE **fp) {
*fp = fopen(arguments.word_file, "r");
if ( *fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
}
and call the function like
getfile(&fp);