简体   繁体   中英

fscanf usage in c - Values not saving properly

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

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

  • Allocate memory to each words[i] and use strcpy()
  • Use strdup() and assign that to words[i] .

In either of cases, you have to free() the allocated memories before exit.

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 "".

eg 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.

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 (ie %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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM