数据输入/输出的差异

时间:2013-04-02 14:24:51

标签: c fgets scanf

我试图编写一个读取.pdb文件的程序,该文件是生物学应用程序中使用的文件类型。这种类型的文件具有标准格式,数据之间具有不同的空白区域。该文件的格式为

ATOM      4  N   ALA     1       2.670   1.801   1.072  0.00  0.00
ATOM      5  CA  ALA     1       3.225   3.144   1.197  0.00  0.00
ATOM      6  C   ALA     1       4.408   3.341   0.256  0.00  0.00
ATOM      7  O   ALA     1       4.553   4.394  -0.363  0.00  0.00
....      .  ..  ...     .       .....   .....   .....  ..... ....

所以我的程序(可能编写得很糟糕)定义了一个结构,读入数据(我从另一篇文章中偷走了http://www.daniweb.com/software-development/c/threads/65455/reading-a-file-using-fscanf#),并将其存储到索引结构中。现在,如果我在内部if循环中打印值,它会吐出正确的数据。但是,当我在外部while循环外打印出相同的值时,它给了我错误的atom []。name(恰好是HA,输入文件中第3列数据的最后一个值。所有其他值是正确的。

这是我的程序

#include <stdio.h>

typedef struct 
{
   char *atm;
   int serial;
   char *name;
   char *resName;
   int resSeq;
   double x;
   double y;
   double z;
   double occupancy;
   double tempFactor;
} pdb;

int main(int argc, char** argv)
{
   int i, j;
   pdb atom[28]; 
   char atm[5]; 
   char name[3]; 
   char resName[4];
   int serial; 
   int resSeq;
   double x;
   double y;
   double z;
   double occupancy;
   double tempFactor;
   char buff[BUFSIZ];
   FILE *file = fopen("test.pdb", "r");

   i = 0;
   while (fgets(buff, sizeof buff, file) != NULL) 
   {
      if (sscanf(buff, "%s %d %s %s %d %lf %lf %lf %lf %lf", 
         atm, &serial, name, resName, &resSeq, &x, &y, &z, 
         &occupancy, &tempFactor) == 10)
      {
         atom[i].atm = atm;
         atom[i].serial = serial;
         atom[i].name = name;
         atom[i].resName = resName;
         atom[i].resSeq = resSeq;
         atom[i].x = x;
         atom[i].y = y;
         atom[i].z = z;
         atom[i].occupancy = occupancy;
         atom[i].tempFactor = tempFactor;
         i++;
         /*printf("%s ", atom[i].atm);
         printf("%d ", atom[i].serial);
         printf("%s ", atom[i].name);
         printf("%s ", atom[i].resName);
         printf("%d ", atom[i].resSeq);
         printf("%lf ", atom[i].x);
         printf("%lf ", atom[i].y);
         printf("%lf ", atom[i].z);
         printf("%lf ", atom[i].occupancy);
         printf("%lf\n", atom[i].tempFactor);*/
      }
   }
   fclose(file);
   for (j = 0; j < i; j++)
      printf("%d of %d: %s\n", j, i-1, atom[j].name);

   return(0);
}

知道为什么会这样吗?此外,对程序格式/结构的任何帮助也将受到赞赏。我更像是一个Fortran人,所以C结构超出了我的专业领域。

提前致谢。

编辑: jsn帮助我,兰迪霍华德改进了它。这是更新和工作的程序:

#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
   char *atm;
   int serial;
   char *name;
   char *resName;
   int resSeq;
   double x;
   double y;
   double z;
   double occupancy;
   double tempFactor;
} pdb;

int main(int argc, char** argv)
{
   int i, j;
   pdb atom[28]; 
   int serial; 
   int resSeq;
   double x;
   double y;
   double z;
   double occupancy;
   double tempFactor;
   char buff[BUFSIZ];
   FILE *file = fopen("test.pdb", "r");

   i = 0;
   while (fgets(buff, sizeof buff, file) != NULL) 
   {
      char *atm = malloc(sizeof(char) * 5); 
      char *name = malloc(sizeof(char) * 3); 
      char *resName = malloc(sizeof(char) * 4); 

      if (sscanf(buff, "%s %d %s %s %d %lf %lf %lf %lf %lf", 
         atm, &serial, name, resName, &resSeq, &x, &y, &z, 
         &occupancy, &tempFactor) == 10)
      {
         atom[i].atm = atm;
         atom[i].serial = serial;
         atom[i].name = name;
         atom[i].resName = resName;
         atom[i].resSeq = resSeq;
         atom[i].x = x;
         atom[i].y = y;
         atom[i].z = z;
         atom[i].occupancy = occupancy;
         atom[i].tempFactor = tempFactor;
         i++;
      }
   }
   fclose(file);
   for (j = 0; j < i; j++)
   {
         printf("%s ", atom[j].atm);
         printf("%d ", atom[j].serial);
         printf("%s ", atom[j].name);
         printf("%s ", atom[j].resName);
         printf("%d ", atom[j].resSeq);
         printf("%lf ", atom[j].x);
         printf("%lf ", atom[j].y);
         printf("%lf ", atom[j].z);
         printf("%lf ", atom[j].occupancy);
         printf("%lf\n", atom[j].tempFactor);
   }

   return(0);
}

1 个答案:

答案 0 :(得分:2)

在while循环中,您需要为每个名称分配每个char *的新内存。你现在正在覆盖他们。

while (fgets(buff, sizeof buff, file) != NULL) 
{

    char *atm = malloc(sizeof(char) * 5); 
    char *name = malloc(sizeof(char) * 3); 
    char *resName = malloc(sizeof(char) * 4); 

    if (sscanf(buff, "%s %d %s %s %d %lf %lf %lf %lf %lf", 
             atm, &serial, name, resName, &resSeq, &x, &y, &z, 
             &occupancy, &tempFactor) == 10)

您正在复制char数组(指针),因此所有名称应该相同(最后一个条目)。