Чтение файла в 2D-массив на C

#c #parsing #file-io #multidimensional-array

#c #синтаксический анализ #file-io #многомерный массив

Вопрос:

Я изучаю C и решил создать текстовую игру в качестве своего учебного проекта. Итак, я пробую этот примитивный «анализатор», который считывает текстовый файл в 2D-массив, но есть проблема: эта карта использует не ячейки шириной в 1 символ, а ячейки шириной в 2 символа. Например, игрок представлен с помощью ** , дверь представлена как ## и так далее.

Это означает, что мне нужно прочитать 2 символа текстового файла, а затем назначить его соответствующей ячейке на карте.

Ну, я создал тестовый файл, который содержит

 aabbccddee
ffgghhiijj
kkllmmnnoo
ppqqrrsstt
uuvvwwxxyy
  

И я попытался прочитать его с

 #include <stdio.h>

#define ROWS 5 
#define COLS 5

int main() {
    FILE *mapfile = fopen("durr", "r");
    char charbuffer[3], row, col, *map[ROWS][COLS];

    /* Initializing array */
    for (row = 0; row < ROWS; row  ) {
        for (col = 0; col < COLS; col  ) {
            map[row][col] = "  ";
        }
    }

    /* Reading file into array */
    for (row = 0; row < ROWS; row  ) {
        for (col = 0; col < COLS; col  ) {
            map[row][col] = fgets(charbuffer, 3, mapfile);
        }
    }

    /* Printing array */
    for (row = 0; row < ROWS; row  ) {
        for (col = 0; col < COLS; col  ) {
            printf("%s", map[row][col]);
        }
        printf("n");
    }

    fclose(mapfile);    
    return 0;
}
  

Но когда я его выполняю, я получаю это

 uuuuuuuuuu
uuuuuuuuuu
uuuuuuuuuu
uuuuuuuuuu
uuuuuuuuuu
  

Я думаю, что это как-то связано с тем фактом, что fgets возвращает указатель, но я не уверен. Я пытался сделать это с помощью fgetc, но это выглядит неаккуратно, и я отбросил его после прочтения о gets.

Комментарии:

1. В C нет строк , только массивы символов. Следовательно, вы не можете назначить «строки» ! Вместо этого используйте strncpy() и убедитесь, что вы понимаете управление памятью, которое задействовано.

Ответ №1:

Вы должны были изменить содержимое, прочитанное из файла. Замените блок чтения файла этим:

 /* Reading file into array */
for (row = 0; row < ROWS; row  ) {
    for (col = 0; col < COLS; col  ) {
        if (fgets(charbuffer, 3, mapfile))
            map[row][col] = strdup(charbuffer);
    }
}
  

и не забудьте также поместить это в начало вашего кода:

 #include <string.h>
  

Комментарии:

1. Я думаю, это то, что я искал. Я искал способ (каким-то образом) разыменования возвращаемого значения fgets, но да, это то, что я искал. Теперь это вроде как работает, все странно отформатировано. Вот так pastebin.com/1F2D5zNp . Может быть, я делаю что-то не так?

2. Если идея состоит в том, чтобы выучить C, то он должен привыкать к malloc, а не вызывать функцию, которая даже не является частью стандарта.

3. Я бы сказал, это было из-за размеров массива. Не забывайте, что fgets не только считывает до, но и помещает EOF в буфер.

4. @MattPhillips Я согласен с тем, что вы сказали. Но я также должен напомнить вам, что POSIX это действующий стандарт.

5. О, Мэтт и Синкоу, вы правы. Думаю, мне придется выяснить, как решить эту проблему. И я родом из языков более высокого уровня, поэтому я никогда не управлял памятью вручную, поэтому я прочитаю немного больше об этом. Спасибо, ребята.

Ответ №2:

Основная проблема заключается в том, что

 char *map[ROWS][COLS];
  

выделяет пространство только для указателей СТРОК x COLS char, оно не выделяет пространство для самих строк. Таким образом, вы постоянно перезаписываете charbuffer, как вы делали это с каждой итерацией, что объясняет, почему в итоге одни и те же символы повторяются снова и снова при чтении. Вам нужно динамически выделять необходимую вам память в соответствии с

 for (row = 0; row < ROWS; row  ) {
    for (col = 0; col < COLS; col  ) {
        charbuffer = (char*)malloc(sizeof(char) * 3);  //****
        map[row][col] = fgets(charbuffer, 3, mapfile);
    }
}
  

Комментарии:

1. Ха, я понимаю incompatible implicit declaration of built-in function ‘malloc’ . Может быть, я что-то упускаю? Может ли это быть мой gcc? О, и мне пришлось изменить charbuffer[3] на *charbuffer, иначе я бы получил incompatible types when assigning to type ‘char[3] from type ‘char *’ ошибку.

2. @user1002327 Правильно насчет charbuffer[3] -> charbuffer *, забыл упомянуть об этом. Что касается malloc, попробуйте #включить «stdlib.h».