当我尝试在C中读取文件时,为什么fscanf会随机更改字符串中的字符?

时间:2013-10-31 21:24:34

标签: c scanf realloc

我正在用C语言编写一个程序,我需要创建一个结构数组,将结构数组保存到文件中,然后打开该文件,读取该文件,并将该文件的内容复制到一个数组中结构(这个称为“朋友”的特殊结构包含三个字符串)。但是,如果数组拥有三个这样的朋友:

John Doe 234-1230 (string, string, string) <br>
Kool Kat 343-3413<br>
Suzie Q 234-1234<br>

一旦我将这个数组保存到一个文件中,我就可以使用下面的open函数打开它:

Joán Doe 234-2132<br>
Kool Kat 343-3413<br>
Suzie Q 234-1234<br>

John Doe 234-2132<br>
Kool Kat 343-3413<br>
Suz Q 234-1234<br>

其中一个字符串(几乎总是结构中的第一个字符串)几乎完全相同,其中一个或多个随机字符被切换出来。谁能告诉我导致这个错误的原因是什么?

void open(friend* book, int* size){
   FILE *pRead;
   char address[100];
   char answer = 'a';
   printf("\nWARNING: Any unsaved data in the current phonebook will be lost!");
   printf("\nType the file-name you would like to open(press '1' for the default location):");
   scanf("%s", &address);

   if(strcmp(address, "1") == 0){
      strcpy(address, "default.dat");
   }

   pRead = fopen(address, "r");
   if(pRead == NULL){
      printf("\nFile not opened\n");
   }else{
      int counter = 0;
      while(!feof(pRead)){
         fscanf(pRead, "%s%s%s", book[counter].pFName, book[counter].pLName, book[counter].pNumber);
         counter++;
         realloc(book, sizeof(friend) * counter);
      }
      *size = counter;
      fclose(pRead);
      printf("\n%s has been loaded into the program!", address);
   }
}

其他信息:当我继续在同一个文件上调用此函数时,它最终会生成正确的字符串,这让我相信我的保存功能是正确的。这与内存分配有关吗?

这是我的结构代码:

typedef struct Contact{ //creates a struct that holds three strings (first name, last name, phone number) (can be referred to as either Contact or friend
   char pFName[20]; //first name of friend
   char pLName[20]; //last name of contact
   char pNumber[12]; //phone number of contact
}friend;

2 个答案:

答案 0 :(得分:2)

我在这里看到一个明确的问题:

  while(!feof(pRead)){
     fscanf(pRead, "%s%s%s", book[counter].pFName, book[counter].pLName, book[counter].pNumber);
     counter++;
     realloc(book, sizeof(friend) * counter);
  }

你总是读到你不拥有的记忆,然后再问realloc。此外,您忽略realloc的返回值。即使您认为它永远不会为NULL,仍然允许重新定位您的数据。这样做会更安全:

  while(!feof(pRead)){
     book = realloc(book, sizeof(friend) * (counter+1));
     fscanf(pRead, "%s%s%s", book[counter].pFName, book[counter].pLName, book[counter].pNumber);
     counter++;
  }

现在,接受book可以改变,你需要将它作为双指针传递,或让你的函数返回它。

这里还有其他一些你应该避免的事情,例如feof测试,你没有检查fscanf的返回值,而你没有防范缓冲溢出。但是,看到你的输入和输出,我认为这些都不会直接影响到你。

答案 1 :(得分:0)

在读取文件名时,scanf函数出错。

scanf("%s", &address);

你应该删除&amp ;.

但是,这可能不是您问题的原因,因为它适用于大多数系统。基本上这里的问题是scanf("%s", &string)衰减到指向char的指针[256],而scanf期望char *类型。这是有效的,因为指针&string&string[0]的表示方式相同。但是,您的代码取决于标准C不保证的事物,它可能在不同的系统中具有不同的行为。