c中的fscanf用法 - 值未正确保存

时间:2016-07-21 07:04:19

标签: c arrays pointers scanf

我有一个小示例程序来说明我的问题:我有一个简单的文本文件,其中有三个单词(每个都在一个新行中),fscanf读取,分配给一个临时变量,然后转移到一个字符串数组。然而,这些值似乎没有转移到数组。 另外,当我从while循环中的第二个printf中删除注释时,我得到一个seg错误。

我对C很新,所以现在才学习这些功能的用法!在此先感谢您的帮助!

#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);
}

输出

pears
apples
zipper

Words 0 = zipper
Words 2 = zipper
Words 3 = zipper

3 个答案:

答案 0 :(得分:4)

在您的代码中,words[i] = tmp;不是存储每个words数组输入的方式。这只会将tmp数组的基地址存储到每个words[i]中,之后,在打印时,它实际上会在每次迭代时打印tmp的最新内容。

如果您想将tmp数组的内容放入每个words[i],您需要

  • 为每个words[i]分配内存并使用strcpy()
  • 使用strdup()并将其分配给words[i]

在任何一种情况下,您必须在退出前free()分配的记忆。

答案 1 :(得分:1)

过去我遇到过同样的问题。

问题在于,当您从文件中读取时,该单词将保留在缓冲区中,然后将其存储到变量temp。

问题在于,当您阅读下一个单词时,缓冲区的内容会发生变化。这也会影响之前的通话!

所以你读了&#34; pears&#34;,你打印&#34; pears&#34;和单词[0] =&#34;梨子&#34;

然后你读了&#34;苹果&#34;,你打印苹果和单词[1] =&#34;苹果&#34;。但是还有单词[0] =&#34;苹果&#34;现在!!

等等......

你需要做的是在阅读文件之前,为每个单词[i]分配内存和malloc,并使其等于&#34;&#34;。

e.g。 words[0] = ""等。

然后当你开始阅读文件时,你应该对temp和words [i]使用strcpy()函数。这将解决您的问题。

我试着尽可能简单地回答这个问题,因为过去这个问题困扰着我,让我很困惑。

答案 2 :(得分:0)

您的代码的第一个重要问题是此行

char* words[15];

它为您提供了15个char指针(char*)的数组。这是与15个字符串的数组相同。没有用于存储字符串的内存。

要获取用于存储字符串的内存,您可以执行以下操作:

char words[15][45];
//  ^          ^^
// no *        memory for each of the 15 strings

现在你有15个字符串的内存。每个字符串最多可以包含44个字符。

通过此更改,您不需要tmp变量 - 只需直接阅读words即可。类似的东西:

#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;
}

添加了一些其他重要更改:

1)fopen之后你必须检查NULL

2)对于带有%s的scanf,总是给出最大尺寸(即%44s),这样就不会有缓冲区溢出

3)确保在读取15个字符串时停止while(以防止缓冲区溢出)

4)只打印您在

中读取的字符串

最后,我将return 0添加到main

的末尾