Reputation: 23
I have a small sample program to illustrate my issue below: I have a simple text file with three words (each in a new line) which fscanf reads, assigns to a temporary variable and then transfers to a string array. Yet, the values do not seem to transfer to the array. Also, when I remove the comment // from the second printf in the while loop I get a seg fault.
I'm fairly new to C, so only now learning the usage of these functions! Thanks in advance for assistance!
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char* words[15];
char tmp[45];
int i = 0;
FILE* fp = fopen("small", "r");
while (fscanf(fp, "%s", tmp) == 1)
{
printf("%s\n", tmp);
words[i] = tmp;
i++;
//printf("%s ", words[i]);
}
printf("\n");
printf("Words 0 = %s\n", words[0]);
printf("Words 2 = %s\n", words[1]);
printf("Words 3 = %s\n", words[2]);
fclose(fp);
}
Output
pears
apples
zipper
Words 0 = zipper
Words 2 = zipper
Words 3 = zipper
Upvotes: 2
Views: 995
Reputation: 44329
The first important problem with your code is this line
char* words[15];
It gives you an array of 15 char pointers (char*
). That is not the same as an array of 15 strings. There are no memory for storing the strings.
To get memory for storing the strings, you can do:
char words[15][45];
// ^ ^^
// no * memory for each of the 15 strings
Now you have memory for 15 strings. Each string can be up to 44 chars.
With this change you don't need the tmp
variable - just read directly into words
. Something like:
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char words[15][45];
int i = 0;
FILE* fp = fopen("small", "r");
if (!fp)
{
printf("no such file\n");
return 0;
}
while ((i < 15) && (fscanf(fp, "%44s", words[i]) == 1))
{ // ^^^^^^^^ is the same as &words[i][0]
i++;
}
printf("\n");
int t;
for (t = 0; t < i; ++t)
{
printf("Words %d = %s\n", t, words[t]);
}
fclose(fp);
return 0;
}
Some other important changes added:
1) After fopen
you must check for NULL
2) For scanf with %s always give a max size (i.e. %44s) so there can't be buffer overflow
3) Make sure to stop the while
when you have read 15 strings (to prevent buffer overflow)
4) Only print as many strings as you have read in
Finally I added return 0
to the end of main
Upvotes: 0
Reputation: 588
I had the same problem in the past.
The problem is that when you read from the file, the word is kept in the buffer, and then you store it to the variable temp.
The thing is that when you read the next word, the contents of the buffer change. And this affects the previous call too!
So you read "pears", you print "pears" and words[0] = "pears"
Then you read "apples", you print apples and words[1] = "apples". BUT ALSO words[0] = "apples" now!!
And so on...
What you need to do is before reading the file, to allocate memory with malloc for every words[i] and get it equal to "".
e.g. words[0] = ""
etc.
Then when you start reading the file, you should use the strcpy() function for temp and words[i]. This will solve your problem.
I tried to answer this as simply as i could because in the past that issue troubled me and confused me a lot.
Upvotes: 1
Reputation: 134356
In your code, words[i] = tmp;
is not the way to store each input to the words
array. That only stores the base address of the tmp
array into each words[i]
and later, while printing, it actually prints the latest content of the tmp
on every iteration.
If you want to get the contents of the tmp
array into each words[i]
, you need to either
words[i]
and use strcpy()
strdup()
and assign that to words[i]
.In either of cases, you have to free()
the allocated memories before exit.
Upvotes: 4