Nick_is_asking Ответов: 4

Проблема языка Си с возвратом функции


Привет всем! У меня есть небольшая проблема в с.
Весь мой код приведен ниже: (это игра, известная как камень-ножницы-карандаш-бумага)
Код:

Что я уже пробовал:

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

char* CPU_random_choice(char **cpu_array);
int player_input();
int check_hand_in_array(char **array , char *input);
int increase_score(int *score);
void result(int *for_CPU , int *for_player);
void win(char **array , char *player_hand , char *cpu_hand , int *CPU_score , int *player_score);

int main(void)
{
    int CPU_score = 0;
    int player_score = 0;
    char *Hands[4] = {"Rock" , "Scissor" , "Pencil" , "Paper"};
    result(&CPU_score , &player_score);

    char *cpu_choice = CPU_random_choice(Hands);
    printf("\nCPU hand: %s\n\n" , cpu_choice);
    int player_hand = player_input();
    printf("\nPlayer hand: %s\n" , Hands[player_hand - 1]);
    win(Hands , Hands[player_hand - 1] , cpu_choice , &CPU_score , &player_score);
    printf("\n\n");
    result(&CPU_score , &player_score);
}

char* CPU_random_choice(char **cpu_array)
{
    srand(time(NULL));
    int i = rand() % 4;
    return cpu_array[i];
}

int player_input()
{
    printf("1:  Rock\n2:  Scissor\n3:  Pencil\n4:  Paper\n");
    printf("Player give a hand: ");
    int player_hand;
    scanf("%d" , &player_hand);

    do
    {
        if(player_hand < 0 && player_hand > 4)
        {
            printf("Invalid hand...\nTry again: ");
            scanf("%d" , &player_hand);
        }
    }

    while(player_hand < 0 && player_hand > 4);

    return player_hand;
}

void result(int *for_CPU , int *for_player)
{
    printf("PLAYER  -  CPU\n==============\n");
    printf("   %d\t    %d\n" , *for_CPU , *for_player);
}

int increase_score(int *score)
{
    return (*score)++;
}

void win(char **array , char *player_hand , char *cpu_hand , int *CPU_score , int *player_score)
{
    if((strcmp(player_hand , CPU_random_choice(array))) == 0)
    {
        printf("Draw!");
    }
    else if(strcmp(player_hand , "Rock") == 0 && (strcmp(CPU_random_choice(array) , "Scissor") || strcmp(CPU_random_choice(array) , "Pencil")) == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Rock") == 0 && (strcmp(player_hand , "Scissor") || strcmp(player_hand , "Pencil")) == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(player_hand , "Rock") == 0 && strcmp(CPU_random_choice(array) , "Paper") == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Rock") == 0 && strcmp(player_hand , "Paper") == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(player_hand , "Scissor") == 0 && strcmp(CPU_random_choice(array) , "Rock") == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Scissor") == 0 && strcmp(player_hand , "Rock") == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(player_hand , "Scissor") == 0 && (strcmp(CPU_random_choice(array) , "Pencil") || strcmp(CPU_random_choice(array) , "Paper")) == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Scissor") == 0 && (strcmp(player_hand , "Pencil") || strcmp(player_hand , "Paper")) == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(player_hand , "Pencil") == 0 && (strcmp(CPU_random_choice(array) , "Rock") || strcmp(CPU_random_choice(array) , "Scissor")) == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Pencil") == 0 && (strcmp(player_hand , "Rock") || strcmp(player_hand , "Scissor")) == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(player_hand , "Paper") == 0 && (strcmp(CPU_random_choice(array) , "Pencil") || strcmp(CPU_random_choice(array) , "Scissor")) == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Paper") == 0 && (strcmp(player_hand , "Pencil") || strcmp(player_hand , "Scissor")) == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(player_hand , "Paper") == 0 && strcmp(CPU_random_choice(array) , "Rock") == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Paper") == 0 && strcmp(player_hand , "Rock") == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
    else if(strcmp(player_hand , "Pencil") == 0 && strcmp(CPU_random_choice(array) , "Paper") == 0)
    {
        printf("Player wins!");
        increase_score(player_score);
    }
    else if(strcmp(CPU_random_choice(array) , "Pencil") == 0 && strcmp(player_hand , "Paper") == 0)
    {
        printf("CPU wins!");
        increase_score(CPU_score);
    }
}

Я исправил предыдущую проблему,которая у меня была с другим способом ,но теперь моя проблема заключается в том,что программа не возвращает правильное решение(победитель) и не увеличивает счет победителя(иногда это происходит, иногда увеличивает счет проигравшего, иногда ничего не делает).Я не знаю, что происходит...
Мне нужна твоя помощь...
Спасибо!!!

KarstenK

Оригинал Грифф прав. Всегда помните: компилятор-единственный друг в программировании, который говорит вам: "не делай этого, потому что у тебя будут проблемы" ;-)

Richard MacCutchan

Опубликованный вами код не соответствует показанному сообщению об ошибке.

Nick_is_asking

Я только что загрузил весь код.Посмотри. Спасибо!!

Richard MacCutchan

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

Richard MacCutchan

if(player_hand < 0 && player_hand > 4)

Целочисленное значение не может быть меньше нуля и больше, чем 4 в то же время.

4 Ответов

Рейтинг:
32

OriginalGriff

Нет-нет - плохая идея!
Когда вы объявляете массив (или любую другую переменную) внутри функции, он создается в стеке (форма памяти, которая содержит локальные переменные и адреса возврата функции), и эта память освобождается и повторно используется при выходе из функции. Поэтому при попытке передать эту память внешнему миру функция имеет специальное имя: hanging reference И это очень плохая идея, потому что следующая функция, которую вы вызовете, будет использовать точно такую же память для очень разных целей и испортит массив - или вы измените массив и испортите память, используемую для других вещей . И тогда все ставки отменяются: ваш код развивает странные ошибки или вылетает "без причины".
И очень, очень трудно обнаружить эти проблемы, когда они возникают, потому что обычно проходит много времени после того, как вы написали - и протестировали - код, который вызвал их!

Так что не делай этого. Когда-либо.

Если вам нужно вернуть новую память из функции, то вам нужно использовать функция malloc[^] чтобы выделить его в куче (другая форма памяти в вашей программе) - и не забудьте использовать свободный[^] чтобы освободить память, когда вы закончите с ней, или ваше приложение начнет "утекать" память, и это тоже плохо!

Что касается проблемы, которую вы заметили - понятия не имею. У нас нет доступа к коду, который вызывает ваша функция, поэтому мы понятия не имеем, какими должны быть параметры.


Nick_is_asking

Я только что загрузил весь код.Посмотри. Спасибо!!

OriginalGriff

А теперь все еще хуже: он рухнет намного раньше*, потому что вы не выделяете никакой памяти для player_hand*

типа char *player_hand;
делать
{
scanf("%s" , player_hand);

Где предполагается разместить пользовательский ввод? Прочтите, что я сказал, особенно то, что касается Мэллока и фри ...

Nick_is_asking

Я понимаю ,что когда я строю функцию,ее переменные сохраняются в специальной части памяти (например, main или другая функция), но я не понимаю, как исправить эту проблему сейчас...
Я перешел по вашей ссылке (malloc/free) ,но она не работает(я определенно делаю что-то не так,я знаю...).
Что же мне делать?
Вы не могли бы мне помочь?
Еще раз спасибо!!!

OriginalGriff

Откуда мне знать, что не так с кодом, который я не вижу? :смеяться:

И "это не работает", вероятно, самый бесполезный отчет о проблеме, который мы получаем - и мы получаем его много. Она ничего не говорит нам о том, что происходит или когда это происходит.
Итак, расскажите нам, что он делает, чего вы не ожидали, или не делает, что вы сделали.
Расскажите нам, что вы сделали, чтобы это произошло.
Сообщайте нам о любых сообщениях об ошибках.

Nick_is_asking

Ну,я хочу вернуть строковый символ из функции player_input ().
Что я должен исправить?

OriginalGriff

Ну, сначала решите, что вы хотите вернуть.
На данный момент player-input возвращает указатель на символ, а не символ.
Если вы хотите вернуть символ, это неправильно.
Это вы хотите вернуть строку символов, это верно - но вам нужно использовать malloc для выделения памяти (и бесплатно освободить ее позже, когда вы закончите с ней).

Рейтинг:
2

KarstenK

Ваш

CPU_random_choice()
функция каждый раз создает новое случайное значение, так что у вас нет четкого потока кода.

Я бы создал для всех этих значений некоторую глобальную константу sstring.
 char *Hands[4] = {"Rock" , "Scissor" , "Pencil" , "Paper"};
// to
const char *HAD_ROCK = "Rock"; // and so on
Таким образом, вы вышли из проблемы локальных ценностей.


Рейтинг:
1

Richard MacCutchan

char* player_input(char **array)
{
    //printf("\n");
    printf("Player give a hand: ");
    char *player_hand; 
    do
    {
        scanf("%s" , player_hand);

        if(check_hand_in_array(array , player_hand) == 0)
        {
            printf("Invalid hand...\nTry again: ");
        }
    }

    while(check_hand_in_array(array , player_hand) == 0);

    return *player_hand;
}

Функция объявляется для возврата char* но ваш оператор return пытается вернуть один символ. Вы объявляете указатель player_hand но это ни на что не указывает так что scanf разобьется. Вы тоже звоните check_hand_in_array дважды, когда вам это нужно только один раз.

Вам нужно что-то вроде:
char* player_input(char **array)
{
    //printf("\n");
    printf("Player give a hand: ");
    char *player_hand = (char*)malloc(256); // get some space
    int handOK = 0;
    do
    {
        scanf("%s", player_hand);
        handOK = check_hand_in_array(array , player_hand);
        if (handOK == 0)
        {
            printf("Invalid hand...\nTry again: ");
        }
    }
    while(handOK == 0);

    return player_hand; // return the allocated hand buffer
}


Member 12556999

убедитесь, что вы освободили данные malloc, иначе у вас будет утечка памяти

Richard MacCutchan

Вы не можете освободить его в этой функции, так как он передается обратно вызывающему объекту.

Рейтинг:
0

Patrice T

Цитата:
Я хочу получить объяснение своей вины...

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