readFile function without fclose - c

I have a function to add new words to a .txt file. I still have to make a function to learn the vocabulary. Several times I have to read the file, so I try to make a function for it.
void readFile(FILE* fp, char *name){
if((fp=fopen(name,"a"))==NULL) {
printf("I cannot open file!\n");
exit(1);
}
}
And I don't want to close the file in this function, because in other functions I would operate on this file.
int main(){
FILE *file;
readFile(file,"verbs.txt");
fclose(file);
return 0;
}
If I try to close file like that, I get core dump. But if fclose is in a readFile it works well. So it is possible to write readFile function without fclose()?

Change it to:
void readFile(FILE** fp, char *name){
if((*fp=fopen(name,"a"))==NULL) {
printf("I cannot open file!\n");
exit(1);
}
}
int main(){
FILE *file=NULL;
readFile(&file,"verbs.txt");
//Use the file here after checking for NULL.
if (file != NULL)
fclose(file); //check for NULL before closing.
return 0;
}

All parameters in C are pass by value. Changing the value of fp in your function does not change the value in the calling function.
You can return the value and use that instead:
FILE *readFile(char *name){
FILE *fp;
if((fp=fopen(name,"a"))==NULL) {
printf("I cannot open file!\n");
exit(1);
}
return fp;
}
int main(){
FILE *file = readFile("verbs.txt");
fclose(file);
return 0;
}

If you want the readFile function to manage its own file pointer, I would do it more like this:
static FILE *fp = NULL;
void readFile(char *name){
if((fp=fopen(name,"a"))==NULL) {
printf("I cannot open file!\n");
exit(1);
}
}
void closeFile(){
if(fp!=NULL) {
fclose(fp);
fp = NULL;
}
}

Related

How to pass file pointer to a function in c

I want to pass the file pointer as an argument to view function. And then I want to get the output the data on file from the view function. But every time telling me file not found.
#include<stdio.h>
void view(FILE *file){
char c;
file=fopen(file,"r");
if(file==NULL){
printf("file not found");
}
else{
while(!feof(file)){
c=fgetc(file);
printf("%c",c);
}
fclose(file);
}
}
int main(){
FILE *file;
file=fopen("hello.txt","w");
char s[]="hello world";
fprintf(file,"%s",s);
fclose(file);
printf("Enter 1 to read file");
int n;
scanf("%d",&n);
if(n==1)
view(file);
return 0;
}
Your error is here:
file=fopen(file,"r");
Use something like this:
file=fopen("file name","r");
As already stated in the comments, and in this answer, the fopen argument is wrong, you pass a pointer to file when you should pass the file path.
Other than that you could refactor your code so that you wouldn't have to close and reopen the file:
void view(FILE *file)
{
// the file is already opened, no need to reopen it
int c;
while ((c = fgetc(file)) != EOF) // better read routine
{ // you could also use fgets to read the whole line
printf("%c", c);
}
fclose(file);
}
int main()
{
FILE *file;
file = fopen("hello.txt", "w+"); // open to write and read
int n;
char s[] = "hello world";
if (file == NULL)
{
printf("file not found"); // perror("fopen"); would be better
return EXIT_FAILURE; // #include <stdlib.h>
}
fprintf(file, "%s", s);
printf("Enter 1 to read file: ");
if (scanf("%d", &n) == 1)
{
if (n == 1)
{
rewind(file); // reset file pointer offset to the beginning
view(file);
}
}
}

Keep counter in txt file

I am trying to keep a conter in txt file, I write a function and when I call the fuction, function should read the txt after, it should increment and write file.
In my txt ("test.txt") there is only one character. It is "0".
Code is here:
void readAndwrite(){
int total = 23;
FILE *fread, *fwrite;
fread = fopen("test.txt", "r");
fwrite = fopen("test.txt","w");
fscanf(fread,"%d",&total);
fclose(fread);
++total;
fprintf(fwrite ,"%d",total);
fclose(fwrite);
}
int main(int argc, char const *argv[])
{
readAndwrite();
readAndwrite();
readAndwrite();
readAndwrite();
readAndwrite();
readAndwrite();
return 0;
}
Why this is not working?
You can open twice but not in same time because the "w" flag destroy contents, so:
void readAndwrite(){
int total = 23;
FILE *f;
f = fopen("test.txt", "r");
if(!f) {
perror("File opening failed");
}
else{
fscanf(f,"%d",&total);
fclose(f);
printf("%d\n", total);
++total;
f = fopen("test.txt","w");
fprintf(f ,"%d",total);
fclose(f);
}
}
If you want to read/write in same time take a look to the doc and "w+" flag

C passing File stream as a function parameter

This function gives infinite loop. Any Help? And is it even possible to pass file stream to a function as argument.
#include<stdio.h>
#include<stdlib.h>
void fcopy(FILE *inFILE1){
FILE *inFILEcopy;
char a;
inFILEcopy=fopen("C:/Users/labuser.pcroot-PC.003/Desktop/empoleecopy.bak","w");
do{
a=fgetc(inFILE1);
fputc(a,inFILEcopy);
if(feof(inFILE1))break;
}while(1);
}
int main(){
FILE *inFILE;
inFILE=fopen("C:/Users/labuser.pcroot-PC.003/Desktop/empolee.dat","w");
fputs("My name is Anthony",inFILE);
fcopy(inFILE);
}
To summarize mine and Phil Brubaker comments, modify your code in this way:
#include<stdio.h>
#include<stdlib.h>
void fcopy(FILE *inFILE1) {
FILE *inFILEcopy;
char a;
inFILEcopy = fopen("C:/Users/scifani/Desktop/empoleecopy.bak", "w");
do{
a = fgetc(inFILE1);
fputc(a, inFILEcopy);
if (feof(inFILE1))break;
} while (1);
fclose(inFILEcopy);
}
int main(){
FILE *inFILE;
inFILE = fopen("C:/Users/scifani/Desktop/empolee.dat", "w");
fputs("My name is Anthony", inFILE);
fclose(inFILE);
inFILE = fopen("C:/Users/scifani/Desktop/empolee.dat", "r");
fcopy(inFILE);
}
FILE* fcopy(char* yourFile) { // Or parse a FILE like you did but with a pointer
FILE *inFILEcopy;
inFILEcopy = fopen("C:/Users/labuser.pcroot PC.003/Desktop/empoleecopy.bak", "w");
if (inFILEcopy == NULL)
return NULL; // You'll have to check null to see if fcopy() failed
FILE* inFILE1 = fopen(yourFile, "r");
if (inFILE1 == NULL) {
puts("File to be copied does not exist.\n");
return NULL;
}
for (char a = fgetc(inFILE1); feof(inFILE1);)
{
fputc(a, inFILEcopy);
if (ferror(inFILE1) || ferror(inFILEcopy)) { // If error in one of the two files
if (fclose(inFILE1))
puts("Couldn't close inFILE1\n");
if (fclose(inFILEcopy));
puts("Couldn't close inFILEcopy\n");
puts("Error during copy.\n");
return NULL;
}
}
return inFILEcopy;
}
int main() {
FILE *inFILE;
inFILE= fopen("C:/Users/labuser.pcroot-PC.003/Desktop/empolee.dat","w");
if (inFILE != NULL)
{
fputs("My name is Anthony", inFILE);
if (!ferror(inFILE) || fclose(inFILE)) // If no error when writing and closing works, we can copy
{
inFILE = fcopy("C:/Users/labuser.pcroot-PC.003/Desktop/empolee.dat");
if (inFILE != NULL)
puts("Copy success\n");
}
}
}
I think this is the best way to do this. I am open to any improvement though. Check this link if you have any question regarding the error checkings, someone explains the best way to do so. This should work perfectly.

Read the next line of a file every time a function is called

I have a text file with numbers on each line. I want to write a function in C that reads in the file and returns the next number in the file every time the function is called.
For example if I have these numbers:
100
200
300
400
and a function called get_number(), if I call get_number() it will return 100, if I call it again, it will return 200, etc.
This is what I've written so far but every time the function is called, it always goes back to the first number in the text file.
int * get_number()
{
FILE* file = fopen("random_numbers.txt", "r");
char line[256];
if (file==NULL)
{
perror ("Error reading file");
}
else
{
fgets(line, sizeof(line), file);
printf("%s", line);
}
return 0;
}
here's a version that does exactly that :
int * get_number(long* pos)
{
FILE* file = fopen("random_numbers.txt", "r");
char line[256];
if (file==NULL)
{
perror ("Error reading file");
}
else
{
fseek(file , *pos , SEEK_CUR);
fgets(line, sizeof(line), file);
printf("%s", line);
}
*pos = ftell(file);
return 0;
}
and you call it from main like this
long pos = 0;
get_number(&pos);
or better yet use a static variable
int * get_number()
{
static long pos = 0;
FILE* file = fopen("random_numbers.txt", "r");
char line[256];
if (file==NULL)
{
perror ("Error reading file");
}
else
{
fseek(file , pos , SEEK_CUR);
fgets(line, sizeof(line), file);
printf("%s", line);
}
pos = ftell(file);
return 0;
}
It's a good idea to avoid opening a file repeatedly. Instead of opening the file every time you call the function, open it once, then pass a file pointer to the function each time you call it.
int * get_number(FILE *file)
{
char line[256];
fgets(line, sizeof(line), file);
printf("%s", line);
return 0;
}
int main()
{
FILE *file = fopen("random_numbers.txt", "r");
if (file == NULL)
{
perror("Error opening file");
return 1;
}
while (!feof(file))
{
get_number(file);
}
fclose(file);
}
Open the file in the calling function.
Pass the FILE* to get_number.
Return an int from get_number, not an int*.
Here's a modified get_number.
int get_number(FILE* file)
{
// This is the core functionality.
// You should add error handling code
int number;
int n = fscanf(file, "%d", &number);
if ( n != 1 )
{
// Add error handling code.
}
return number;
}
This is normal, because you open your file each time you call get_number(); (this is even worse because no fclose are called.
What you want maybe is giving a file descriptor at get_number(); in this way :
void get_number(FILE* file)
{
char line[256];
if (file==NULL)
perror ("Bad descriptor given");
else
{
if (fgets(line, sizeof(line), file) == NULL)
perror("Fgets failed");
else
printf("%s", line);
}
}
And what you want, outside your function, is to do the following :
FILE * file = fopen("random_numbers.txt", "r");
get_number(file); // 100
get_number(file); // 200
fclose(file);
I made your function void, because the return here is pointless. You could change that and use atoi and the return fonction.

Why does it matter where fopen is used?

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;
}
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");
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.
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,...) */
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");

Resources