Ошибка сегментации на загрузчике для игры Sokoban в C - PullRequest
0 голосов
/ 01 марта 2019

Так что я пытаюсь написать код на C, который бы создал массив символов из файла, похожего на:

10 8
##########
######  ##
# $  $  ##
# #  .# ##
#  . #.@ #
##$# *   #
##   #####
##########

Но я застрял с ошибкой сегментации, и я былпоиск, откуда это может прийти безуспешно ... Я был бы очень признателен, если бы кто-то мог прочитать мой код и дать мне свой отзыв ... Заранее спасибо!

//We define a structure representing a map (for the Sokoban game)
    typedef struct map map;
    struct map{
        int width;
        int height;
        int x;
        int y;// x and y are the position of the player
        char* p_char; //p_char is pointing an array which will contain the elements of the map, the characters currently on the file above
    };

    //The function that reads the file and store the characters in an array
    char* ReadMap(const char const* filename)
    {
        FILE* p_file = fopen(filename, "r");
        char* p_array = NULL;
        if (p_file = NULL) {
            exit(EXIT_FAILURE);
        }
        else{   
            size_t size=1;
            while (getc(p_file)!=EOF) {
                size++;
            }
            p_array=(char*)malloc(sizeof(char)*size);
            fseek(p_file,0,SEEK_SET);
            for(size_t i=3; i<size-1; i++) {
                p_array[i]=(char)getc(p_file);//i=3 cause we don't want the 2 first int, representing the size of the array
            }
            p_array[size-1]='\0';
            fclose(p_file);
        }
        return p_array;
    }

    int main(int argc, char *argv[]){
        if (argc != 2) {
            fprintf(stderr, "You must provide a file name!\n");
            exit(EXIT_FAILURE);
        }
        //We define a map structure
        map map_loaded; 
        FILE *p_file1 = NULL;
        p_file1=fopen(argv[1],"r");
        if (p_file1==NULL) {
            fprintf(stderr, "Cannot read file %s!\n", argv[1]);
            exit(EXIT_FAILURE);
        }
        //we're trying to recover width and height, two int at the beginnning of the file
        int width=0;
            map_loaded.width=width;
        int height=0;
            map_loaded.height=height;
        int fscanf_result=0;
            fscanf_result=fscanf(p_file1, "%d %d\n", &width, &height);
        char* p_char=NULL;
        map_loaded.p_char=p_char;
        p_char=ReadMap(argv[1]);
        if (p_char != NULL) {
            printf("%s\n", p_char);
            free(p_char);
        }
    }

1 Ответ

0 голосов
/ 01 марта 2019

Причиной ошибки сегментации является выражение p_file = NULL, используемое в качестве условия.

p_file = NULL - это выражение присваивания .Он устанавливает p_file в NULL и оценивается как присвоенное значение, равное NULL.NULL трактуется как ложное при использовании в качестве условия.

С другой стороны, условие, являющееся ложным, указывает на успешное открытие файла, когда условие сравнение p_file == NULL.

В этом случае условие становится ложным, когда p_file не является NULL.

По этой причине в выражении else записывается код, который ожидает, что p_file не является NULL..

Код включает в себя операторы, которые передают p_file в fgetc().

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

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

В данном примере размерная часть равна 10 8, что составляет 4 символа.Это означает, что пропуск «3 символов» не имеет смысла.

Также обратите внимание, что запуск i с 3 не пропустит содержимое файла и просто оставит первые 3 элемента массива неинициализированными, как указывают некоторые программисты.

Вместо этого вы можете «пропустить первую строку».Другими словами, вы можете «пропустить до первого символа новой строки».

size_t size=1;
int c;

while (getc(p_file)!=EOF) {
    size++;
}

fseek(p_file,0,SEEK_SET);

while ((c=getc(p_file))!='\n' && c!=EOF) { // drop the first line
    size--;
}

p_array=(char*)malloc(sizeof(char)*size);

if (p_array!=NULL) { // for in case malloc() fails
    for(size_t i=0; i<size-1; i++) {
        p_array[i]=(char)getc(p_file);
    }

    p_array[size-1]='\0';
}

fclose(p_file);

Одним из способов включения индексирования width*i+j является удаление символов новой строки, добавив этот код после строки p_array[i]=(char)getc(p_file);:

if (p_array[i] == '\n') { // if the character is newline, remove it
    i--; // rollback
    size--; // adjust size for the newline character dropped
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...