unknown dimension vector with dynamic memory (in c)
The program consists in that I have a file that contains a vector of integers,but I do not know how many components it has, using dynamic sizing malloc,realloc,free, etc I have to get the number of components that it has and create a vector that contains them. without wasting memory.
The problem is in the while, I tried it with a file of 5 integers {1,2,3,4,5} to see how it worked. in said cycle the counter it counts 6 components instead of 5 and then I get vectors with 6 components when it's actually 5. I try to use the fseek to control the file variable but I don't find the error and they didn't change the results. I would like to know how to make it count the components well and not drag that component others.
#include <stdio.h>
#include <stdlib.h>
#define in 1
main()
{
int i,j=1,c,pos,*v,*p;
FILE*arch;
arch=fopen("vector.dat","r");
if(arch==NULL)
{
perror("El archivo no se pudo abrir\n");
return -1;
}
v=(int*)malloc(sizeof(int));
c=fread(v,sizeof(int),in,arch);
if(c!=in) //con esto contemplo la salvedad que el archivo este 'vacio'
{
v=NULL;
}
else
{
while((c==in)&&(0==fseek(arch,sizeof(int),SEEK_CUR)))
{
fseek(arch,-sizeof(int),SEEK_CUR);
j++;
v=(int*)realloc((void*)v,j*sizeof(int));
c=fread(v+j-1,sizeof(int),in,arch);
printf("*%d\n",j);
}
}
pos=j-1; //encuentro cuantas posiciones efectivas va a tener mi vector
p=(int*)realloc((void*)v,pos*sizeof(int));
p=v;
//imprimo los valores para ver como salieron
for(i=0;i<pos+1;i++)
{
printf("%d\n",*(p+i));
}
return 0;
}
1 answers
It doesn't make much sense to try to read data from a file if you are not clear in what format it is recorded.
In the absence of that knowledge (I repeat: indispensable) I will assume that the file contains n
integers recorded in binary format, each occupying the size of a int
on the same platform. [*]
In such a case, it is not necessary to read the entire file to get n
, it is enough to first ask for the size of the file (it can be done with stat
or, since we need to open the file, with fseek
+ftell
. Nor does it take a while to read, We can do a single fread
.
For example:
int readFile(const char * file) {
int ret, n, i;
int * v;
FILE * arch = fopen(file, "rb");
if (arch == NULL) {
perror("El archivo no se pudo abrir\n");
return -1;
}
ret = fseek(arch, 0, SEEK_END); // nos posicionamos al final del archivo
if (ret != 0) {
perror("Error en Fseek end\n");
fclose(arch);
return -2;
}
// ftell nos da la posicion final, es decir cantidad de bytes del archivo
n = (int)(ftell(arch) / sizeof(int)); // n= cantidad de elementos
ret = fseek(arch, 0, SEEK_SET); // volvemos al comienzo del archivo
if (ret != 0) {
perror("Error en Fseek set\n");
fclose(arch);
return -3;
}
if (n == 0) {
puts("archivo no contiene elementos");
} else {
v = (int * ) malloc(sizeof(int) * n); // alocamos buffer
ret = (int) fread(v, sizeof(int), n, arch); // leemos n enteros
if (ret != n) {
puts("error en lectura");
} else {
printf("leidos %d enteros\n", n);
}
}
fclose(arch);
return 0;
}
[*] note that in general this is not a good strategy, because the size of an int can vary between platforms - the file then would not be portable.