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);
Related
I tried to read the data from a text file and add it to an array. However, it raises an error ["Warning:" assignment makes integer from pointer without a cast]. I declared fp is a variable of FILE, and already open text file with read-only mode.
char arrRequest[100];
char strRow[10];
int i = 0;
.....................
void request(){
for (;;){
fgets(strRow, 10, (FILE *)fp);
i = i + 1;
arrRequest[i] = strRow; // it raises an error here
printf("value of %d is %s:\n", i, arrRequest[i]);
}
}
Could you please tell me why it happens?
Thanks.
In your code, you declared:
char arrRequest[100];
char strRow[10];
But in for loop:
arrRequest[i] = strRow;
It means you assign a character to an array of character. So it raises an error here.
If you want to copy a string, you should usestrcpy function. You can declare an array of pointer or 2D array as the comment above:
char arrRequest[100][10]
// using strcpy
strcpy(arrRequest[i], strRow);
Or
char * arrRequest[100]
// allocate for each arrRequest element
arrRequest[i] = malloc(strlen(strRow)*sizeof(char) + 1);
if (!arrRequest[i])
// Handle error
OT, you should use while loop to stop reading the file if there is nothing still to read. You can use for loop as you used in your code, but have to stop reading until you meet EOF. Do not need to cast fp if you declare FILE *fp before.
while(fgets(strRow, 10, fp);)
I'm trying to copy contents of one file into another. Before I finished, I wanted to print the contents out on screen to see that things are working. But they didn't.
I included...
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
and my code is...
void decodeBin(char * filename){
//opens filename for reading and outfilename for writing
FILE * input = fopen(filename, "r");
char file_name[] = "";
strcpy(file_name, filename);
char out_file[] = "out";
strcat(out_file, file_name);
FILE * output = fopen(out_file, "w");
char ch;
if (input != NULL){
while((ch = fgetc(input)) != EOF)
printf("%c", ch);
}
fclose(input);
fclose(output);
}
I looked at the other stack overflow posts, which suggested to check if file pointer is not null, which I do. What's going wrong?
You're causing undefined behavior by writing outside the bounds of the file_name and out_file arrays. When you don't specify a size for the array, the size is determined from the string you use to initialize it. So it's equivalent to
char file_name[1] = "";
char out_file[4] = "out";
The extra byte is for the trailing null.
Since you didn't declare the arrays big enough for the strings you're copying into them, you get undefined behavior.
You need to declare the size of the arrays big enough to hold the largest possible filename. Or use malloc() to size it in terms of the parameters.
There's no need for the file_name variable, since it's just a copy of filename, and you can use that directly.
char *outfile = malloc(strlen(filename) + sizeof("out"));
sprintf(outfile, "out%s", filename);
Then at the end of the function, do
free(outfile);
With the following program, I wish to read a file (say, a text file) and store all of it's contents in a variable. So, to achieve it, I cooked up the following with the help of Stack Overflow suggestions. However, this program returns the contents of a file twice.
For instance, let the following program read a text file with the following contents:
John Start 0
Using *,15
Then, the program will display the following:
John Start 0
Using *,15
John Start 0
Using *,15
Thus, I would like your help in finding out the problem. Thanks a lot in advance!
//Program to read a file and store it's contents in a single variable
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
/*Reads contents of a file and returns address of variable, in which file contents are stored*/
char* fileRead(char*);
//Concatenates 2 strings
char* concat(char*,char*);
//Calculates the size of the file
unsigned long fsize(char* file);
int main()
{
char *prt, *out;
//Allocate memory & take the input of the file name to read
prt = malloc(256);
printf("\nEnter the name of the file : \t");
scanf("%255s",prt);
//Copy the address of read data & output it
out = fileRead(prt);
printf("\nContents : \n-----------------\n%s", out);
free(out);
free(prt);
return 0;
}
char* fileRead(char *file)
{
//function to read the contents of a file
FILE *fip;
char *text, *temp, read[1024];
int size, i=0;
fip=fopen(file, "r");
size=(int)fsize(file);
temp = malloc(size*10);
text = temp;
//If the file doesn't exist then...
if(fip==NULL)
{
temp = strdup("ERROR : File doesn't exist! Please try again!\n");
return temp;
}
//Begin concatenation, once after the file reading has been initiated
while(fgets(read, 1024, fip) != NULL)
{
temp = concat(text,read);i++;
}
fclose(fip);
return text;
}
char* concat(char* dest, char* src)
{
//function to concatenate src to dest
while(*dest) dest++;
while(*dest++ = *src++);
return --dest;
}
unsigned long fsize(char* file)
{
//calculates the size of file
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(f);
fclose(f);
return len;
}
Edit 1: Thanks a lot people. For your quick response& efficient answers. As for the size*10 thing, it was a random idea, I came up with, to deal with one of the Segmentation Fault errors. Never thought the size+1 option. I've learned a lot from you all. Will come with a new question soon. Thanks again!
Your problem is that you use "text" as a string but failed to do it.
A "string" in C is a char array terminated by '\0'.
If you use any string related function, you have to unsure that you give string !
So after you allocated "text" (througth "temp"), "text" is not yet a string since it doesn't contain '\0'.
Since it's an "empty" string at the beginning, you have to initialize by doing
text[0] = '\0';
Now, why your file is printed twice ? Dunno, but I have to bet on an UB since your string wasn't properly initialized.
I really have no idea how to Google search on this specific topic, so I hope one of you guys can help me out here.
Basically I've got this code:
fp = fopen("ELSO.html", "w");
I also got a variable with a name:
char name[25] = {"JohnShepard"};
What I want is to call fopen so that the name would be JohnShepard.html (i.e the content of the variable). Is such thing even possible?
As an alternative to strcat, you can use snprintf:
char buffer[100];
char name[25] = "JohnShepard";
int i = snprintf(buffer, sizeof buffer, "%s.html", name);
// "i" should now contain the length of string in "buffer"
FILE *fp = fopen(buffer, "w");
// ... etc ...
This method is safer than strcat because it requires you to provide the size of the output buffer. If there isn't enough room, then you won't end up overrunning the buffer (which is dangerous). Also, it doesn't modify the original string, but whether that is important or not is up to you.
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.