Dynamic memory allocation practice

advertisements

im tring to do a book exercise in C maily dealing with dynamic memory allocation. The program wants me to do the following

-read a file and open a file from stdin, for example ./program < input.txt > output.txt
-store each line by dynamically creating an array of strings
 *assume and allocate enough space to store 5 lines of type char*
  when this turns out to insufficient double the amount of space to store more/*realloc?*/
 *when allocatingspace to store line,allocate only enough memory to store particular line
-print lines to screen in reverse order
-print number of lines to screen
-print total characters to screen
(we can assume each line can be stored in 1000 bytes)

im trying to plan out my method to do this and was hoping for some input. Im new to dynamic memory allocation so forgive me if i butcher but i have read up on it. The following will be my psuedocode method and question. Lets say we have file input with lines

hello world
store these lines
but only enough memory to store these particular lines
then print out these lines in reverse
make sure to keep track of the line count,and character count
this is a 6th line so double the space of the array to store 10 lines

my psuedocode dash means general instruction,* is a bit more detailed

-read file in from stdin
    begin index count for the string_array
    /*we can assume line will fit into 1000 bytes*/
      buffer[1000]
    /*allocate memory to store 5 adresses of strings*/
      char** string_array = malloc(5 * sizeof(char))
    /*begin reading file*/
      while(fgets(buffer,sizeof(buffer),stdin != NULL))
-store each line in buffer into the array
    /*allocate only enough space to store the particular line,not sure how to do this but..*/
      string_array[index] = malloc(strlen(buffer) * sizeof(char)) /*afraid buffer will be 1000 like intialized?*/
    /*add characters of line to character sum and add the line to linesum*/
      charactersum = charactersum + strlen(buffer)
      linesum = linesum + 1
    /*fill the array index with each line string*/
      strcpy(string_array[index],buffer
    increment index

one thing i have no clue on is how to realocate space for the string_array because eventually it will need more space then to store 5 adresses. im thinking..

string_array = realloc(string_array, 2*sizeof(string_array)

but how do i check if my array has no more room to store string addresses in order to realloc and where would i place it? Is this method feasible? im hoping im using malloc and realloc correctly with no match errors because i have trouble with those. The printings, i can do fine but im more concerned about meeting the dynamic allocation requirements correctly and building the array correctly


Regarding your statement:
The printings, i can do fine but im more concerned about meeting the dynamic allocation requirements correctly and building the array correctly

Here are some steps to create, modify and free memory for
char **string_array={0}; //will become an array of "strings"

Note: C does not really have a string type, but when a char array is terminated with a NULL character, (\0), it is commonly referred to as a C string.

1) Determine the number of strings, and maximum length for each one. For a simple illustration, use:

#define NUM_STRINGS 10
#define MAX_STR_LEN 10

2) create pointers for each of your strings (really just creating NUM_STRINGS char *'s)

string_array=malloc(NUM_STRINGS * sizeof(char *));//creates 10 char *

Now you have *string_array[0] through *string_array[9], each having
a place in memory but no memory space. (big difference)

3) Allocate memory space for each char *, thus creating char arrays

for(i=0;i<NUM_STRINGS;i++)
{
    string_array[i]=malloc(MAX_STR_LEN +1);//+1 for null terminator
                                           //note: this could have also been
                                           //...(MAX_STR_LEN * sizeof(char) +1)
                                           //but because sizeof(char) == 1, it is equivalent
}

4) for memory _re_allocation of string_array, again, you could use the #define:

for(i=0;i<NUM_STRINGS;i++)
{
    string_array[i] = realloc(string_array, 2*MAX_STR_LEN +1);
}

Note:
realloc could also be applied to increase the number of strings as well, here it is only
applied to change the the length of each existing string.

5) Finally, When finished using any variable created in this manner, memory for it is on the heap
rather than the stack, and must be free'd.

for(i=0;i<NUM_STRINGS;i++)
{
    free(string_array[i]);
}
free(string_array);

In Summary here is everything discussed above (except realloc) wrapped up in two
functions to create string arrays, then free them:

//Create string arrays
char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
    int i;
    a = calloc(sizeof(char*)*(numStrings), sizeof(char*));
    for(i=0;i<numStrings; i++)
    {
      a[i] = calloc(sizeof(char)*maxStrLen + 1, sizeof(char));
    }
    return a;
}
//free string arrays
void freeMemory(char ** a, int numStrings)
{
    int i;
    for(i=0;i<numStrings; i++)
        if(a[i]) free(a[i]);
    free(a);
}

Usage example:

int main(void)
{
    char **str=0;
    //create array pointers and space for desired number of strings:
    str = allocMemory(str, NUM_STRINGS, MAX_STR_LEN);//create space for NUM_STRINGS strings,
                                                     //each with space for MAX_STR_LEN + 1 characters
                                                     //(+1 for NULL);
    //use strings...

    //when done using:
    freeMemory(str, NUM_STRINGS);
    return 0;
}