Enter custom file name to be read? - c

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 !

Related

getline doesn't store the string in the variable

I wrote a function that opens a file which name is given by the user:
#include <stdio.h>
#include <stdlib.h>
void getfile(FILE** pfile)
{
void getrep(char*,char,char);
void clear(void);
char rep;
char* nfile=NULL;
printf("Name of the file: ");
clear();
nfile=NULL;
getline(&nfile,NULL,stdin);
printf("The name of the file is: %s\n",nfile);
*pfile=fopen(nfile,"r");
while(!*pfile)
{
printf("Can't open the file. Want to retry <Y/N> ? ");
getrep(&rep,'Y','N');
if(rep=='Y')
{
system("clear");
free(nfile);
nfile=NULL;
printf("Name of the file: ");
clear();
getline(&nfile,NULL,stdin);
printf("The name of the file is: %s\n",nfile);
*pfile=fopen(nfile,"r");
}
else
exit(-1);
}
free(nfile);
}
The getrep function simply ensures that the user gives Y or N or y or n as an answer. Here's the clear function:
#include <stdio.h>
void clear(void)
{
char c;
while((c=getchar())!=EOF && c!='\n');
}
Here's what I get when I run the program:
Name of the file: Data.dat
The name of the file is: (null)
Can't open the file. Want to retry ?
When I used the debugger gdb and printed the value of nfile after entering the file's name, it remains 0x0, i.e, NULL. (You might have noticed that I allocated no memory for nfile, but I initialized this variable to NULL so that getline will do it for me. I'm using getline instead of gets because it seems better and, after all, ubuntu 16.04 hates gets)
I believe the reason why this is happening is that when the user is asked to enter the name, it's due to the getchar() in the clear function. Thus the name entered by the user is erased, and the nfile receives nothing in getline. I also tried using this clear function instead:
#include <stdio.h>
void clear2(void)
{
char c;
while((c=getchar())!='\n');
}
Unfortunately, I get the same result. I used fflush(stdin); instead of clear(); but this time the program skips getline not letting the user enter anything. I also removed the space that comes after file: in printf("Name of the file: "); but nothing changes.
Could you please help me? Thanks in advance!
From the getline manual page`:
If *lineptr is set to NULL and *n is set 0 before the call, then getline() will allocate a buffer for storing the line
Since you pass a NULL pointers as the n argument, the call will not allocate a buffer for you. You need to explicitly pass a pointer to a variable of size_t that has been initialized to zero:
char *nfile = NULL;
size_t n = 0;
getline(&nfile,&n,stdin);
The issue is in the getline call.
The second parameter passed in is NULL which is incorrect.
Rather it should be like this:
size_t n = 0;
getline(&nfile,&n,stdin);
As per the man page for getline, states:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
If *lineptr is set to NULL and *n is set 0 before the call, then
getline() will allocate a buffer for storing the line. This buffer
should be freed by the user program even if getline() failed.

How to write string member of structure to file using fwrite?

I have a code in c and I am using structure which contains name to get user input using scanf() function. whenever i try to write the name in file using fwrite() it does not write all the characters I have enter but only few(only four characters). I know the problem is with sizeof() of fwrite() function but I cant figure what should be written inside sizeof() so I can store the string I get from user. I know it will work if char name[20] is used instead of char *name.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
struct Emp
{
char *name;
char *addr;
}*e;
int main()
{
FILE *fp;
e=(struct Emp *)malloc(sizeof(struct Emp));
e->name=(char *)malloc(sizeof(char )*20);
fp=fopen("Employee.txt","r+");
if(fp==NULL)
{
fp=fopen("Employee.txt","w+");
if(fp==NULL)
{
printf("cannot open the file");
exit(1);
}
}
printf("Name of Employee: ");
scanf("%s",e->name);
fwrite(e->name,sizeof(e->name),1,fp);
return 0;
}
If I input name of Employee: chiranjibi fwrite()function will only write chir in the file. Is there any way to get this code working so i can input any number of characters from user?
sizeof(e->name) returns the size of the pointer (typically 4 or 8)
Use strlen(e->name) to get the length of the string. Assuming the string in null terminated.
You can directly give 4 as the second parameter to fwrite() call.
fwrite(e->name,4,1,fp);
Hence, it only write first four character into the file. If you want to change based on user input, declare a variable and fetch from user the number of character to be printed and then pass the variable as the second parameter to this function call.

How do I read lines from a file in C?

I need to read in a file. The first line of the file is the number of lines in the file and it returns an array of strings, with the last element being a NULL indicating the end of the array.
char **read_file(char *fname)
{
char **dict;
printf("Reading %s\n", fname);
FILE *d = fopen(fname, "r");
if (! d) return NULL;
// Get the number of lines in the file
//the first line in the file is the number of lines, so I have to get 0th element
char *size;
fscanf(d, "%s[^\n]", size);
int filesize = atoi(size);
// Allocate memory for the array of character pointers
dict = NULL; // Change this
// Read in the rest of the file, allocting memory for each string
// as we go.
// NULL termination. Last entry in the array should be NULL.
printf("Done\n");
return dict;
}
I put some comments because I know that's what I'm to do, but I can't seem to figure out how to put it in actual code.
To solve this problem you need to do one of two things.
Read the file as characters then convert to integers.
Read the file directly as integers.
For the first, you would use freed into a char array and then use atoi to convert to integer.
For the second, you would use fscanf and use the %d specify to read directly into an int variable;
fscanf does not allocate memory for you. Passing it a random pointer as you have will only cause trouble. (I recommend avoid fscanf).
The question code has a flaw:
char *size;
fscanf(d, "%s[^\n]", size);
Although the above may compile, it will not function as expected at runtime. The problem is that fscanf() needs the memory address of where to write the parsed value. While size is a pointer that can store a memory address, it is uninitialized, and points to no specific memory in the process' memory map.
The following may be a better replacement:
fscanf(d, " %d%*c", &filesize);
See my version of the spoiler code here

Reading string input from file in C

I have a text file called "graphics" which contains the words "deoxyribonucleic acid".
When I run this code it works and it returns the first character. "d"
int main(){
FILE *fileptr;
fileptr = fopen("graphics.txt", "r");
char name;
if(fileptr != NULL){ printf("hey \n"); }
else{ printf("Error"); }
fscanf( fileptr, "%c", &name);
printf("%c\n", name);
fclose( fileptr );
return 0;
}
When I am using the fscanf function the parameters I am sending are the name of the FILE object, the type of data the function will read, and the name of the object it is going to store said data, correct? Also, why is it that I have to put an & in front of name in fscanf but not in printf?
Now, I want to have the program read the file and grab the first word and store it in name.
I understand that this will have to be a string (An array of characters).
So what I did was this:
I made name into an array of characters that can store 20 elements.
char name[20];
And changed the parameters in fscanf and printf to this, respectively:
fscanf( fileptr, "%s", name);
printf("%s\n", name);
Doing so produces no errors from the compiler but the program crashes and I don't understand why. I am letting fscanf know that I want it to read a string and I am also letting printf know that it will output a string. Where did I go wrong? How would I accomplish said task?
This is a very common problem. fscanf reads data and copies it into a location you provide; so first of all, you need the & because you provide the address of the variable (not the value) - that way fscanf knows where to copy TO.
But you really want to use functions that copy "only as many characters as I have space". This is for example fgets(), which includes a "max byte count" parameter:
char * fgets ( char * str, int num, FILE * stream );
Now, if you know that you only allocated 20 bytes to str, you can prevent reading more than 20 bytes and overwriting other memory.
Very important concept!
A couple of other points. A variable declaration like
char myString[20];
results in myString being a pointer to 20 bytes of memory where you can put a string (remember to leave space for the terminating '\0'!). So you can usemyStringas thechar *argument infscanforfgets`. But when you try to read a single character, and that characters was declared as
char myChar;
You must create the pointer to the memory location "manually", which is why you end up with &myChar.
Note - if you want to read up to white space, fscanf is the better function to use; but it will be a problem if you don't make sure you have the right amount of space allocated. As was suggested in a comment, you could do something like this:
char myBuffer[20];
int count = fscanf(fileptr, "%19s ", myBuffer);
if(count != 1) {
printf("failed to read a string - maybe the name is too long?\n");
}
Here you are using the return value of fscanf (the number of arguments correctly converted). You are expecting to convert exactly one; if that doesn't work, it will print the message (and obviously you will want to do more than print a messageā€¦)
Not answer of your question but;
for more efficient memory usage use malloc instead of a static declaration.
char *myName // declara as pointer
myName = malloc(20) // same as char[20] above on your example, but it is dynamic allocation
... // do your stuff
free(myName) // lastly free up your allocated memory for myName

there is a runtime error in this file handling code

This is a simple code to store a person's name and number in a file.the problem occurs when i also want to include the person's contact number.the error occurs after the contact number is scanned.
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp;//file pointer
char *name,*number;
char filename[]="testfile.txt";//file to be created
fp=fopen(filename,"w");
if(fp==NULL)
{
printf("\nerror\n");
exit(1);
}
fprintf(stdout,"Please enter a name:\t");
fscanf(stdin,"%s",name);
fprintf(fp,"%s",name);
fprintf(stdout,"Enter contact number:\t");
fscanf(stdin,"%s",number);
fprintf(fp,"%s",number);
fclose(fp);
}
you did not malloc() the memory for name and number!
Here is an extract of your code:
char *name;
fscanf(stdin,"%s",name);
name is a pointer to a char (or the first char of a string) but you didn't initialized it's value so it points anywhere.
The second line with fscanf read a word and write it in memory at the address pointed by name. So, basically, fscanf will try to write somewhere it will probably won't be able to write.
There are 2 solutions:
either you change char *name to char name[MAXNAME] (where MAXNAME is a constant value)
either you do a malloc: char *name = malloc(MAXNAME)
The same for number.
Allocate memory for pointers name and number
name = malloc(sizeof(char) * num_elements);
number = malloc(sizeof(char) * num_elements);

Resources