Как мне прочитать из текстового файла и выделить место в памяти, используя malloc для двухмерного массива строк для каждого слова в текстовом файле - PullRequest
0 голосов
/ 09 мая 2019

Я новичок в кодировании, и у меня возникли проблемы со следующим.

Мне необходимо прочитать из текстового файла, каждая строка будет содержать: команда arg1 arg2 arg3 ... команда arg1 команда arg2 команда командаarg1 arg2 ... arg9 и т. д.

То, что я пытаюсь сделать, это прочитать весь этот файл в массив двухмерных строк, называемый массивом, используя malloc.Таким образом, если бы я сделал: массив [0] [0] я бы получил доступ к команде arg1 arg2 массив arg3 [1] [0] я бы получил доступ к команде arg1 arg2 и т. Д.

Я также знаю, что естьмаксимум 100 строк и 256 символов в строке.Ниже показано, как я пытался объявить свой malloc, однако при попытке выделить строки для 2d-массива он выделил только отдельные символы.

Я не совсем понимаю, как это сделать, подробное объяснение будет с благодарностью

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));
}

Ответы [ 2 ]

0 голосов
/ 09 мая 2019

Если я правильно понял, вам нужно установить двумерный массив char * вместо int.

То есть вы обращаетесь к правильной строке разыменованием (array[the_ith_row]), а затем обращаетесь к правильному элементу (команда, arg1, arg2, ...) с помощью другой разыменования (array[the_ith_row][the_jth_col]).

Обратите внимание : строки типа "arg1" и "command" обрабатываются как "массив символов", поэтому вам необходимо хранить char * для доступа к ним. int может хранить только один char (с некоторым дополнительным использованием пространства), поэтому здесь не будет работать.

Итак, правильный должен выглядеть так:

#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"

ОБНОВЛЕНИЕ: я пропустил некоторые * здесь ..

0 голосов
/ 09 мая 2019

Вы выделяете, используя sizeof(array), что является неправильной требуемой единицей распределения.

Похоже, вам нужны два разных типа выделения памяти или объекты.

Первый - это массив указателей на символьные строки, поскольку данные файла представляют собой последовательность символьных строк.

Второй вид выделения памяти - для памяти, в которой хранится фактическая строка символов.

Первый вид выделения памяти для массива указателей на символьные строки:

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

Второй вид выделения памяти для символьной строки, которая представляет собой массив символов, будет:

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

256 + 1 необходим для того, чтобы выделить пространство для 256 символов плюс еще один для конца строки.

Таким образом, чтобы выделить все необходимое пространство, вы должны сделать следующее:

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.

Использование realloc()

Был задан вопрос об использовании функции realloc() для настройки размера выделенной памяти.

Для второго вида памяти, памяти для фактической строки символов, главное - использовать realloc() как обычно, чтобы увеличить или уменьшить объем памяти. Однако, если память сокращается, вам необходимо рассмотреть, была ли усечена текстовая строка, и предоставлен ли новый конец конца строки, чтобы обеспечить правильное завершение текстовой строки с помощью индикатора конца строки.

// 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
}

Если вы гарантируете, что когда область памяти для pArray] установлена ​​после NULL после выделения массива, вы можете просто использовать функцию realloc(), как описано выше, без предварительного использования malloc(), так как если указатель в аргументе на realloc() равно NULL, тогда realloc() просто сделает malloc() для памяти.

Для первого типа памяти вам нужно будет рассмотреть вопрос об освобождении любой памяти, указатели которой могут быть уничтожены при сокращении выделенного массива. Это означает, что вам нужно будет немного больше управлять и хранить данные управления о выделенной области памяти. Если вы можете гарантировать, что вы будете только увеличивать размер массива и никогда не сокращать его, то вам не нужно выполнять какое-либо управление, и вы можете просто использовать тот же подход, который предусмотрен для второго типа памяти выше.

Однако, если память, выделенная для первого типа памяти, должна быть как меньше, так и больше, вам необходимо иметь представление о размере выделенной области памяти. Вероятно, самым простым было бы иметь простой struct, который бы обеспечивал как указатель на выделенный массив, так и максимальное количество элементов, которые может содержать массив.

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

Предупреждение: следующий код не был протестирован или даже скомпилирован. Также обратите внимание, что это работает только в том случае, если выделение памяти будет увеличено.

Тогда вы бы обернули функцию realloc() в функцию управления. Эта версия функции обрабатывает только если realloc() всегда для расширения массива. Если сделать его меньше, вам нужно будет обработать этот случай в этой функции.

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;
}

и используйте эту функцию что-то вроде

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...