Jump to content

Reading a file to memory

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
6 replies to this topic

#1
Gredorian

Gredorian

    Newbie

  • Members
  • Pip
  • 4 posts
Wow! I was looking for some help with my little C problem and found this great programming community. I think I'll be hanging out here once in a while :)

Well getting to the point... I'm trying to read the content of a file to memory. Each line goes into a string of characters. Problem is some of the data gets overwritten with pieces of other data also from the file (yeah it's a little confusing). Here's a piece of code, hopefully you'll see something I missed:


     FILE *file;

     char **buff;

     char ch;

     int lines,i;

     if(!(file=fopen("file.txt","rt")))

         return;

     lines=flines(filename); // flines just returns the number of lines in the file

     buff=(char**)malloc(sizeof(char*)*lines);    

     

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

         buff[i]=(char*)malloc(sizeof(char)+1);

         ch=fgetc(file);

         sprintf(buff[i],"%c%c",ch,'\0');

         while((ch=fgetc(file)) != '\n'){

             if(ch == EOF) break;

             buff[i]=(char*)realloc(buff[i],strlen(buff[i])+2);

             sprintf(buff[i],"%s%c",buff[i],ch);

         }

         if(ch == EOF) break;

     }


Any ideas? It seems to work ok but as I said some data comes out messy. I was wondering if it's a memory issue (all those reallocs...). Oh and just for the record I do take care of the garbage in the memory :-) I just didn't enter the entire code because it's quite big.

Thanks in advance. If I'm not supposed to ask for help in this area feel free to delete my topic and accept my apologies.

#2
Mukbul

Mukbul

    Newbie

  • Members
  • Pip
  • 3 posts
I'm trying to read the content of a file to memory. Each line goes into a string of characters. Problem is some of the data gets overwritten with pieces of other data also from the file (yeah it's a little confusing
Extensive vaporizer reviews
vaporizer review

#3
dcs

dcs

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 775 posts
In C it can be a little more gruesome than C++'s vector of strings. Is C++ not an option?

#4
Gredorian

Gredorian

    Newbie

  • Members
  • Pip
  • 4 posts
I wish. I like object orientation better but it's for school and I have to do it using C. Since I made my explanation pretty confusing would you people please just try to find something wrong with the code? Maybe do it yourselves to see how it goes (I hope I'm not crossing the line here :laugh:). I've caught some bugs in my program and I'm only here because this one seems invisible to me.

Thanks

#5
dcs

dcs

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 775 posts
One idiom you want to avoid is this:
[COLOR="Red"]ptr[/COLOR] = realloc([COLOR="Red"]ptr[/COLOR], newsize);
This will leak memory if realloc fails.

I might choose to take bigger chomps than a single byte:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **my_read(FILE *file, size_t *rows)
{
   char *result, **array = malloc(sizeof *array);
   if ( !array )
   {
      return 0;
   }
   *rows = 0;
   do {
      /* Try to slurp the lines of the file. */
      [COLOR="Blue"]size_t size = 32; /* Tailor value to suit your preference. */[/COLOR]
      array[*rows] = malloc(size);
      if ( array[*rows] )
      {
         char *start = array[*rows];
         while ( (result = [COLOR="Blue"]fgets(start, size, file)[/COLOR]) != NULL )
         {
            char *newline = strchr(start, '\n');
            if ( newline )
            {
               *newline = '\0';
               break; /* Got everything from this line. */
            }
            else /* There is still more data in the line. */
            {
               char *temp = realloc(array[*rows], size * 2);
               if ( temp )
               {
                  array[*rows] = temp;
                  start = array[*rows] + size - 1;
                  size *= 2;
               }
               else
               {
                  free(array[*rows]);
                  puts("error occurred");
                  return 0;
               }
            }
         } /* inner loop */
      }
      ++*rows;
   } while ( result );
   return array;
}

void my_write(char **array, size_t rows)
{
   size_t i;
   for ( i = 0; i < rows; ++i )
   {
      puts(array[i]);
   }
}

void my_cleanup(char **array, size_t rows)
{
   size_t i;
   for ( i = 0; i < rows; ++i )
   {
      free(array[i]);
   }
   free(array);
}

int main(void)
{
   static const char filename[] = "file.txt";
   FILE *file = fopen(filename, "r");
   if ( file )
   {
      size_t rows;
      char **array = my_read(file, &rows);
      if ( array )
      {
         my_write(array, rows);
         my_cleanup(array, rows);
      }
      fclose(file);
   }
   else
   {
      perror(filename);
   }
   return 0;
}
There are probably more efficient ways to realloc memory, but I didn't dig in too deep.

#6
Gredorian

Gredorian

    Newbie

  • Members
  • Pip
  • 4 posts
Sorry I couldn't reply sooner. I want to thank you dcs for your patience. I solved this issue kinda badly: made a copy of all that memory block and then destroyed the old one. Well it worked, that's what matters I guess.

One more thing... Is there a way I can "watch" the memory that my program allocates? I think all the issues I had until now with my program are related to memory and they are VERY difficult to spot.

#7
dcs

dcs

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 775 posts
Debugging printfs come to mind. It can be an art as much as a science, though.

I think *nix may have available the option of Electric Fence to help debug memory issues.