c program crashes while trying to open a file with variable filename - c

As stated in the title, i ask for the user to provide the filename and i use gets to save it in str. Then i try to access the file using the name and the program crashes.
int openFile(FILE *fp){
puts("What's the name of the file (and format) to be accessed?");
char str[64];
gets(str);
fp = fopen((const char *)str, 'r');
...
return 0;
In main:
FILE *fp; // file pointer
openFile(fp);
The filename i enter (data.txt) is indeed in the same directory as the rest of the project so that should not be the problem. I've tried testing if the file is opened correctly (which it should) but it keeps crashing right after i give the name.

The main problem is that you are trying to set an argument passed by value in a function and expect the value to be changed outside. This can't work.
Currently you have:
void openFile(FILE* fp) {
fp = ...
}
int main()
{
FILE* fp;
openFile(fp);
}
But fp in main() is passed as a pointer by value. Which means that inside openFile you are setting a local variable, while the passed one is not modified.
To solve the problem you can:
directly return a FILE* from openFile
accept a pointer to pointer argument to be able to set it, eg void openFile(FILE** fp) and then openFile(&fp)
Mind that the second argument of fopen is a const char* not a single char, "r" should be used.

It should be fp = fopen(str, "r");, because fopen() expects mode as a char * pointing to a string, rather than a single char.
Also, since parameters in C are passed by value, your fp won't get modified after openFile() is called. To get it work, you'll have to rewrite it, and call it by openFile(&fp);. Here is an example:
void openFile(FILE **fp) {
puts("What's the name of the file (and format) to be accessed?");
char str[64];
fgets(str, 64, stdin);
str[strcspn(str, "\n")] = '\0';
*fp = fopen(str, "r");
}
fgets() is used to provide buffer overflow protection.

Related

c++ fopen() returning a NULL pointer when I try using a char array or pointer

I'm attempting to open a file with fopen and storing it into a FILE*.
The code I have is as follows:
char path[300];
printf("File name: ");
fgets(path, 300, stdin);
FILE* fp;
fp = fopen(path, "r");
if (fp == NULL) {
printf("file does not exist\n");
}
When I run the above code, I get a file not found error; however, when I hardcode the file name:
fp = fopen("test.txt", "r");
The code works as intended.
I think the issue might have something to do with the data type since fopen requires a const char* for it's parameter. I've tried using char*'s but to no avail.
No, it's much simpler than that. When you use fgets the newline character at the end of the line gets included in the char array. That newline is then messing up your attempt to open the file.
Incidentally fopen does not require a const char* parameter. It requires a parameter which can be converted to a const char*. That includes char* as well as char [].

C function fopen(); error: too many arguments to the function

Why can I not do this?
fopen("%s",stringarray,fpointer);
The above returns an error that says too many arguments to function.
But this works,
fopen("file.txt",fpointer);
How can I get around this problem? Do I have to modify the headers in the code?
You cannot call
fopen("%s",stringarray,fpointer);
because that's not the way fopen works. You don't get to make up the way you want to call a standard function like this -- you have to call it the way the documentation says to. You can't call
fopen("file.txt",fpointer);
either. You have to call something like
fpointer = fopen("file.txt", "r");
assuming that you have declared
FILE *fpointer;
so that fpointer will be your "open file pointer" or "file handle" as you read the file file.txt.
Assuming stringarray is a char * (really a chararray), simply pass it directly into fopen. There's no need to format it with %s, it's already a string.
FILE *fp = fopen(stringarray, "r");
Functions in C take very, very, very specific arguments. fopen takes a filename as a char * and the mode to open the file (read, write, etc...) as another char *. It returns a pointer to the opened file, or NULL if there was an error.
If you did need to do some sort of formatting, you'd use sprintf to do the formatting and pass the result into fopen.
// Allocate memory to store the result of sprintf
char filename[256];
char name[] = "foo";
// filename = foo.txt
sprintf(filename, "%s.txt", name);
// Open foo.txt
FILE *fp = fopen(filename, "r");
fopen (const char *filename, const char *mode)
If you take a look in fopen function, it takes only two arguments as input. So, you cannot use it like fopen("%s",stringarray,fpointer);. For more information about fopen() visit here

How to overwrite a preallocated char array in C

I initialize a char array as a global variable in my C program with a default file location/name as
char file[] = "/home/jack/files/data.txt";
Later in the program, if a condition is satisfied I read a file containing a new file name
int read_new_file(char *fname)
{
FILE *inp;
char buffer[255];
char oldFile[127], newFile[127];
inp = fopen(fname, "r");
while ( fgets(buffer, 255, inp) != NULL )
{
sscanf(buffer, "%s %s",oldFile,newFile);
file = newFile; // <---- Is this wrong/unsafe?
}
return 0;
}
I should note that it is assumed file fname only contains one line with 2 strings. This was just to show the general framework of the code. My question, as highlighted in the code, is it wrong or unsafe to simply try and reassign the char file variable with the new string?
The size of the newFile string will likely differ from it's original default size. The default has to be predefined, since the condition may not require a new file to be read. If the assignment is wrong or unsafe, what is a better approach?
You need to declare file so it's large enough to hold newFile.
char file[127] = "/home/jack/files/data.txt";
Then when you want to update it, you use:
strcpy(file, newFile);
file = newFile; // <---- Is this wrong/unsafe?
It is wrong since file is an array. The compiler won't let you do that.
Whether it is safe or not is not relevant since you can't do it.
Use strcpy instead.
strcpy(file, newFile);

C programming: how to fopen a designated file and dynamically allocate its contents into a 2D array?

Basically my program prompts the user to enter the name of a file that he wants to open. My program is supposed to open that file and scan its contents into a 2D array. But how do you do it so that the program opens the file that the user designates? Here's my code so far:
#include <stdio.h>
#include <string.h>
FILE *open_file(int ar[3][4]);
int main()
{
FILE *fp;
int ar[3][4];
fp = open_file(ar);
}
FILE *open_file(int ar[3][4])
{
FILE *fp;
int i;
char file[80];
printf("Please input file name ");
scanf("%s", &file); //am I supposed to have written ("%s", file) instead?
fp = fopen("%s", "r");// very confused about this line; will this open the file?
for (i = 0; i < 12; i++)
fscanf(fp, "%d", &ar[i][]); //how do you scan the file into a 2D array?
}
To use malloc, I'd have to write something like fp = (int *)malloc(sizeof(int));?
scanf("%s", &file); // am I supposed to have written ("%s", file) instead?
Yes, but not for the reason you would think. So
scanf("%s", file);
is correct instead (explanation: the %s format specifier tells scanf() to expect a char *, but you're passing it a char (*)[80] if you write the addressof operator, and mismatching type specifiers for printf() and scanf() invoke undefined behavior).
fp = fopen("%s", "r"); // very confused about this line; will this open the file?
No, it won't. It will open the file named %s. You have to write
fp = fopen(file, "r");
instead. Don't assume you can use a format string where you can't.
The varialble file contains the name of the file entered by the user, so pass it to fopen. What you have there is a format string.
fp = fopen(file, "r");

Enter custom file name to be read?

I want to allow users to type the name of any .txt file to be read/written.
This is my code :
printf("Enter .txt file name\n");
scanf("%s",&fname);
FILE *inputf;
inputf=fopen(&fname,"w");
Problem is this method does not work (having &fname) as a parameter.
I can imagine its because C needs "filename.txt" for it work ... even if I enter for example : "custom.txt", the program returns an error of "Storage block not big enough for this operation"
What is the correct method to accomplish this ?
Im using C and im pretty much using basic commands .. (not too advanced)
Thanks alot !!!
The scanf statement will try to store the filename entered as input into the memory, starting from the address passed as its 2nd argument. So you have to allocate/reserve some memory and pass its address to scanf.
As you have not mentioned the type of fname, let me list the possibilities and then answer you.
char fname;
The 2nd argument of scanf and the 1st argument of fopen, both need to be char *. So, passing address of fname or &fname is valid. But it has a problem.
When you declare 'char fname' you are reserving memory for only 1 char. When scanf tries to store the input filename, it will have to write more than 1 char. So eventually you end up overwriting some other memory.
char *fname;
In this case pass fname to both scanf and fopen, instead of '&fname'.
But you have to allocate some memory (e.g. using malloc), before using fname. Otherwise fname will contain some garbage address and scanf will try to overwrite some random memory.
So either declare fname as char fname[N] or char *fname = malloc(N+1); (where N is the maximum possible length of filename you would be entering).
And then, pass fname to both scanf and fopen as follows:
scanf("%s",fname);
inputf = fopen(fname,"w");
Defining fname as a char array, and assuming you expect the filename (without extension) as input (which means you need to append the extension to it):
char fname[128];
printf("Enter .txt file name\n");
scanf("%123s",fname);
strcat(fname,".txt");
FILE *inputf;
inputf=fopen(fname,"w");
Note that an input length check is added to avoid buffer overflow errors in scanf.
I think this can help
#include <stdio.h>
void read_name(char *);
int main(void)
{
char name[BUFSIZ];
char line[BUFSIZ];
FILE *f;
printf("Name ");
read_name(name);
if ( (f=fopen(name,"r"))==NULL)
return -1;
else
return 0;
fclose(f);
}
void read_name(char *s)
{
int i;
fgets(s,BUFSIZ,stdin);
for (i=0; s[i]!='\n'; i++);
s[i]='\0';
return;
}
Try inputf = fopen(fname,"w");.
Also if you want to just read a filename, you can just do sscanf(file,"%s",t) and it will store the filename into t !

Resources