Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

writing variable length structs #2 URGENT HELP NEEDED!!

Status
Not open for further replies.

vlakas1981

Programmer
Dec 11, 2002
40
GR
hello everyone..

Here is my very urgent problem:

i had a previous post a little time ago, and i got an answer which i thought would help but it didn't (by xwb).
Here's the problem:

i've got a table (l_table) of i elements, every single one being a struct of the following type:

struct coded_letter{
int size;
int *elem;
};

i is 256. i use l_table.size as the counter of the elements pointed at by the pointer *elem.
(I regard *elem as a table, so i use it as l_table.elem[j]).
I do some processes, populate this table, and then i want to save it to a file.
I used this (proposed by xwb) process:

for (i = 0; i < 256; i++){

fwrite (&l_table.size,sizeof(l_table.size),1,fps);
fwrite (l_table.elem,sizeof (*l_table.elem),l_table.size, fps);


}

and then read them using

for (i = 0; i < 256; i++){

fread (&l_table.size, sizeof(l_table.size), 1, fps);
l_table.elem = malloc ((l_table.size) * sizeof (*l_table.elem));
fread (l_table.elem, sizeof (*l_table.elem), l_table.size, fps);
}

(again by xwb).

the problem is that, although everything seems to be ok when writing the data, when i read them,
i get a l_table.size of 0 for every i except for i=1, for which i get l_table.size=4456544!!!
I also get nothing in l_table.elem for any i, not even for i=1.

Thanks very much for any helpful answer.
vlakas1981
 
A few things to try.

1. Have you tried writing only one structure?
2. Are you resetting the file pointer?
3. Does the data look good if you open the file?

Matt
 
hello zyrenthian, and thanks for your interest.

1. Thre is no meening to write only one structure, i HAVE to write the whole of it. it is part of a compression program, and the 256 structs are each representing a character. I did try it however, with no different results. i still get 0 for any i except 1.

2. Resetting the file pointer?? please explain more. i initialise it, close the file and reopen it, and reinitialise the pointer. The part of the file which it reads is ok (Checked it with ftell).

3. The data doesn't (and should't) look good, since i create bytes from different bitstrings (part of the compression algorithm).

hope this clarifies more
 
vlakas1981: i did not read your code.
my be on the weekend, but stop using STUPID var-names
of ONE chars. your 'i' is one.
suppose you have to change, in a xx-thousend lines src,
all occurance of 'i' to some else.... how will you do it ??
i know very well the editor, change 'i' to 'iii' ist not
the question, but
int i; /* to be changed */
case 'i': /* don't touch */
and so on, do you see the problem ?
-----------
when they don't ask you anymore, where they are come from, and they don't tell you anymore, where they go ... you'r getting older !
 
thanks jamisar for the hint, but the code is not really big and the problem really isn't that. if you have something to help me please do so, if not, please don't load this thread. Other people might get bored reading and end up not helping me.
 
The thing is, the code looks good. The only thing that I can think of is that sizeof is not returning what is expected. Does not make sense though. maybe replace it with sizeof(int)??? The resetting of the pointer will be handled fine if you reopen the file so that is not the issue. I understand that the data should not &quot;look&quot; readable but you should be able to open the file in a hex editor and look at the first 4 hex values to determine if, infact, you are writing the correct value. Then with a bit of math, you can find the next offset and look if the lenght value there is correct as well. The reason I suggested only one to be written out is so you could open the file in hex and verify that infact your lenght value is being written properly. Also keep in mind that your hex value may need to be byte swapped when you open the file in hex. This means (abcd are bytes)

abcd

may need to be represented as

dcba

If you are on a litte endian machine.

[sunshine] THAT JUST MAY BE THE PROBLEM!!! I dont know the exact way that fwrite works but I am willing to bet that it writes a single byte at a time. If that is the case and you ARE on a little endian machine, you MAY need to byteswap the data you read in. I say &quot;MAY&quot; because, in theory, writing and reading back from the same system should not cause any problems.

For verification purposes dont bother with reading in the whole file at the current time. Just verify that you can, infact, read in the first amount of bytes and it IS the value you expect.

Here is a routine to byteswap the data you read in.

I have verified that this code works and have used it numerous times. You pass in a pointer to the value you want swapped and its size (via sizeof). This is a long shot but what do you got to lose?

Good luck and I will see if I can come up with anything else.

Matt


Code:
void byteswap(void* ptr,size_t size)
{
	char* bsptr = (char*)ptr;

	for(int i = 0,j=size-1;i<j;i++,j--)
	{
		bsptr[i]^=bsptr[j]^=bsptr[i]^=bsptr[j];
	}
}


 
thanks zyrethian for the time you already have spent, but i tried what you proposed with no better (if not worst) results! I have used fread and fwrite some times and i don't think there should be any inversion done. i will however try to check the file with a hex viewer.
if you 'd like me to send you the whole code (449 lines of not-so-perfectly-coded huffman compression algorithm) please give me your email.
thank you very much again for your time.
 
Hi vlakas1981,

This is a very fundamental problem you are stuck in to. You are having a pointer in your structure, and I guess you know what a pointer contains? Its just an address. There is no information other than the starting address of the memory block a pointer points, like its size. So when you are writing the structure to a file, it writes the value of variable &quot;size&quot; and the address contained within the pointer &quot;elem&quot; NOT the contents of the array pointed by &quot;elem&quot;.

Solution 1: write the contents of the array pointed by elem one by one to the file and read them similarly taking the size from the file first (that you wrote before the contents).

Solution 2: convert the array of ints to a string! yes, it sounds bizar but is easier to handle (read/write) and then put it in the file.

There could be better solutions, but this is all I could think of at the moment. I hope it helps!

Chow!
Roy.
 
roy, thanks for your answer..

i have already thought this way and this was the first thing i tried to do with the elems. but it didn't work either. i know i am not supposed to write the pointer to the file, but i was hoping for fwrite to understand me!!! i did try writing each element out to the file but to no success.
 
It is possible the sizeof isn't returning what you want. Try this
Code:
for (i = 0; i < 256; i++){

    fwrite (&l_table[i].size,sizeof(int),1,fps);
    fwrite (l_table[i].elem,sizeof (int),l_table[i].size, fps);
    

}

and then read them using

    for (i = 0; i < 256; i++){
            
        fread (&l_table[i].size, sizeof(int), 1, fps);
        l_table[i].elem = malloc ((l_table[i].size) * sizeof (int));
        fread (l_table[i].elem, sizeof (int), l_table[i].size, fps);
    }
If you are on Unix and that still doesn't work, od -x the output file. Check the hex dump and see if it is what you are expecting. If you are not on Unix, try the following: it just prints the first 1024 bytes of the file: you should be able to figure out what happened from there
Code:
#include <stdio.h>
#define BUFFMAX 1024
main (int argc, char* argv[])
{
    FILE* dump;
    char  buff[BUFFMAX];
    int block, offs, bytes;
    if (argc < 2) return 1;
    dump = fopen (argv[1], &quot;rb&quot;);
    memset (buff, 0, sizeof (buff));
    bytes = fread (buff, 1, sizeof(buff), dump);
    fclose (dump);
    for (block = 0; block < bytes; block += 16)
    {
        for (offs = 0; offs < 16; offs++)
        {
            printf (&quot;%02x &quot;, buff[block + offs]);
        }
        printf (&quot;\n&quot;);
    }
    return 0;
}
Just a thought: are you opening the file for writing with &quot;wb&quot; and for reading with &quot;rb&quot;? If the b is missing, it takes it as ASCII: not binary.
 
thanks everyone for your help, but being unable to understand the problem, so as to overcome it, i switched to fprintf and fscanf. this had as a result bigger file (which i wanted to avoid using fwrite) but at least it is working. Happy holidays everyone!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top