I'm trying to write a program that reads in a .pdb file, which is a file type used in biology applications. This type of file has a standard format with varying white space between data. The file is of the form
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
.... . .. ... . ..... ..... ..... ..... ....
So my program (probably poorly written) defines a structure, reads in the data (which I stole from another post here http://www.daniweb.com/software-development/c/threads/65455/reading-a-file-using-fscanf#), and stores it into an indexed struct. Now if I print the values inside of the inner if-loop, it spits out the correct data. However, when I print out the same values outside the outer while-loop, it gives me the wrong atom[].name (which just so happens to be HA, the last value in the 3rd column of data in the input file. All other values are correct.
Here is my program
#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);
}
Any idea why this might be happening? In addition, any help on the program format/structure would also be appreciated. I'm more of a Fortran guy, so C structures are out of my realm of expertise.
Thanks in advance.
EDIT: jsn helped me out and Randy Howard refined it. Here is the updated and working program:
#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);
}
Inside the while loop you need to allocate new memory for each char* for each name. You are overwriting them right now.
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)
You are copying the char array (pointers), so all the names should be the same (the last entry).