Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Processing Data File

I am trying to process a file in c++ with an unknown file structure that was written by a GWBASIC program. I've not programmed in c++ so am stuck.

It seems there are two structs that alternate. Structure #1 repeats itself 64 times, then structure #2 repeats itself 40 times, structure #1 repeats itself 32 times, then structure #2 repeats itself 20 times. Do I need to repeat an fread statement "x" number of times? For example:

loop 64 times: (fread(&p1, sizeof(struct preRec1), 1, f))
OR put the "x" number in the fread statement:
(fread(&p1, sizeof(struct preRec1), 64, f))

Here is my code thus far and it is not producing the proper output:'

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

struct preRec1 {
char ID[5];
char X1[3];
};

struct preRec2 {
char ID[5];
char NOTES[59];
};

//Add extra termination character here

struct Rec1 {
char ID[6];
char X1[4];
};

struct Rec2 {
char ID[6];
char NOTES[60];
};

struct Hdr {
char X1 [256];
};

void main(void)
{
FILE *f, *f2;

struct preRec1 p1;
struct preRec2 p2;
struct Rec1 r1;
struct Rec2 r2;

struct Hdr h;

f=fopen("extrachg", "rb");
f2 = fopen("extrachg_out", "wb");

memset ((&h), 0x0, sizeof(h));
memset ((&r1), 0x0, sizeof(r1));
memset ((&r2), 0x0, sizeof(r2));

fread(&h, sizeof(struct Hdr), 1, f);
memcpy(&h.X1, &h.X1, sizeof(h.X1));

while (fread(&p1, sizeof(struct preRec1), 1, f))
{
memcpy(&r1.ID, &p1.ID, sizeof(p1.ID));
memcpy(&r1.X1, &p1.X1, sizeof(p1.X1));

fprintf(f2, "%s|", r1.ID);
fprintf(f2, "%s|", r1.X1);
}

while (fread(&p2, sizeof(struct preRec2), 1, f))
{
memcpy(&r2.ID, &p2.ID, sizeof(p2.ID));
memcpy(&r2.NOTES, &p2.NOTES, sizeof(p2.NOTES));

fprintf(f2, "%s|", r2.ID);
fprintf(f2, "%s|", r2.NOTES);
}

fclose(f);
printf("All Done\n");

}

Thanks,
cj
[2632 byte] By [cjspsx] at [2007-11-11 9:56:40]
# 1 Re: Processing Data File
you can read all at once, with sizeof(thingy), 64 as you had it. This is the more efficient way to read it as well, if the structs are fairly small.
jonnin at 2007-11-11 20:59:42 >
# 2 Re: Processing Data File
No, a sinlge fread() per struct will do. fread accepts the sieof the struct times the number of instances thereof, so you can read the first 64 structs in one shot, then the 32 structs in another fread() call etc.
If you want to be a wise guy, you can use a single fread call for the entire file: create a struct that contains the correct number of the other structs:
struct WholeFile
{
struct1 s1[64];
struct2 s2[40];
struct1 s1[32];
struct2 s2[20];
};
WholeFile wf={0};
Now, use a single fread call to read the entire file into wf.
Danny at 2007-11-11 21:00:42 >
# 3 Re: Processing Data File
Thanks. Do you mean something like this:

struct preRec1 {
char ID[5];
char X1[3];
};

struct preRec2 {
char ID[5];
char NOTES[59];
};

//Add extra termination character here

struct Rec1 {
char ID[6];
char X1[4];
};

struct Rec2 {
char ID[6];
char NOTES[60];
};

struct Hdr {
char X1 [256];
};

struct preW{
struct preRec1 p1[64];
struct preRec2 p2[40];
struct preRec1 p3[32];
struct preRec2 p4[20];
};

struct W {
struct Rec1 r1[64];
struct Rec2 r2[40];
struct Rec1 r3[32];
struct Rec2 r4[20];

};

void main(void)
{
FILE *f, *f2;

preW p1 = {0};
W r1 = {0};
struct Hdr h;

f=fopen("extrachg", "rb");
f2 = fopen("extrachg_out", "wb");

memset ((&h), 0x0, sizeof(h));
memset ((&r1), 0x0, sizeof(r1));

fread(&h, sizeof(struct Hdr), 1, f);
memcpy(&h.X1, &h.X1, sizeof(h.X1));

while (fread(&r1, sizeof(struct r1), 1, f))

The compiler does not like this. The last line in red errors out:
"Use of undefined type 'r1' "
cjspsx at 2007-11-11 21:01:47 >
# 4 Re: Processing Data File
Do the structs appear in repeated order, e.g., 64 of x, 40 of y...then once more 64, 32 etc? I'm asking this because you're using a loop.
As for sizeof(struct r1),
Your compiler is right: r1 is an instance of W, it's not a type. Use either sizeof(r1) or sizeof(struct W).
Danny at 2007-11-11 21:02:46 >
# 5 Re: Processing Data File
No, the structs do not occur more than once. However, when I roll them up into one struct, then I have trouble referencing the individual fields.

struct W {
Rec1 r1[64];
Rec2 r2[40];
Rec1 r3[32];
Rec2 r4[20];
};

void main(void)
{
FILE *f, *f2;

struct preW pW1 = {0};
struct W rW1 = {0};
struct Hdr h;

f=fopen("extrachg", "rb");
f2 = fopen("extrachg_out", "wb");

memset ((&h), 0x0, sizeof(h));
memset ((&rW1), 0x0, sizeof(rW1));

fread(&h, sizeof(struct Hdr), 1, f);
memcpy(&h.X1, &h.X1, sizeof(h.X1));
fread(&rW1, sizeof(struct W), 1, f);
{

memcpy(&rW1.r1.ID, &pW1.p1.ID, sizeof(pW1.p1.ID)); <--error C2228: left of '.ID' must have class/struct/union type
cjspsx at 2007-11-11 21:03:45 >
# 6 Re: Processing Data File
p1 is an array of 64 structs, so you can't treat it as a single struct. If you want to copy the entire 64 struct at once using memcpy, you need to calculate the offset of 64 structs, not one. Also, why do you need memcpy in the first place? You can simply assign each sub struct using ordinary assignment:
rW1.r1=pW1.p1;
As a rule, C and C++ allow you to assign structs of the same type using teh assignment operator. You therefore don't need memcpy here.
Danny at 2007-11-11 21:04:45 >
# 7 Re: Processing Data File
This needs to result in a delimited file and I do not know how to process multiple different-size structs. I would just break up the data into pieces and process it in pieces because that is what my c skills allow. The problem is that I have a larger file with seven stucts to process later so I need to learn how to do process these multiple structs.

I've tried removing the while clause with no success and I've tried for-loops with garbled data:

No While Clause:

struct preW{
preRec1 p1[64];
preRec2 p2[40];
preRec1 p3[32];
preRec2 p4[20];
};

struct W {
Rec1 r1[640];
Rec2 r2[2640];
Rec1 r3[320];
Rec2 r4[1320];
};

void main(void)
{
FILE *f, *f2;

struct preW pW1 = {0};
struct W rW1 = {0};
struct Hdr h;

f=fopen("EXTRACHG", "rb");
f2 = fopen("EXTRACHG_OUT", "wb");

memset ((&h), 0x0, sizeof(h));
memset ((&rW1), 0x0, sizeof(rW1));

fread(&h, sizeof(struct Hdr), 1, f);
memcpy(&h.X1, &h.X1, sizeof(h.X1));

fread(&rW1, sizeof(struct W), 1, f);
fprintf(f2, "%s|", rW1.r1->ID);
fprintf(f2, "%s|\n", rW1.r1->X1);
fprintf(f2, "%s|", rW1.r2->ID);
fprintf(f2, "%s|\n", rW1.r2->NOTES);
fprintf(f2, "%s|", rW1.r3->ID);
fprintf(f2, "%s|\n", rW1.r3->X1);
fprintf(f2, "%s|", rW1.r4->ID);
fprintf(f2, "%s|\n", rW1.r4->NOTES);

fclose(f);
printf("All Done\n");
}

For Loop:

void main(void)
{
FILE *f, *f2;

struct preRec1a pa;
struct Rec1a ra;


struct preRec2a pa2;
struct Rec2a ra2;

f=fopen("extrachg","rb");
f2=fopen("extrachg_OUT", "wb");


memset ((&ra), 0x0, sizeof(ra));

for (int a = 0; a <= 64; a = a+1)
{

(fread(&pa, sizeof(struct preRec1a), 1, f));

memcpy(&ra.ID, &pa.ID, sizeof(pa.ID));
memcpy(&ra.X1, &pa.X1, sizeof(pa.X1));

fprintf(f2, "%s|", ra.ID);
fprintf(f2, "%i|\n", ra.X1);

}

for (int b = 0; b <= 40; b = b + 1)
{
(fread(&pa2, sizeof(struct preRec2a), 1, f));

memcpy(&ra2.ID, &pa2.ID, sizeof(pa2.ID));
memcpy(&ra2.NOTES, &pa2.NOTES, sizeof(pa2.NOTES));

fprintf(f2, "%s|", ra2.ID);
fprintf(f2, "%s|\n", ra2.NOTES);

}

for (int c = 0; c <= 32; c = c+1)
{

(fread(&pa, sizeof(struct preRec1a), 1, f));

memcpy(&ra.ID, &pa.ID, sizeof(pa.ID));
memcpy(&ra.X1, &pa.X1, sizeof(pa.X1));

fprintf(f2, "%s|", ra.ID);
fprintf(f2, "%i|\n", ra.X1);

}

for (int d = 0; d <= 20; d = d + 1)
{
(fread(&pa2, sizeof(struct preRec2a), 1, f));

memcpy(&ra2.ID, &pa2.ID, sizeof(pa2.ID));
memcpy(&ra2.NOTES, &pa2.NOTES, sizeof(pa2.NOTES));

fprintf(f2, "%s|", ra2.ID);
fprintf(f2, "%s|\n", ra2.NOTES);

}
fclose(f);
printf("All Done\n");
}
cjspsx at 2007-11-11 21:05:54 >