C Gameboard с проблемами 2d Array - PullRequest
0 голосов
/ 29 января 2019

ОБНОВЛЕНИЕ: исправлено зависание указателя, что решило многие мои проблемы.Также отменил мой инициал Game_board.Затем я создал метод перемещения, который тестирует образцы.

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

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Использование неинициализированного указателя

Большая проблема в том, что вы используете char *tempLabel; в качестве неинициализированного указателя .(Куда он указывает? Какой действительный адрес памяти он хранит в качестве значения?) Попытка копирования данных в него гарантируется SegFault.Вместо этого вам нужно проверить длину game_piece_get_label(piece) и выделить length + 1 символов хранения с malloc, calloc or realloc, например,

Например:

char *game_piece_to_string (struct game_piece *piece)
{
    char *tempLabel;    /* uninitialized pointer */
    size_t len = strlen (game_piece_get_label(piece));

    tempLabel = malloc (len + 1);
    if (tempLabel == NULL) {
        perror ("malloc-tempLabel");
        return NULL;
    }
    memcpy (tempLabel, game_piece_get_label(piece), len + 1);

    if (len > 3)
        tempLabel[1] = '\0';
    for (size_t i = 3; i > len; i--)
        strcat(tempLabel, " ");

    return tempLabel;
}

Заметьте, что вы пытаетесь делать со своими условными выражениями, и цикл с sizeof (a_pointer) не имеет большого смысла.Предположительно, вам нужна длина из tempLabel.

Проблемы с выделением платы

Ваше выделение указатель на указатель-до struct game_piece почти назад.Вы должны сначала выделить row количество указателей, а затем выделить col число struct game_piece на строку.После этого у вас будет выделено хранилище для каждого [i][j] для одного struct game_piece, и именно здесь вы решите поместить char label[30]; как отдельный элемент в структуре, что излишне усложнит ссылку на label.

Внося изменения, вы можете сделать что-то вроде:

void game_board_init(struct game_board* game_board, int rows, int cols)
{
    /* allocate row number of pointers */
    game_board->board = malloc (sizeof(*game_board->board)*rows);
    /* allocate col number of **game_board->board per row
     * (e.g. col * sizeof (struct game_piece) per row)
     */
    for (int i = 0; i < rows; i++){
        game_board->board[i] = malloc(sizeof(struct game_piece) * cols);
    }
    game_board->row = rows;
    game_board->col = cols;
    for (int i=0; i < rows; i++){
        printf("\n");
        for (int j=0; j < cols; j++) {
            game_piece_init_default(&game_board->board[i][j]);
            printf("%s ",game_board->board[i][j].label);
        }
    }
}

Все это указывает на то, что вы либо (1) компилируете свой код без включенных предупреждений или (2) сознательно игнорируя предупреждения, которые генерирует ваш компилятор.Для gcc / clang добавьте -Wall -Wextra -pedantic (как минимум) к параметрам компилятора, для VS добавьте /W3 и не принимайте код, пока он не скомпилирует без предупреждения .Пусть ваш компилятор поможет вам написать лучший код.(это сэкономит вам невероятное количество времени в долгосрочной перспективе)

Вы также захотите взглянуть на Как отлаживать небольшие программы и поговорить с уткой... Действительно, это помогает :)

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

Внесение вышеуказанных изменений и добавление следующей заглушки для предупреждения о неиспользуемых переменных в вашем незавершенном game_board_move_piece, например,

    if (game_board || src_row || src_col || dest_row || dest_col) {}

Я могу скомпилировать ваш код с помощью gcc:

gcc -Wall -Wextra -pedantic -Wshadow -std=c11 -Ofast -o gb_init gb_init.c

без предупреждения .У вас есть немного дополнительной отладки, как показано ниже:

Пример Использование / Вывод

$ ./bin/game_board_init
Please enter the number of rows.
3
Please enter the number of columns.
3

--- --- ---
--- --- ---
--- --- --- Please enter a label for a new piece. Enter "Q" when done.
a
Please enter a row for the piece.
1
Please enter a column for the piece.
1
New piece "a" added.
Please enter a label for a new piece. Enter "Q" when done.c
Please enter a row for the piece.
2
Please enter a column for the piece.
2
New piece "c" added.
Please enter a label for a new piece. Enter "Q" when done.b
Please enter a row for the piece.
0
Please enter a column for the piece.
0
New piece "b" added.
Please enter a label for a new piece. Enter "Q" when done.q
try again -kelly
b  ------
---a  ---
------c  Would you like to move a piece? Enter "Y" to move a piece.
Y
Please enter the piece's row.2
Please enter the piece's column.2
Please enter the piece's new row.2
Please enter the piece's new column.0
A piece is already in that space.
try again -kelly
b  ------
---a  ---
------c  Would you like to move a piece? Enter "Y" to move a piece.
n

Вот где вступает в игру разговор с "уткой"...

Полный использованный тестовый код

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXL 30     /* if you need a constant, #define one (or more) */

struct game_piece
{
    char label[MAXL];
};

struct game_board
{
    struct game_piece **board;
    int row, col;
};

void game_piece_init_default(struct game_piece* piece)
{
    strcpy(piece->label, "---");
}

void game_piece_init(struct game_piece* piece, char* new_label)
{
    size_t len = strlen (new_label);

    if (len < MAXL)
        memcpy (piece->label, new_label, len + 1);
    else {
        fputs ("warning: label truncated.\n", stderr);
        memcpy (piece->label, new_label, MAXL-1);
        piece->label[MAXL-1] = 0;   /* nul-terminate */
    }
}

char *game_piece_get_label (struct game_piece *piece)
{
    return piece->label;
}

char *game_piece_to_string (struct game_piece *piece)
{
    char *tempLabel;    /* uninitialized pointer */
    size_t len = strlen (game_piece_get_label(piece));

    tempLabel = malloc (len + 1);
    if (tempLabel == NULL) {
        perror ("malloc-tempLabel");
        return NULL;
    }
    memcpy (tempLabel, game_piece_get_label(piece), len + 1);

    if (len > 3)
        tempLabel[1] = '\0';
    for (size_t i = 3; i > len; i--)
        strcat(tempLabel, " ");

    return tempLabel;
}

void game_board_init(struct game_board* game_board, int rows, int cols)
{
    /* allocate row number of pointers */
    game_board->board = malloc (sizeof(*game_board->board)*rows);
    /* allocate col number of **game_board->board per row
     * (e.g. col * sizeof (struct game_piece) per row)
     */
    for (int i = 0; i < rows; i++){
        game_board->board[i] = malloc(sizeof(struct game_piece) * cols);
    }
    game_board->row = rows;
    game_board->col = cols;
    for (int i=0; i < rows; i++){
        printf("\n");
        for (int j=0; j < cols; j++) {
            game_piece_init_default(&game_board->board[i][j]);
            printf("%s ",game_board->board[i][j].label);
        }
    }
}

int game_board_is_space_valid(struct game_board* game_board, 
                                int row, int col)
{
    if (row > game_board->row || col > game_board->col)
        return 0;
    if (row < 0 || col < 0) 
        return 0;
    return 1;
}

int game_board_add_piece(struct game_board* game_board, 
                        struct game_piece* piece, int row, int col)
{
    if (game_board_is_space_valid(game_board, row, col) == 0) 
        return 0;
    if (strncmp(game_board->board[row][col].label, "---", 3) == 0) {
        game_board->board[row][col] = *piece;
        return 1;
    }
    return 0;
}

int game_board_move_piece(struct game_board* game_board, 
                    int src_row, int src_col, int dest_row, int dest_col)
{
    return 0;
    if (game_board || src_row || src_col || dest_row || dest_col) {}
}

void game_board_print(struct game_board* game_board)
{
    int col = 3;
    int row = 3;
    printf("try again -kelly");
    for (int i=0; i < row; i++) {
        printf("\n");
        for (int j=0; j < col; j++) {
            printf("%s",game_piece_to_string(&game_board->board[i][j]));
        }
    }
}

int main()
{
    /* declare local variables */
    int row;
    int col;
    int destRow;
    int destCol;
    int rowNum;
    int colNum;
    struct game_board board;
    struct game_piece piece;
    char input_string[30];

    /* get the size of the game board */
    printf("Please enter the number of rows.\n");
    scanf("%d", &rowNum);

    printf("Please enter the number of columns.\n");
    scanf("%d", &colNum);

    game_board_init(&board, rowNum, colNum);

    /* get the first piece's label */
    printf("Please enter a label for a new piece. "
            "Enter \"Q\" when done.\n");
    scanf("%s", input_string);

    while (strcmp(input_string, "Q") != 0 && strcmp(input_string, "q") != 0)
    {
        game_piece_init(&piece, input_string);

        /* get the location to place the piece */
        printf("Please enter a row for the piece.\n");
        scanf("%d", &row);

        printf("Please enter a column for the piece.\n");
        scanf("%d", &col);

        /* verify the space is valid then add the piece to the board */
        if (game_board_is_space_valid(&board, row, col))
        {
            if (game_board_add_piece(&board, &piece, row, col))
            {
                printf("New piece \"%s\" added.\n", 
                        game_piece_get_label(&piece));
            }
            else
            {
                printf("A piece is already at that space.\n");
            }
        }
        else
        {
            printf("Invalid row and/or column.\n");
        }

        /* get the label for the next piece */
        printf("Please enter a label for a new piece. "
                "Enter \"Q\" when done.");
        scanf("%s", input_string);
    }

    /* print the board and check if user wants to move a piece */
    game_board_print(&board);
    printf("Would you like to move a piece? Enter \"Y\" to move a piece.\n");
    scanf("%s", input_string);

    while (strcmp(input_string, "Y") == 0 || strcmp(input_string, "y") == 0)
    {
        /* get the location of the piece */
        printf("Please enter the piece's row.");
        scanf("%d", &row);

        printf("Please enter the piece's column.");
        scanf("%d", &col);

        /* get the destination for the piece */
        printf("Please enter the piece's new row.");
        scanf("%d", &destRow);

        printf("Please enter the piece's new column.");
        scanf("%d", &destCol);

        /* verify both spaces are valid then move the piece */
        if (game_board_is_space_valid(&board, row, col) &&
            game_board_is_space_valid(&board, destRow, destCol))
        {
            if (game_board_move_piece(&board, row, col, destRow, destCol))
            {
                printf("Piece moved to new space.\n");
            }
            else
            {
                printf("A piece is already in that space.\n");
            }
        }
        else
        {
            printf("A row or column is invalid. No piece moved.\n");
        }

        /* print the board and check if the user wants move another piece */
        game_board_print(&board);
        printf("Would you like to move a piece? "
                "Enter \"Y\" to move a piece.\n");
        scanf("%s", input_string);
    }

    return 0;
}
0 голосов
/ 29 января 2019

Добро пожаловать в переполнение стека.В общем, мы НАМНОГО предпочитаем, чтобы вы вставляли здесь свой код, а не ссылались на него.(Ссылка со временем может устареть).Вы также должны описать, какое сообщение об ошибке вы видите, чтобы убедиться, что мы все на одной странице.

У вас может быть несколько проблем, но первая, безусловно, заключается в том, что в game_piece_to_label вы используетенеинициализированный указатель.

char* game_piece_to_string(struct game_piece* piece)
{
    char* tempLabel;
    strcpy(tempLabel, game_piece_get_label(piece));

Вам необходимо распределить часть памяти и назначить ее для tempLabel.В настоящее время вы пишете в случайную память, что для меня приводит к segfault.

...