delete struct member

i have 2 files, let say tes.bin and tes2.bin
both is binary files,
tes.bin have this struct :
1
2
3
4
5
6
7
struct tes
{
 int a;
 char b[64];
 int c;
 int d;
}

while tes2.bin have :
1
2
3
4
5
6
struct tes2
{
 int a;
 char b[64];
 int d;
}


using fread to read binary and take the value to struct tes:

1
2
3
4
5
6
7
8
FILE *filetes;
tes tmpSTR;
filetes=fopen(".\\tes.bin","rb");
if( filetes!=NULL)
{
	fread(&tmpSTR,sizeof(tes),1,filetes);
	fclose(filetes);
}

so my question is :
is it possible to delete struct member int c one?
or skip int c for tes2.bin in fread?
i know i can use 2 separate struct, but it's frustrating if you have more than 100 files for each struct with only different 1 or 2 struct member...
Last edited on
is it possible to delete struct member int c one?
or skip int c for tes2.bin in fread?
No.

i know i can use 2 separate struct, but it's frustrating if you have more than 100 files for each struct with only different 1 or 2 struct member...
What is the problem?
that is way too much, and if there's more efficient way that would help instead of making 100 struct, arent that would be better 1 struct for any others just by skipping int c
because the other member is exactly the same struct...
only different on int c...
You confuse declaration and definition. A struct is a declaration: It tells the compiler that something like this exists.

A definition is when you actually have a variable to work with. An array is such a definition. For instance:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tes type1_array[100]; // Note: Defines an array of type tes with 100 fields
int type1_size = 0;
tes2 type2_array[100]; // Note
int type2_size = 0;
...
if(is_type1)
{ // read the data for type1
  fread(&type1_array[type1_size],sizeof(type1_array[type1_size]),1,filetes);
  ++type1_size;
}
else // read the data for type2
{
  fread(&type2_array[type2_size],sizeof(type2_array[type2_size]),1,filetes);
  ++type2_size;
}
You confuse declaration and definition. A struct is a declaration:

This

1
2
3
4
5
6
7
struct tes
{
    int a;
    char b[64];
    int c;
    int d;
};


is a struct definition.

Or at least that what GCC thinks, going by

.../main.cpp:8:8: error: redefinition of 'struct Test'
.../main.cpp:4:8: error: previous definition of 'struct Test'


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

struct Test {
   int a;
};

struct Test {
   int a;
   int b;
};

int main() {
    Test t;

    return 0;
}


Andy
Last edited on
no, i understand define and declare,
i do, but what i want is something like changing struct on the run...
for example if files size is 643 byte...
it would have struct :
1
2
3
4
5
6
7
8
9
struct tes
{
int a;
int b
char c[64];
double d;
float e;
etc...
}

but if the files have size 639
it have :
1
2
3
4
5
6
7
8
struct tes
{
int a;
char c[64];
double d;
float e;
etc...
}


instead of creating each struct, i wonder if i can use the same struct with a condition such as :
1
2
3
4
5
6
7
8
9
struct tes
{
int a;
if(filesize==643)
{int b;}
char c[64];
double d;
float e;
}

or when declaring :
tes.type1 tes1; (load int b)
tes.type2 tes2; (skip int b)
but well, tes.type1 is also not possible because struct cant be used that way :3
but i'm looking a way "like" that, if it's possible o.O
Last edited on
if there's more efficient way that would help instead of making 100 struct,

I'm confused about the 100 files and 100 structs.

Are you saying you have 100 files which each use a slightly different struct? Or are you just talking about files which just use one of two different structs?

And does the bigger struct have all the members of the smaller one, as you example shows? And are the extra members in the middle of the struct or at the end?

Also, how big are the files? If they're bigger than a certain size I would not read the whole file with a single call to fread (or equivilent.)

Andy
Maybe you can consider changing the order of the elements? Put the most frequently changed elements at the bottom of struct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct tes
{
    int a;
    char b[64];
    int d;
    int c;
};

struct tes2
{
    int a;
    char b[64];
    int d;
};


Then tes2 is just a part of tes. You can use tes to hold everything, and cast it to tes2 when necessary.

1
2
tes dat;
tes2 *p = (tes2*)dat;


i wonder if i can use the same struct with a condition such as :

No

The data in the file is fixed, so you've got to use the right struct to read it. (Or extract the data member by member, which would be more painful.)

Andy
well, actually tes.bin is an older version of tes2.bin files
they have exactly have same struct, except tes2.bin have more data in it's struct...

what i really want to do is actually upgrade tes.bin to tes2.bin
so i was hoping something like :
reading data from tes.bin and tes2.bin and assign the value to the struct
(it can be done by fread)
then assign value from tes.bin to tes2.bin
and use fwrite to rewrite tes.bin using tes2.bin struct but with tes.bin values in it...
so let say :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct tes
{
int a;
char c[64];
double d;
} old;
struct tes2
{
int a;
int b;
char c[64];
double d;
}new;
for example tes.bin have value
a=1;
c={'t','e','s'};
d=3.5;

while tes2.bin have :
a=3;
b=2;
c={'t','e','s'};
d=5;

then assigned value from old to new :
so it become :
a=1;
b=2
c={'t','e','s'};
d=3.5;
and rewrite old tes.bin
and i was hoping to use only 1 struct


well, if it's not possible, i'm very sorry to bother you guys :D
if anyone have any knowledge about this, even it's just a little hope for me, i would appreciate it :)
Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <type_traits>
#include <fstream>

template< typename T > std::istream& read( std::istream& stm, T& t )
{
    static_assert( std::is_trivially_copyable<T>::value, "not trivially copyable" ) ;
    return stm.read( reinterpret_cast<char*>( std::addressof(t) ), sizeof(t) ) ;
}

template< typename T > std::ostream& write( std::ostream& stm, const T& t )
{
    static_assert( std::is_trivially_copyable<T>::value, "not trivially copyable" ) ;
    return stm.write( reinterpret_cast< const char* >( std::addressof(t) ), sizeof(t) ) ;
}

struct tes
{
    int a ;
    char b[64] ;
    int c ;
};

struct tes2 : tes
{
    int d ;
};

tes2& merge( const tes& t, tes2& t2 )
{
    static_cast<tes&>(t2) = t ; // copy t.a, t.b and t.c to t2
    // leave t2.d unchanged
    return t2 ;
}

int main()
{
    std::ifstream fin_tes( "tes.bin", std::ios::binary ) ;
    std::ifstream fin_tes2( "tes2.bin", std::ios::binary ) ;
    std::ofstream fout( "tes.modified.bin", std::ios::binary ) ;

    tes t ;
    tes2 t2 ;
    while( read( fin_tes, t ) && read( fin_tes2, t2 ) ) write( fout, merge( t, t2 ) ) ;
}
Computers are fast and life is short, don't try to over think this. Just write a function to copy a tes struct to a tes2 struct:

1
2
3
4
5
6
void tesTotes2(const tes &src, tes2 &dst)
{
    dst.a = src.a;
    memcpy(dst.b, src.b, sizeof(src.b));
    dst.d = src.d;
}


Now read a your tes, covert it to a tes2, and write the tes2. You should be able to convert all the files as fast as the disk can read/write them.
Topic archived. No new replies allowed.