Как настроить заполнение массива с помощью memset

#c

#c

Вопрос:

У меня есть структура Player, которая содержит игровое поле, представляющее собой 2d массив символов.

Когда я использую memset, он не устанавливает массив

Я пробовал использовать адрес платы (amp;, *) и без этих символов

Я могу заставить это работать, если использую указатель на переменную Player в ‘initializeBoard’, но в назначении указано не использовать указатель

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

const int ROWS = 10;
const int COLS = 10;

const char *PLAYERONE = "Player 1";
const char *PLAYERTWO = "Player 2";
const char WATER = '~';
const int NUM_SHIPS = 5;

typedef struct gameBoard {
    char board[ROWS][COLS];
} GameBoard;

typedef struct human {
    char name[20];
    GameBoard gameBoard;
} Player;

// function prototypes

void displayGameBoard(Player player);
void initializeBoard(Player player);
void initializePlayer(Player *player, const char *name);






// main function
int main() {
    Player playerOne;
    Player playerTwo;
    // call function welcomeScreen

    initializePlayer(amp;playerOne, PLAYERONE);
    // end program
    return 0;
}

void displayGameBoard(Player player) {
    int row;
    int col;
    printf("%s's Game Boardn", player.name);
    printf("---------------------------------------------n");
    printf("|   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |n");
    printf("---------------------------------------------n");
    for (row = 0; row < ROWS; row  ) {
        printf("| %d |", row);
        for (col = 0; col < COLS; col  ) {
            printf(" %c |", player.gameBoard.board[row][col]);
        }
        printf("n");
    }
    printf("---------------------------------------------");
}

void initializeBoard(Player player) {
    memset(*player.gameBoard.board, WATER, sizeof(player.gameBoard.board));
}

void initializePlayer(Player *player, const char *name) {
    char playerName[20];
    GameBoard playerBoard;
    strcpy(player->name, playerName);
    player->gameBoard = playerBoard;
    initializeBoard(*player);
    displayGameBoard(*player);
}
  

Я ожидаю, что результат будет заполнен символом ‘~’, но это либо портит весь терминал, либо выводит пробелы

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

1. лучше предоставить небольшой фрагмент кода, который применим только к вашей проблеме. Просмотр этого занимает много времени

2. Если вы знаете , что проблема заключается в вызове memset, есть ли веская причина для публикации такого большого количества кода?

3. Я сократил объем кода

4. Не копируйте структуру по значению. Вы получили это правильно в initializePlayer , но неправильно в initializeBoard . Голосование за закрытие этого как простой опечатки.

5. При вызове strcpy(player->name, playerName); , playerName не был инициализирован -> неопределенное поведение. Исправьте это в первую очередь. Ты имел в виду strcpy(player->name, name); ?

Ответ №1:

Здесь:

 void initializeBoard(Player player) {
    memset(*player.gameBoard.board, WATER, sizeof(player.gameBoard.board));
}
  

Вы передаете Player объект по копии, а не по ссылке. Устанавливаемый вами объект не является объектом, который вы намереваетесь установить, и в любом случае является временным. Передача больших структур в стеке также неэффективна (в этом случае вы также можете пересмотреть подпись displayGameBoard() ). Также члену board не нужно разыменовывать.

 void initializeBoard(Player* player);

...

void initializeBoard(Player* player) 
{
    memset( player->gameBoard.board, WATER, sizeof(player->gameBoard.board));
}
  

Затем вызовите его в initializePlayer() таким образом:

 initializeBoard(player);
  

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

1. @Trickzter Это не имеет значения, он, очевидно, начал писать это до того, как я опубликовал это. Мне также абсолютно не нравится торопиться, просто чтобы первым опубликовать ( 1).

2. @Trickzter : К чему ты клонишь? Проверьте время публикации. Ответ не был опубликован, когда я начал писать это — я ничего не могу поделать, если есть один правильный ответ, и на него одновременно отвечали два человека! Кроме того, два человека, объясняющие одно и то же, могут дать разные представления или добавить ясности.

3. @Clifford Я понимаю это, но ради ясности и простоты я думаю, что избыточность не является необходимой. Вы оба прояснили одну и ту же ситуацию одинаковым образом. Просто хотел прояснить эту тему! Я знаю, что подобные вещи происходят легко и являются обычным явлением 🙂

4. @Trickzter : Я не собираюсь удалять сообщение, потому что оно было продублировано из-за условия гонки. Ваш представитель SO не указывает, что вы квалифицированы, чтобы быть арбитром таких вещей. Способ повысить рейтинг ответа, который вам нравится, — это проголосовать за него. Это дублирование безвредно, и, похоже, теперь оно предпочтительнее для OP в любом случае.

Ответ №2:

Проблема в том, что вы передаете свою структуру проигрывателя по значению здесь:

 initializeBoard(*player);
  

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

 initializeBoard(player);
  

и измените initializeBoard-функцию на эту:

 void initializeBoard(Player *player) {
   memset(player->gameBoard.board, WATER, sizeof(player->gameBoard.board)); 
}
  

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