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



我有一个小的示例程序来说明下面的问题:我有一份简单的文本文件,其中有三个单词(每个单词在一行中),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("%sn", tmp);
    words[i] = tmp;
    i++;
    //printf("%s ", words[i]);
}              
printf("n");
printf("Words 0 = %sn", words[0]);
printf("Words 2 = %sn", words[1]);
printf("Words 3 = %sn", words[2]);
fclose(fp);
}

输出

pears
apples
zipper
Words 0 = zipper
Words 2 = zipper
Words 3 = zipper

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

如果要将tmp数组的内容获取到每个words[i]中,则需要使用

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

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

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

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

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

所以你读"梨",你打印"梨"和单词[0]="梨"

然后你读"苹果",你打印苹果和单词[1]="苹果"。还有单词[0]="苹果"现在!!

等等…

您需要做的是在读取文件之前,使用malloc为每个单词[i]分配内存,并使其等于"。

例如words[0] = ""

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

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

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

char* words[15];

它为您提供了一个由15个字符指针组成的数组(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 filen");
    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 = %sn", t, words[t]);
  }
  fclose(fp);
  return 0;
}

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

1) fopen之后,必须检查空

2) 对于%s的扫描,总是给出最大大小(即%44s),因此不会出现缓冲区溢出

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

4) 只打印在中读取的字符串数量

最后,我在main 的末尾添加了return 0

相关内容

  • 没有找到相关文章

最新更新