#c
Вопрос:
Я пытаюсь создать игру «камень,ножницы,бумага», используя функции на языке Си, но, похоже, не могу понять, как присвоить строку переменной char после ее инициализации. Итак, функция генерирует случайное число и сравнивает это число с эфиром, камнем, бумагой или ножницами. тем не менее, я не могу присвоить строку переменной, которую я хочу, чтобы функция возвращала после ее вызова
int getConsoleChoice() { char consolePick; int randNum; srand(time(NULL)); randNum = rand() % 3; if(randNum == 0) { char consolePick = "Rock"; } if(randNum == 1) { char consolePick = "Paper"; } if(randNum == 2) { char consolePick = "Scissors"; } return consolePick; }
Комментарии:
1. Попадание: строка-это последовательность символов, а не один символ. На последовательность символов ссылается указатель, т. е.
char*
.2. То, что у вас здесь есть, — это символьный тип данных. Этот код усекает указатели строковых литералов через целочисленный тип на
char
, а затем возвращает это значение в виде целого числа. С включенными предупреждениями компилятора ваш компилятор должен прямо сейчас устроить настоящую истерику.3. Смотрите
strcpy
иstrncpy
вstring.h
заголовке.4. Не объявляйте переменную внутри
if
блоков. Это делает переменную локальной для блока, она не обновляет переменную, объявленную в верхней части функции.5. Почему ваша функция объявляется возвращаемой
int
, когда вы хотите вернуть строку?
Ответ №1:
Объявите возвращаемое значение переменной и функции как char *
, которое является типом строки в C.
char *getConsoleChoice() { char *consolePick; int randNum; srand(time(NULL)); randNum = rand() % 3; if(randNum == 0) { consolePick = "Rock"; } else if(randNum == 1) { consolePick = "Paper"; } else { consolePick = "Scissors"; } return consolePick; }
Вы также можете упростить это, используя массив:
char *getConsoleChoice() { char *moves[] = {"Rock", "Paper", "Scissors"}; int randNum; srand(time(NULL)); randNum = rand() % 3; return moves[randNum]; }
Комментарии:
1. Это придирка, но функции должны возвращаться
const char*
.2. Я собирался это сделать, но не хотел открывать эту банку с червями, объясняя изменения….
3. Он не показывает никаких ошибок, но он также ничего не выводит,
4. А, в этом есть смысл.
5. Почему бы не воспользоваться кривой обучения? Благодаря своим усилиям вы станете более всесторонним программистом.
Ответ №2:
char
представляет собой один символ. Строка-это набор этих строк, хранящихся вместе где-то в памяти, с нулевым завершающим символом, чтобы мы могли определить, где заканчивается эта строка. Поэтому, когда у нас есть ячейка памяти, в которой хранится набор значений какого-либо типа, мы используем указатель. Он содержит адрес памяти, который «указывает» на начало. Тип строки таков char*
.
Для иллюстрации, давайте выделим несколько байтов в памяти, отображающих строку по какому-либо адресу, представим, что у нас 32-разрядный компьютер, и в качестве аргумента строка начинается с адреса 0xffa01000:
0 1 2 3 4 5 6 7 --- --- --- --- --- --- --- --- 0xffa01000 | R | o | c | k | ~ | ? | ? | ? | --- --- --- --- --- --- --- ---
вышесказанное-это то, как выглядит «Камень» в памяти. Каждая из этих ячеек представляет собой один байт, содержащий char
значение. Обратите внимание, что я использовал ~
для представления байта NUL и ?
для представления памяти, о которой мы не заботимся (потому что она не является частью строки).
Если вы хотите сохранить значение, указывающее на эту строку, вы используете указатель:
const char* rock = "Rock";
В нашем примере из предыдущего примера указатель rock
теперь содержит адрес 0xffa01000, и если мы начнем считывать информацию из памяти оттуда, пока не достигнем байта NUL, то мы прочитаем строку "Rock"
.
Вы можете использовать указатель как массив. Сверху rock[0]
вам дадут персонажа 'R'
, rock[1]
дадут 'o'
и так далее…
Итак, есть некоторые основы того, что на самом деле представляют собой строки в C. Но вернемся к твоей игре.
С тем, что вы пытаетесь сделать, цель, вероятно, состоит в том, чтобы использовать значение 0, 1 или 2 для представления оружия. Потому что с ним просто легче работать. Вы всегда можете превратить это в строку, когда вам нужно. Вот пример того, как вы могли бы это сделать:
const char* weaponName(int w) { static const char* names[] = { "Rock", "Paper", "Scissors" }; // Note: the defensive programming approach would also range-test this index // before using it. return names[w]; }
Эта функция просто использует номер оружия в качестве индекса для поиска строки в массиве. Вспомните, что было раньше… То, что мы имеем здесь, — это просто массив указателей на строки, которые находятся где-то в памяти. Вам не нужно беспокоиться о том, где.
Обратите внимание, что я также использовал const
. Не беспокойтесь об этом слишком сильно, но это предотвращает случайное изменение этих строк. Изменение строковых литералов запрещено, и поэтому мы храним их как константы, чтобы компилятор жаловался, если мы попытаемся их изменить.
Что касается static
, ну, это другая тема, но в основном это означает, что одна копия этого массива всегда будет в памяти, даже после возврата функции. Поэтому мне не нужно беспокоиться о том, что мои строки каким-то образом не будут существовать после возврата функции. Они, вероятно, все равно не исчезли бы, но это гарантирует.
В любом случае, вернемся к тому, как это использовать, это довольно просто. Ваш случайный бросок оружия становится однострочной функцией, и получение строкового представления-это просто вызов функции, которую мы выполнили ранее.
Вот код, который 10 раз перевернет оружие и распечатает, что у него есть:
int randomWeapon() { return rand() % 3; } int main() { // Seed the random generator -- you should only do this once! srand(time(0)); for (int i = 0; i lt; 10; i) { int weapon = randomWeapon(); printf("%sn", weaponName(weapon)); } }