2012-02-11 2 views
1

Я пытаюсь прочитать карту из текстового файла и создать массив строк в соответствии с количеством строк и столбцов на карте. Каждая ячейка в сетке представляет собой строку из 2 символов.Динамически выделять строковую матрицу в C

Например,

**--**--**-- 
--**--**--** 

должен создать матрицу 2 * 6. Количество строк и столбцов равно ROWS и COLS соответственно. Я использовал

char ***map = malloc(ROWS * sizeof(char *)); 
for (i = 0; i < ROWS; i++) 
{ 
    map[i] = malloc(COLS * sizeof(char) * 2); 
} 

Но когда я пытаюсь использовать map[x][y], это будет сегментации.

ответ

1

char ***map; может быть интерпретирован как «массив массивов строк», поэтому внутренний массив содержит указатели на символы. Таким образом, ваш цикл должен выглядеть следующим образом:

for(i = 0; i < ROWS; i++) { 
    int j; 

    map[i] = malloc(COLS * sizeof(char*)); 
    for(j = 0; j < COLS; j++) map[i][j] = malloc(3 * sizeof(char)); // 3 chars because a string has to be terminated by \0 
} 

В качестве альтернативы, вы можете объявить карту в качестве char **map, то ваш код инициализации будет работать, но тогда вам нужно использовать map[i][j] и map[i][j+1] для доступа к элементам из отдельные клетки.

+0

Пробовал этот, и теперь он не segfault, но теперь похоже, что массив пуст или по какой-то причине он ничего не печатает. Кажется, я не читаю файл в массиве. http://pastebin.com/8Uu4fNJf – user1002327

+0

Ну, заполнил массив вручную, и похоже, что он сейчас печатает. Ну, я думаю, я должен позаботиться о проблеме чтения. – user1002327

+0

О проблеме чтения: я использовал fgets для подсчета количества строк и столбцов на карте и, конечно же, до EOF. Поэтому мне пришлось перезапустить позицию указателя, закрыв и снова открыв файл, но я думаю, что должен быть более эффективный способ сделать это. – user1002327

0

Если вы хотите 2D-массив, вы заявляете map как char***? Измените его на char**.

(. Если я misunderstoop, и вы хотите 2D массив char*, вы должны изменить распределение, использование sizeof(char**) и sizeof(char*) и выделить память для строки отдельно)

Edit: Если вы знаете размер карту, когда вы ее объявите, сделайте это char map[ROWS][COLS][2]; Если вы этого не сделали (или хотите просто передать его другим функциям), вы можете объявить его как char (**map)[2] и сохранить свои распределения так, как они есть.

(Изменение 2 к 3, если вы хотите, чтобы прекратить их \0 (Для того, чтобы распечатать его, например))

+1

Это 2D массив строк, поэтому я добавил дополнительный *. Я посмотрю, что происходит с 'char **'. – user1002327

+0

Не забудьте выделить память в строку! – asaelr

+0

Размер 'char **' и sizeof 'char *' эквивалентен всей системе. Размер одного типа указателя всегда совпадает с другим. –

0

Это должно быть

char ***map = malloc(ROWS * sizeof(char**)); 
for (i = 0; i < ROWS; i++) 
{ 
    map[i] = malloc(COLS * sizeof(char*)); 
    for (int j=0; i<COLS; ++j) 
     map[i][j] = malloc(3*sizeof(char); 
} 

Edit: Как указано в другом ответе и комментарий, должно быть 3 не 2 malloc'ed символов.

+0

Но если вы заранее знаете, что каждая запись имеет 2 символа, вы можете просто сделать ее матрицей «unsigned short's» и переинтерпретировать там, где это необходимо, что может быть менее раздражающим в целом. –

+0

Может быть лучше, чем «malloc» три символа, два для строковых символов и один для символа нулевого терминатора. –

+0

По-прежнему segfault. Это исходный код. http://pastebin.com/Z28gQmyy [-] – user1002327

0

Первая строка должна быть:

char **map = malloc(ROWS * sizeof(char *)); 

Как правило, добавить один * к типу возвращаемого таНос(). Если вы выделите массив из пяти чисел с malloc(5 * sizeof(int)), вы получите int *.

Или, вы можете думать о каждом * как добавление измерение — char * является 1-D массив символов, и char ** является 2-D массив а.

1

Это может выглядеть следующим образом:

int i, j, ROWS = 2, COLS = 6; 
char ***map = malloc(ROWS * sizeof(char **)); 
for (i = 0; i < ROWS; ++i) 
{ 
    map[i] = malloc(COLS * sizeof(char*)); 
    for (j = 0; j < COLS; ++j) 
     map[i][j] = malloc(2 * sizeof(char)); 
} 

Обратите внимание, что 2 char s позволяют хранить эти символы, но это может причинить вам некоторые проблемы, если вы собираетесь работать с ними в виде строки (printf("%s, strcpy ...). В этом случае я предпочел бы выделить память для 3 char s, чтобы можно было сохранить и завершающий символ.

Также обратите внимание, что вы должны очистить эту память после ее выделения, а очистка должна выполняться в обратном порядке в соответствии с назначением. Это может выглядеть так:

for (i = 0; i < ROWS; ++i) 
{ 
    for (j = 0; j < COLS; ++j) 
     free(map[i][j]); 
    free(map[i]); 
} 
free(map); 

Надеюсь, это поможет.

+0

Если вы знаете, что каждая строка имеет всего 2 символа, вам необязательно нужен третий символ. –

+0

@ RichardJ.RossIII: Да, для их хранения достаточно двух символов. Но что, если он хочет их распечатать? Ему не нужно писать собственную функцию для печати, если заканчивается символ ... – LihO

+0

@ RichardJ.RossIII: Во всяком случае, это хороший момент. Я отредактировал свой ответ. – LihO