2

I had to isolate part of my program for a program that plays a game and keeps track of your losses and wins for the duration of your game. However, my losses variable only increments to at most 1, but if my wins variable increments then it resets the losses back to 0. Also once I exit the while loop it resets losses to 0 again. Wins functions normally.

We have tried swapping where wins and losses gets incremented in the if/else clauses. We have also changed all bools to just 0 and 1's and of course I've isolated the problematic code away from the rest of the program. I have print statements everywhere to keep track of variable values. An I just have the if usrWins switching between true and false for the entirety of continueGame until continueGame is false for testing.

#include <stdio.h>

int main() {
    int wins = 0;                   //wins is 0
    int losses = 0;                 //loses is 0
    char usrGame;                   //user yes or no answer
    int continueGame = 1;       //replay game
    int usrWin = 1;                    //if the user wins a round

    while (continueGame){           //until user quits
        if (!usrWin){                //increment wins
            losses++;
            printf("You Losses!\n");
            printf("Wins: %d\n",wins);
            printf("Losses: %d\n",losses);
        }
        else{                       //increment losses
            wins++;
            printf("You Win!\n");
            printf("Wins: %d\n",wins);
            printf("Losses: %d\n",losses);
        }



        printf("Bool: %d  Wins: %d  Losses: %d\n",usrWin,wins,losses);
        printf("\nPlay again? ");     
        scanf("%s",&usrGame);       //prompt if user wants to continue, adding to wins and losses
        printf("\n");

        if (usrGame != 'y'){        //if not, end loop
            continueGame = 0;
        }
        else{
            if (usrWin){    //change usrWin bool
                usrWin = 0;
            }
            else{
                usrWin = 1;
            }
        }
    }

    printf("Wins: %d    Losses: %d\n",wins,losses);     //display results
    return 0;
}

Expected wins to increment, then loses, then wins etc. and finally prints out final value when user ends game. Wins works but losses never goes past 1, rests to 0 if wins increments or the game is ended.

Output looks like:

You Win!

Wins: 1

Losses: 0

Bool: 1 Wins: 1 Losses: 0

Play again? y

You Losses!

Wins: 1

Losses: 1

Bool: 0 Wins: 1 Losses: 1

Play again? y

You Win!

Wins: 2

Losses: 0

Bool: 1 Wins: 2 Losses: 0

Play again? y

You Losses!

Wins: 2

Losses: 1

Bool: 0 Wins: 2 Losses: 1

Play again? n

Wins: 2 Losses: 0

///////////And for a case where I always have usrWin = 0///////////

You Losses!

Wins: 0

Losses: 1

Bool: 0 Wins: 0 Losses: 1

Play again? y

You Losses!

Wins: 0

Losses: 1

Bool: 0 Wins: 0 Losses: 1

Play again? n

Wins: 0 Losses: 0

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
natasha.oz
  • 21
  • 1
  • This exact code in isolation causes that exact output? – Carcigenicate Oct 03 '19 at 21:36
  • Yes. And it's also only the losses variable regardless of if I have it in the if statement or the else statement. – natasha.oz Oct 03 '19 at 21:38
  • 5
    Maybe undefined behavior because you told `scanf` that you're accepting a string, yet you're passing a single char? You might be clobbering memory. – Carcigenicate Oct 03 '19 at 21:38
  • 3
    `scanf` adds a null terminator for `%s` iirc. That null terminator is 0, and the memory directly after `usrGame` might be overwritten by the terminator? – Carcigenicate Oct 03 '19 at 21:40
  • Just changed the both scanf and usrGame to ints to check and the program worked as expected so it was definitely that! Thank you. – natasha.oz Oct 03 '19 at 21:47
  • 3
    It might make more sense to make `usrGame` a `char[2]` array (or maybe larger unless you use a safer version of `scanf` and keep your scanf the same. Conceptually, you're having the user input characters, not numbers. And glad I could solve that. I'm getting rusty in C. That took some mental effort to spot XD – Carcigenicate Oct 03 '19 at 21:49
  • Oh yeah definitely will try that, thank you! Just wanted to try with ints myself to see if that would really fix the problem. – natasha.oz Oct 03 '19 at 21:59
  • 2
    If you're using `char[2]` don't forget to specify `scanf("%1s", &usrGame)` to [avoid a buffer overflow](https://stackoverflow.com/questions/1621394/how-to-prevent-scanf-causing-a-buffer-overflow-in-c). – tadman Oct 04 '19 at 04:01
  • Welcome to Stack Overflow! It looks like you forgot to enable a good set of warnings. For GCC, I recommend `-Wall -Wextra -Wwrite-strings` as a minimum; consider also `-Wpedantic -Warray-bounds` for identifying some other common mistakes. – Toby Speight Oct 04 '19 at 10:11

1 Answers1

0

For your code, I think the problem you have is with scanf and buffer overflow. You tell scanf to read a string and store it at an address of a single char. Thus, where there are two characters or more, scanf will attempt to write into the address spaces of other variables. When reading with %s, scanf will also append a \0 to the end of the string. Your char usrGame is not an array. Thus, anything else that more than a single "y" will go onto other address spaces. Hence, memory corruption.

To fix the issue, you only have to choose a method that reads a single first character from input then disregard the rest of the input, or read a single character then flush the input stream.

You can just try to change scanf to this and it will work:

scanf("%c%*[^\n]",&usrGame);
Kevin Ng
  • 2,146
  • 1
  • 13
  • 18