简体   繁体   中英

How do i read from a text file and allocate memory space using malloc for a 2d string array for each word in the text file

i am new to coding and am having a problem with the following.

I am required to read from a text file, each row will contain: command arg1 arg2 arg3... command arg1 arg2 command command arg1 arg2 ... arg9 etc

What i am trying to do is read this entire file into a 2D string array called array using malloc. This way if i were to do: array[0][0] i would access command arg1 arg2 arg3 array[1][0] i would access command arg1 arg2 and so on.

I also know there is a max of 100 rows and 256 characters per line. Below is how i attempted to declare my malloc however when trying to allocate strings to the 2d array, it only allocated single characters.

I dont quite understand how to do this, detailed explanation would be greatly appreciated

int row = 100;
int col = 256;
int **array;
array = (int**)malloc(row*sizeof(array));

   if(!array){
   perror("Error occured allocating memory");
   exit(-1);
   }

for(int i = 0; i<row;i++){
array[i] = (int*)malloc(col*sizeof(array));
}

You are allocating using sizeof(array) which is not the correct unit of allocation that you want.

It looks like what you want are two different kinds of memory allocations or objects.

The first is an array of pointers to character strings since the file data is a series of character strings.

The second kind of memory allocation is for the memory to hold the actual character string.

The first kind of memory allocation, to an array of pointers to character strings would be:

char **pArray = malloc (100 * sizeof(char *));  // allocate the array of character string pointers

The second kind of memory allocation, to a character string which is an array of characters would be:

char *pString = malloc ((256 + 1) * sizeof(char));  // allocate a character array for up to 256 characters

The 256 + 1 is needed in order to allocate space for 256 characters plus one more for the end of string character.

So to allocate the entire needed space, you would do the following:

int  iIndex;
int  nMax = 100;
char **pArray = malloc (nMax, sizeof(char *));  // allocate array of rows

for (iIndex = 0; iIndex < nMax; iIndex++) {
    pArray[iIndex] = malloc ((256 + 1) * sizeof (char));  // allocate a row
}

// now use the pArray to read in the lines of text from the file.
// for the first line, pArray[0], second pArray[1], etc.

Using realloc()

A question posed is using the realloc() function to adjust the size of the allocated memory.

For the second kind of memory, memory for the actual character string, the main thing is to use realloc() as normal to expand or shrink the amount of memory. However if memory is reduced, you need to consider if the text string was truncated and a new end of string terminator is provided to ensure the text string is properly terminated with and end of string indicator.

// modify size of a text string memory area for text string in pArray[i]
// memory area. use a temporary and test that realloc() worked before
// changing the pointer value in pArray[] element.
char *p = realloc (pArray[i], (nSize + 1) * sizeof (char));
if (p != NULL) {
    pArray[i] = p;     // valid realloc() so replace our pointer.
    pArray[i][nSize] = 0;   // ensure zero terminator for string
}

If you ensure that when the memory area for pArray] is set to NULL after allocating the array, you can just use the realloc() function as above without first using malloc() since if the pointer in the argument to realloc() is NULL then realloc() will just do a malloc() for the memory.

For the first kind of memory, you will need to consider freeing any memory whose pointers may be destroyed when the allocated array is shortened. This means that you will need to do a bit more management and keeping management data about the allocated memory area. If you can guarantee that you will only be increasing the size of the array and never shortening it then you don't need to do any management and you can just use the same approach as provided for the second kind of memory above.

However if the memory allocated for the first kind of memory will need to be smaller as well as larger, you need to have some idea as to the size of the memory area allocated. Probably the easiest would be to have a simple struct that would provide both a pointer to the array allocated as well as the max count of items the array can hold.

typedef struct {
    size_t   nCount;
    char   **pArray;
} ArrayObj;

Warning: the following code has not been tested or even compiled. Also note that this only works for if the memory allocation will be increased.

Then you would wrap the realloc() function within a management function. This version of the function only handles if realloc() is always to expand the array. If making it smaller you will need to handle that case in this function.

ArrayObj ArrayObjRealloc (ArrayObj obj, size_t nNewCount)
{
    // make the management a bit easier by just adding one to the count
    // to determine how much memory to allocate.
    char **pNew = realloc (obj.pArray, (nNewCount + 1) * sizeof (char *));

    if (pNew != NULL) {
        size_t   ix;

        // realloc() worked and provided a valid pointer to the new area.
        // update the management information we are going to return.
        // set the new space to NULL to have it in an initial and known state.
        // initializing the new space to NULL will allow for knowing which array
        // elements have a valid pointer and which don't.
        obj.pArray = pNew;
        for (ix = nNewCount; ix >= obj.nCount; ix--) {
            obj.pArray[ix] = NULL;
        }
        obj.nCount = nNewCount;
    }

    return obj;
}

and use this function something like

AnyObj obj = {0, NULL};

// allocate for the first time

obj = ArrayObjRealloc (obj, 100);

// do stuff with the array allocated
strcpy (obj.pArray[i], "some text");

// make the array larger
obj = ArrayObjRealloc (obj, 150);

If I got it right, you need to set up a two dimensional array of char * instead of int .

That is, you address the correct row by dereferencing once ( array[the_ith_row] ), and then address the correct element(command, arg1, arg2, ...) by another dereference ( array[the_ith_row][the_jth_col] ).

Notice : strings like "arg1" and "command" are treated as "array of chars" therefore you need to store a char * in order to access them. int could only store one char (with some extra space consumption), therefore won't work here.

So, the correct one should look like:

#include <string.h>

int row = 100;
int col = 256;
char ***array;
array = (char ***)malloc(row * sizeof(char **));
if (!array) {
   perror("Error occured allocating memory");
   exit(-1);
}

for (int i = 0; i < row; i++) {
   array[i] = (char **)malloc(col * sizeof(char *));
}

// Do some example assignments
for (int j = 0; j < col; j++) {
   array[i][j] = strcpy((char *)malloc(100), "test_string");
}

//therefore printf("%s", array[0][0]); will print test_string"

UPDATE: I missed some * here..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM