Strange error in binary files and RLE

Pages: 12
Sep 13, 2010 at 10:22pm
Hello!

I'm implementing the RLE algorithm applyed to a matrix. I'd like to write the encoded data inm a binary file and then read that file (just to verify the encoding and writing).
But I have a strange result. In debugging mode I found that it writes correctly the vector but when I scan the file it is read once more than needed...
here is the code:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <stdio.h>
#include <stdlib.h>

void RLE_enc(int **matrix, int nr, int nc, int *&vet, int *n_vet)
{

	int j, i, count, elem;
	bool exit;

	j=i=count=0;
	*n_vet = 0;
	exit = false;
	vet = new int[1];
	elem=matrix[i][j];
	
	while (!exit)
	{
		if (matrix[i][j]==elem)
		{
			count++;
			j++;
			if (j==nc)
			{
				i++;
				if (i==nr)
				{
					exit = true;
					vet = (int*) realloc(vet, sizeof(int) * ((*n_vet)+2));
					vet[(*n_vet)]=count;
					vet[(*n_vet)+1]=elem;
					(*n_vet)+=2;
				}
				else
					j=0;
			}
		}
		else
		{
			vet = (int*) realloc(vet, sizeof(int) * ((*n_vet)+2));
			vet[(*n_vet)]=count;
			vet[(*n_vet)+1]=elem;
			elem=matrix[i][j];
			(*n_vet)+=2;
			count=0;
		}
	}

  

}


int main()
{
	int **matrix;
	FILE *fp;
	int nr = 2, nc = 3, i, j;

	matrix = new int* [nr];
	for (i = 0; i<nr; i++)
		matrix[i] = new int[nc];

	for (i = 0; i<nr; i++)
		for (j= 0; j<nc; j++)
			matrix[i][j] = i*nc + j;

	int n_vet, *vet;
	RLE_enc(matrix, nr, nc, vet, &n_vet);

	fp = fopen("prova.bin", "wb");

	for (i = 0; i<n_vet; i++)
		fwrite(&vet[i], sizeof(int), 1, fp);

	fclose(fp);

	fp = fopen("prova.bin", "rb");

	i = 0;
	while (!feof(fp))
	{
		fread(&vet[i], sizeof(int), 1, fp);
		printf("%d", vet[i]);
		i++;
	}

	fclose(fp);



	return 0;


}


the output vector should be:
1 0 1 1 1 2 1 3 1 4 1 5
but the program shows a number in addition which I didn't write...what I'm wrong??

thanks
Last edited on Sep 13, 2010 at 10:35pm
Sep 13, 2010 at 10:34pm
I noticed that in text files I don't have the error:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
fp = fopen("prova.bin", "w");

for (i = 0; i<n_vet; i++)
	fprintf(fp, "%d ", vet[i]);
fclose(fp);

fp = fopen("prova.bin", "r");

int aux;
while (fscanf(fp, "%d ", &aux) != EOF)
{
	printf("%d", aux);
}

fclose(fp);


and in the file & on the screen I can read
1 0 1 1 1 2 1 3 1 4 1 5

it goes stranger and stranger...
Last edited on Sep 13, 2010 at 10:35pm
Sep 14, 2010 at 8:12am
From what I'm able to gather and understand, you've got an array of 12 numbers which would be 0 to 11 but your while(!feof(fp)) is reading 0 to 12.

Though I'm very much a beginner and had to spend a good while looking through this code with a debugger to understand its operation enough to get an idea, it seems to me that you're reading off the end of the array.

I could be wrong, but it's a thought at least while you wait for other responses.
Sep 14, 2010 at 8:18am
thanks for the reply.
The "strange" is that while writing the file it writes the 12 numbers of the array. butwhen it reads the file if goes one integer over the EOF and returns a number I haven't written!
Sep 14, 2010 at 8:31am
I'm taking a crash course in some concepts here.. But your area here:
vet[(*n_vet)]=count;
vet[(*n_vet)+1]=elem;
(*n_vet)+=2;

Lets say *n_vet = 0;
The above code is essentially accomplishing:
vet[(0)] = count; // *n_vet == 0
vet[(0 + 1)] = elem; // *n_vet == 1
(0) += 2; // *n_vet == 2

When you get to your final run through this loop, placing 1 then 5 into the array, you have:
vet[(10)] = count; // *n_vet == 10
vet[(10 + 1)] = elem; // *n_vet == 11
(10) += 2; // *n_vet == 12

So you've got an array written from 0 to 11 but n_vet leaves with a value of 12, 1 larger than your array.

This is what I'm seeing, in any case.

Edit: cleaned things up a little.
Last edited on Sep 14, 2010 at 8:35am
Sep 14, 2010 at 8:41am
yes, n_vet, which is the number of items in the array, should be 12 in this case (from index 0 to index 11 of the array)
Sep 14, 2010 at 8:44am
Yes, but 'while (!feof(fp))' is reading from 0 to 12; 13 locations. If you force n_vet = 11; right after you call RLE_enc(), the output is correct.
Sep 14, 2010 at 8:51am
in the reading process Istore the read data into the array but it is indipendent from the previous computing. It is the same if I change the reading into:

1
2
3
4
5
6
while (!feof(fp))
{
	fread(&aux, sizeof(int), 1, fp);
	printf("%d", aux);
	i++;
}


if I change n_vet into 11 then the writing cicle:
1
2
for (i = 0; i<n_vet; i++)
	fwrite(&vet[i], sizeof(int), 1, fp);


will write only 11 items of the array into the file, not 12.
Sep 14, 2010 at 8:52am
simply, the strange is in the fact that I store 12 items but I read 13 items because EOF is somehow brought one item over the last item I write..
Sep 14, 2010 at 8:56am
If you write from 0 to 12 with an array that has 12 indices, you're going to go off the end of your array.

Here's a more visual example:
Array Index:--0--1--2--3--4--5--6--7--8--9-10-11-12
Stored value:[1][0][1][1][1][2][1][3][1][4][1][5]-??- // Your output
Last edited on Sep 14, 2010 at 9:05am
Sep 14, 2010 at 9:05am
sorry, but in this code (the file writing):
1
2
3
4
5
6
7
8
9
10
11
for (i = 0; i<n_vet; i++) // n_vet = 12
	fwrite(&vet[i], sizeof(int), 1, fp);
/*
 i = 0 (0<12 -> write the file)
 i = 1 (1<12 -> write the file)
 i = 2 (2<12 -> write the file)
 i = 3  (3<12 -> write the file)
...
 i = 10  (10<12 -> write the file)
 i = 11  (11<12 -> write the file)
 i = 12 (12<12 FALSE -> exit the cycle) */


the array index goes from 0 to 11. when i == 12 it exits the cycle! so it writes 12 numbers, index from 0 to 11
Sep 14, 2010 at 9:09am
Edit: Disregarded last entry.

The thing is, my debugger is showing that !feof is doing exactly what it should. It's running from 0 to 12.
Last edited on Sep 14, 2010 at 9:11am
Sep 14, 2010 at 9:12am
It should be true if the check was at the end of the cycle (like a do ... while() ) but in the "for" case the check is at the beginning so it first check the condition. if i = 1 it exits without writing nothing!
Sep 14, 2010 at 9:16am
with my compiler (VS 6.0) the reading:

1
2
3
4
5
6
while (!feof(fp))
{
	fread(&aux, sizeof(int), 1, fp);
	printf("%d", aux);
	i++;
}


is done from index i=0 to i = 13. This is the problem! in the writing I write 12 items but in the reading I find 12 items into the file! and I don't know why!
Sep 14, 2010 at 9:22am
The for loop seems to be writing &vet[12] as it leaves. Because I can see &vet[i] being left with an extra value as the loop breaks.
Sep 14, 2010 at 9:27am
I remember reading some articles elsewhere on the feof function behavoir. You may want to change to below and see how ?

1
2
3
4
5
while (fread(&aux, sizeof(int), 1, fp)>0)
{
	printf("%d", aux);
	i++;
}
Sep 14, 2010 at 9:28am
If you refer to debug watch, it's common. infact when it exit i=12 and the variable debug watch tries to show you the cet[12]value (which doesn't exist) so it reads over the array. but into the for cycle if doesn't write the vet[12] item..
Sep 14, 2010 at 9:33am
it works perfectly!...but for what stange, inhuman, nonsense reason the feof function behave in this way?? It's clearly a bug!
Last edited on Sep 14, 2010 at 9:33am
Sep 14, 2010 at 9:39am
Let me clarify, it was NOT my solution. I read an article elsewhere and that author like you was tearing his hairs out on such a simple problem that in the end, he conclude feof just wasn't worth all the endless nights and propose use fread return code instead.

I also wonder why this is so. Can you access the source code for feof to take a look at it's internal implementation ?
Sep 14, 2010 at 9:49am
Pages: 12