I've written the following program to read line by line from a file and store it in the words array. The output should be two random words from the array. But surprisingly the words array contains only the last word read repeatedly. Any help on what went wrong?
int main(){
int i = 0;
char line_buffer[BUFSIZ];
char* words[20];
FILE *fp = fopen("input.txt", "r");
while (fgets(line_buffer, sizeof(line_buffer), fp)) {
//printf("%s", line_buffer);
words[i] = line_buffer;
i = i + 1;
}
printf("%d", i);
int j = rand()%8;
int k = (j+1)%8;
printf("%s %s", words[j], words[k]);
fclose(fp);
return 0;
}
input.txt
nematode knowledge
empty bottle
nevertheless
claustrophobia
metamorphosis
acknowledgement
impossibility
never gave up
You read each line of data into the same buffer, so the last line overwrites all previous lines. You're going to have to allocate space for each line by some means or other - either dynamic memory allocation with malloc()
(or possibly strdup()
), or using a fixed size array (which limits the amount of data your program can handle safely). You'll also need to deal with newlines in the data read.
You get some credit for using fgets()
and not using gets()
; that is a 100% correct decision.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
enum { MAXLINES = 30 };
int main(void)
{
int i = 0;
char lines[MAXLINES][BUFSIZ];
FILE *fp = fopen("input.txt", "r");
if (fp == 0)
{
fprintf(stderr, "failed to open input.txt\n");
exit(1);
}
while (i < MAXLINES && fgets(lines[i], sizeof(lines[0]), fp))
{
lines[i][strlen(lines[i])-1] = '\0';
i = i + 1;
}
fclose(fp);
printf("%d\n", i);
srand(time(0));
int j = rand() % i;
int k = (j+1) % i;
printf("%s %s\n", lines[j], lines[k]);
return 0;
}
This checks that the file was opened successfully, closes the file as soon as the reading is complete, and ensures that it does not trigger a stack overflow by reading more lines than the array can hold. It wastes a lot of space by over-allocating space so each line could be very long (though the lines are typically quite short). If a line is longer than BUFSIZ, it will be read into a couple of adjacent entries in lines
. It does not assume that there are 8 lines in the data file. It zaps the newline at the end of each line (unless a line is split, in which case it zaps the last character before the split on the first of the two lines). It seeds the random number generator with the current time. It seems odd that you only ever want adjacent lines from the file.
int main(){
int i = 0;
int BUFSIZE = 1000;
char* words[20];
FILE *fp = fopen("input.txt", "r");
if (fp == 0){
fprintf(stderr, "Error while opening");
exit(1);
}
words[i] = malloc(BUFSIZE);
while (fgets(words[i], BUFSIZE, fp)) {
i++;
words[i] = malloc(BUFSIZE);
}
printf("Output: \n");
srand(time(NULL));
int j = rand()%i;
int k = (j+1)%i;
fflush(stdout);
printf("%d - %s %d -%s", j, words[j], k, words[k]);
int x;
for(x = 0; x<i; x++)
free(words[x]);
scanf("%d", x);
fclose(fp);
return 0;
}
ps. Check malloc result
You repeatedly overwrite the memory in line_buffer. The words array contains only pointers this variable.
You should either use a multi-dimensional array or allocate memory at runtime.
Btw: Bad things will happen when you pass more than 20 lines to your code ...
Did you initialize the random number generator with srand
? An explanation, with an example of how to use it is available here.