#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()
функцию, потому что нет причин передавать по значению, и это требует гораздо больших вычислительных затрат (скопируйте всю структуру)