Reading from file into array, line by line - c

I am trying to read from a file in C. My code is the following. It seems to read everything fine into the array, but when I try to print it, I get the error Segmentation fault (core dumped)
FILE *fp;
char * text[7][100];
int i=0;
fp = fopen("userList.txt", "r");
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while(fgets((*text)[i++],100,fp) != NULL) ;
printf("%s", &text[0]);
fclose(fp);
Can someone point me in the right direction?
I have tried reading and copying solutions from other similar cases, but they are extremely specific to the user.

So part one, you don't need a pointer to a char[][]:
char text[7][100];
Part 2, just deference your array of strings like a normal person, nothing fancy here:
while(fgets((text)[i++],100,fp) != NULL) ;
Live example: http://ideone.com/MADAAs
Some things to watch out for:
If your input file has more than 7 lines you are going to have problems.
Why is “while ( !feof (file) )” always wrong?

char * text[7][100]; //wrong - this is 2 diminutions array of char pointers, replace it with
char text[7][100];
while(fgets((*text)[i++],100,fp) != NULL) ; // replace this with
while(fgets(&text[i++][0],100,fp) != NULL) ;
NOTE: this code will work in the current scope of the function (on the stack) if you need to use it outside the scope of current scope , allocate some memory on the heap and use the pointers of the heap.

Related

Segmentation fault strcpy/strcat

I am writing a program to open a file (say "input_file"), manipulate its contents and then output it to another file ("manipulated-input_file")
I have done this with strcpy and strcat in the following way:
char t-filename[]="Manipulated-", filename[50], td-filename[50];
memset ( filename, '\0', FILE_NAME);
printf("Please enter the filename - \n");
scanf( "%30s", filename );
strcpy(td-filename,filename);
strcat(t-filename,td-filename);
printf("%s\n", t-filename);
Now printf functions prints the t-filename as "Manipulated-input_file"
After this part, I have a section where I open "input_file" and
do something.
fptr = fopen(filename, "r");
while ( fgets (line, sizeof line, fptr) != NULL)
{
...do something...
}
fclose(fptr);
Later I wanted to open a file with name 't-filename' at the end of the code:
tptr = fopen(t-filename, "w");
fprintf(tptr,"something");
fclose(tpr);
When I compile this code I am getting "Segmentation fault (core dumped)".
I do not know what went wrong. Can somebody help?
transfilename doesn't have enough space to hold additional items added there by strcat(transfilename,translatedfilename);. It's already full with "Translated-" since [] gives you the exact amount of characters in the initializing string, plus a null terminator.
You need to either change it to char transfilename [LARGE_ENOUGH] or use dynamic memory allocation to change the size in run-time.
strcat(t-filename,td-filename);
t-filename is not large enough to accommodate the result and it is an Undefined Behaviour.
same here
strcat(transfilename,translatedfilename);
transfilename is not large enough to accommodate the result and it is an Undefined Behaviour.

I got Segmentation Fault error when I make cat -b function

I want to make 'cat -b' function.
This result is perfect when meet last step.
I got Segmant Fault error and I don't know how to fix it.
How can I do?
FILE *file_name = NULL;
file_name = fopen(av[2], "r");
char temp[1024], *str;
int cnt_file_number = 1;
while(!feof(file_name)){
printf("%4.d ", cnt_file_number++);
str = fgets( temp, sizeof(temp), file_name);
if(strcmp(str, "\0") == 0 ) break;
printf("%s", str);
}
fclose(file_name);
fgets returns a null pointer if it encounters an error.
You are using str right away without checking it.
A better way would be something like
while(fgets(temp, sizeof(temp), file_name) {
// your printing code but using temp instead of str
}
Since fgets returns either temp or null you don't need that extra str pointer and if it is null due to EOF the loop will terminate properly.
Also, checking feof in your loop condition won't do the job because several characters are read at once and EOF might not be the next char but among the next few chars.
Edit: oh sorry. I misread. You are actually checking if str is empty but as others pointed out in the comments there is a better way to do this. Maybe this even solves the problem.
Aside from the fact that your program does not reflect the description of what "cat -b" would do, we do not know what av[2] is; so, no telling whether that file exists or is readable. It'd be wise to check fopen() to ensure that it opens a valid file. If it is not, then it returns NULL and feof(NULL) will fail.
Also, if you read past the end of file, str == NULL and strcmp(NULL,...) will fail.

Using Fgets in two ways

I looked through some "FGETS" questions before posting, and what i gathered is it may be a new line character thats causing the issue for the manual input.
int main ( int argc, char *argv[] ){
char temp[1000];
FILE *user_file;
printf("Starting....\n"); //Used for user visual.
if(argc == 2){ //open file
user_file = fopen(argv[1],"r");
if( user_file == NULL ){
printf("No file was found.");
exit(2);
}else{
fgets(temp,strlen(temp),user_file);
}
}else if( argc > 2 ){ // Will exit if arguments are greater than 2.
printf("Maximum args 2.\n");
exit(1);
}else{
printf("File was not provided, please enter the text to convert.\n"); //If the user doesnt provide a file allow manual input.
fgets(temp,strlen(temp),stdin);
}
printf("%s\n",temp);
return 0;
}//End main
Questions:
Why is fgets not opening the txt file I provide it with on the cmd line, and storing it to the temp array?
Why is Fgets being skipped over in the "else" statment if the file is not provided?
Why is print being skipped over in both instances?
Hey and by the way thank you very much for the assistance.
If you know a similar question that has been asked, can you post it in the comments so I can read it.
Your code has multiple problems.
Here's the first problem:
char temp[1000];
Your buffer declaration does not initialize the buffer's contents - so the value of each char value will be whatever was in the raw memory previously. In C most strings are "null-terminated" so having a terminating NULL (0 - zero) is important otherwise you can run into buffer-overruns.
The "best" approach is to zero-out (zero-initialize) the array/buffer before you use it, like so (in C99):
char temp[1000] = {0};
...this way temp will contain all 0 values (NULL) so anything written to it (provided it's no longer than 999 bytes) will automatically have a null-terminator (though fgets will append a terminating 0 value, but not every function in C does this).
The second problem is related to the first: you're using the runtime string-length function strlen to get the size of the strlen buffer. This is incorrect as the buffer sized is fixed at compile-time to 1000. The strlen will return the index of the first 0 (NULL) char value, which is undefined behavior at this point because you haven't zero-initialized the buffer anyway (so it could return 0 immediately if the buffer's original raw data contained a zero, or it could overrun 1000 because there was never any zero value.
...thus you need to re-use the buffer-length, like so:
#define TEMP_LENGTH 1000
char temp[ TEMP_LENGTH ];
...
fgets( temp, TEMP_LENGTH, user_file );
Finally, you're making the same mistake when you call fgets( temp, ..., stdin ).
The array temp[] is uninitialized, and you attempt to find strlen(temp). You don't even know if there is a NUL stored in the array. Try doing:
#define MAXLINE 1000
and changing your calls to fgets():
fgets(temp, MAXLINE, user_file);
...
fgets(temp, MAXLINE, stdin);
Here problem is in your code, instead of passed numerical value in second argument you passed strlen(temp).
fgets(temp,strlen(temp),user_file);
right way is :-
fgets(temp,1000,user_file);

Reading a file using fgets and printing its content on screen

I still consider myself as a new webby in C.I am trying to read a file in, file is not binary but its size varies from small size of feb kbs to big size files of feb Mbs.I am using fgets function, i had taken reference from this link but after compilation, i am getting segmentation fault.i tried to debug it with gdb and found that i am able to open file but unable to read.Here is my code.
#include<stdio.h>
#define MAX_LENGTH 1048576
int main()
{
FILE *fp;
char *result;
char line[MAX_LENGTH];
fp =fopen("/home/shailendra/sampleprograms/C/shail1.txt","r");
if(result=fgets(line,MAX_LENGTH,fp) != NULL)
printf("The string is %s \n",result);
else
printf("Error opening the file");
if(fclose(fp))
printf("fclose error");
}
This Segmentation fault really sucks your blood.I understand that it is due to insufficient memory allocation but i had used MAX_LENGTH 1048576, so i don't think that it must create any problem.I had tried it with both small files with only one line and a big file with multiple lines but i am unable to figure out why i am getting segmentation fault.
I also looked at this and this but got no help.
Try some parentheses:
if((result=fgets(line,MAX_LENGTH,fp)) != NULL)
^ ^
Without those you'll store the result of the comparison instead of a pointer to the string.
Side note: you don't need result at all. When it succeeds, fgets returns the pointer you passed in; in other words you can just printf line:
if(fgets(line, MAX_LENGTH, fp))
printf("The string is %s \n", line);
Second side note: before trying to fgets from the file, you should check whether fopen succeeded:
if (!fp)
perror("fopen");
Couple of things in addition to cnicutar's answer:
#include <stdio.h>
^ Please make sure you have a space between your includes and the headers
fgets will read until it's encountered a new line or EOF (whichever comes first), so to read the whole file you'd have to do it in a loop.
I would recommend doing it like this (no need for the pointer assignment as pointed out):
while(fgets(line, MAX_LENGTH, fp))
printf("%s", line);

Find and Replace in a C File

The Problem was to find and replace a string in a C File.
I am new to C Files. I have tried the following code but I didnt get any output:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *f1,*f2;
char *src,*dest,*s1,ch,ch1,ch2,ch3;
int i;
f1=fopen("input.txt","rw");
f2=fopen("dummy.txt","rw");
src="mor";
dest="even";
while(ch!=EOF)
{
ch=fgetc(f1);
if(ch==src[0]) //Finding 1st char of src
{
fgets(s1,strlen(src),f1);
if(strcmp(src+1,s1)==0) //Finding occurance of "src" in file
{
fseek(f1,strlen(src)-1,SEEK_CUR);
while(ch1!=EOF) //Copying remaining data into another file
{
ch1=fgetc(f1);
fputc(ch1,f2);
}
fseek(f1,-strlen(src),SEEK_CUR);
for(i=0;i<strlen(dest);i++) //replacing "src" with "dest"
{
ch2=dest[i];
fputc(ch2,f1);
}
fclose(f1);
f1=fopen("input.txt","a");
while(ch3!=EOF) //Appending previosly copied data into 1st file
{
ch3=fgetc(f2);
fputc(ch3,f1);
}
}
}
}
fclose(f1);
fclose(f2);
}
The Contents of input.txt is "morning".
Kindly point the ERROR in the logic and also give an efficient code for the same.
Thanks in Advance.
Reading files in C is usually a bit messy. The first problem that I see is the way ch is used in the main loop. The first time
while (ch != EOF)
is executed, ch is uninitialized, and if it happens to hold EOF, the main loop will not execute at all. I usually use the following structure for reading from files:
FILE *fInput = fopen("input.txt", "r");
int ch; /* need an int to hold EOF */
for (;;)
{
ch = fgetc(fInput);
if (ch == EOF) break;
...
}
In addition, you may need to read up on file pointer concept. For example, after reading the remainder of src, you fseek() forward, and skip some more characters before you copy data to f2. Essentially, you read m, read or (with fgets() - and into an unallocated buffer s1 that would go ka-boom on you some time in the near future), skip 2 more characters (now your pointer is at last n of "morning"), copy "ng" into f2, try to write EOF to f2 in this loop (hence the above pattern for reading until EOF), seek two characters back (which may fail once you reach EOF, my C file functions are a bit rusty these days), write "even" to f1 (which should, if I am wrong about seek after EOF, set input file to "mornieven", and not change it if I am correct). In summary, I don't think the code does what you intend it to do.
I would recommend building up your function. Each one of the following can be written as a program that you should test and finish before going to next step:
read the file safely, and print it out
detect the contents of src, and print the rest of input
save the rest of the input to second file instead of printing
replace src with dest in first file, and ignore the rest (since you open input file with 'rw', this will truncate the rest of input). You may need to do an fseek() to clear the EOF status. Also look at ftell() to record a position that you can jump back to using fseek()
finally, copy in everything you have saved to second file after replacing src with dest (no need to close f1 here. But it is better to open f2 as write, close after copy from first file, and reopen as read to perform the copy back to f1).
In addition, when you need a buffer (such as s1), just use a large enough array for now, but look into malloc() and free() functions to perform dynamic memory allocations for situations like these.
One simple way to do the replace would be to first read in the whole file into a buffer
e.g.
FILE* fpIn = fopen("file.txt","rb");
fseek(fpIn, 0L, SEEK_END);
size_t s = ftell(fpIn);
fseek(fpIn, 0L, SEEK_SET);
void* buf = malloc(s);
fread(buf,s,1,fpIn);
now while writing the file, check for your string
char src[] = "mor";
char dest[] = "even";
int lenSrc = strlen(src);
int lenDest = strlen(dest);
for (char* ch = buf; ch < buf + s; ++ch)
{
if ( !memcmp( ch, src, lenSrc ) )
{
fwrite( dest, 1,lenDest, fpOut );
ch += lenSrc;
}
else
{
fputc( *ch, fp );
}
}
disclaimer: haven't compiled this
You are printing the wrong thing in your output. Print, "ch", not the file pointer.
while(ch!=EOF)
{
ch=getc(f1);
printf("%c",ch);
}
while(ch!=EOF)
{
ch=getc(f2);
printf("%c",ch);
}
Also, f2 is closed at the end during your output. You'll have to reopen it (just like you do with f1.)
At first glance, I see that your code to call fgets is wrong. You have not allocated any memory and you are reading a string into an uninitialized pointer. Read into an array or dynamically allocated memory.
Another problem is that you are declaring ch as char. fgetc() returns an int, and for good reason. It is good to be able to return any possible character or EOF, so EOF shouldn't be a character, so ideally fgetc() returns a bigger type than char.
The upshot is that the loop may well never end, since ch can't possibly hold EOF on some standard implementation. Declare it (and ch1 and ch3) as int.

Resources