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;
}
 3
Author: dwarandae, 2016-08-28

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.

 3
Author: leonbloy, 2016-08-28 21:21:58