• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 283
  • Last Modified:

Read from a file

Hi,

I am reading my data structure from my c program instead I would like to read my datastructure from a file.

Here is my program

//------------------------------------------------------------------
#include <stdio.h>

int main()
{
  FILE *infile;
  FILE *outfile;
  struct
  {
    char value1[2];
    char emty1[14];
    char value4[4];
    char value7[4];
    char empty2[8];
    int  key;
    char empty3[14];
  } mytype;

  infile=fopen("Datafile","rb");
  outfile=fopen("Outfile","wb");
  while(!feof(infile))
  {
    fread(&mytype,sizeof(mytype),1,infile);
    if(!feof(infile))
    {
     if(mytype.key==30069)
     {
      fprintf(outfile,"1st value = \'%\'\n",mytype.value1);
      fprintf(outfile,"4th value = \'%\'\n",mytype.value4);
      fprintf(outfile,"7th value = \'%\'\n",mytype.value7);
     }
    }
  }
  fclose(outfile);
  fclose(infile);
  return(0);
}
//------------------------------------


This structure,
struct
  {
    char value1[2];
    char emty1[14];
    char value4[4];
    char value7[4];
    char empty2[8];
    int  key;
    char empty3[14];
  } mytype;

I would like to read from a file (e.g. structure.txt). How would I do that?

I will be really appreciate your help.

Thanks,
John.
 
0
John22
Asked:
John22
  • 2
1 Solution
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi John22,

You'd do it almost exactly like you're doing now.   The catch is that the text file must have the data in the exact format (spacing) as your structure expects.

To get a good sample, initialize the items of your structure with fixed data and write it to your output file.

 
#include <stdio.h>

/*  The struct definition is global, so move it outside of main()  */
/*  Also, using 'typedef struct' instead of just 'struct' can make usage a bit easier  */

  typedef struct
  {
    char value1[2];
    char emty1[14];
    char value4[4];
    char value7[4];
    char empty2[8];
    int  key;
    char empty3[14];
  } mytype;


int main()
{
  FILE    *infile;
  FILE    *outfile;
  mytype  mydata;    /* mytype structure */

  infile=fopen("Datafile","rb");
  outfile=fopen("Outfile","wb");
  while(!feof(infile))
  {
    fread(&mydata,sizeof(mytype),1,infile);
    if(!feof(infile))
    {
     if(mytype.key==30069)
     {
      fprintf(outfile,"1st value = \'%\'\n",mytype.value1);
      fprintf(outfile,"4th value = \'%\'\n",mytype.value4);
      fprintf(outfile,"7th value = \'%\'\n",mytype.value7);
     }
    }
  }
  fclose(outfile);
  fclose(infile);
  return(0);
}



Good Luck,
Kent
0
 
John22Author Commented:
Hi Kent,

Thanks for your reply.

May be, I wasn't clear in my description.

The below structure, I would like to read from a file (structure.txt) instead of my C program.

 typedef struct
  {
    char value1[2];
    char emty1[14];
    char value4[4];
    char value7[4];
    char empty2[8];
    int  key;
    char empty3[14];
  } mytype;

I am also reading another binary file (Datafile). It will be two files, one binary file (Datafile) and another structure file (structure.txt).

The purpose of this thing is : I am going to compile my c program and use executable. So, Whenever I use different Datafile binary file, I just need to modify structure.txt file. I don't have recompile my code.

Thanks.
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi John,

It's not so easy as that.  When you compile a program, the structure becomes an integral part of your program.  If you want to make a data structure that can change according to a parameter file, or as in your stated case a "structure" file, you need to do all of the heavy lifting yourself.  This means that your structure file will have to be kept in a format that your program can understand, and you'll have to do all of the data manipulation based on character positioning.  Your code won't be able to maintain the structure by using normal structure syntax.

I'll be glad to show you how it's done, but it really is a lot of work and makes for a lot more complicated code than just recompiling an existing program.

Kent
0
 
MercantilumCommented:
I propose you this syntax for your structure.txt file:
 1 char for type ((C)har, (I)nt, (D)ouble...)
 n chars for the "number of" times of type
 '\n'

----For your structure you would have in the file
C2
C14
C4
C4
C8
I1
C14
----

You create a function to read the structure, and set three (allocated) arrays, char types[], int lengths[], int isize[], and an int 'items' (number of items)
lengths for arrays is the number of elements, isize is the size in bytes of all elements
And you calculate the size of the structure int ssize at the same time.
items = ssize = 0;
...
while (fgets (buf, 10, file_struct))
{
   if (buf[0] == 'C' || buf[0] == 'I' || buf[0] == 'D')
   {
      types[items]  = *buf;
      lengths[items] = atoi(buf+1);
      isize[items]   = lengths[items] * (*buf=='C' ? sizeof(char):(*buf =='I' ? sizeof(int):sizeof(double)));
      ssize += isize[items];
      items++;
   }
}


Now you have your three vars set, you can deal with the actual data file (example)
for one struct  (BYTE is unsigned char)

    int h = open ("datafile", O_RDONLY); // open file you could use fopen
    BYTE *my_data = malloc(ssize);
    read (h, my_data, ssize);  // 1 struct is read (errors to be checked)


The almost last part is to access the items of the struct ... we can imagine a function returning the nth item in a buffer (preallocated), type and
indicate the number of times (array), one or more... We use here my_data previously filled with one struct from data file

BYTE *getitem (int num, char *type, int *elements)
{
    int i, offset;
    for (offset=i=0 ; i<num ; i++) offset += isize[i]; // calculate offset of requested item
    *type = types[num];
    *elements = lengths[num];
    return ((BYTE *)my_data + offset);
}


And finally an example to print all items... (from my_data)
...
   BYTE *one;
   char type;
   int nelem;
   int i,j;

   for (i=0 ; i<items ; i++)
   {
      one = getitem (i, &type, &nelem);
      for (j=0 ; j<nelem ; j++)   switch (type)
      {
      case 'C': printf ("%c", one + j*sizeof(char)) ; break;
      case 'I': printf ("%d", one + j*sizeof(int)) ; break;
      case 'D': printf ("%lf", one + j*sizeof(double)) ; break;
      default:
   }
   printf ("\n");

This can be optimized but it can be a good start.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now