Why is my program skipping my first loop? - c

I am working on an assignment in C, trying to create a program that simulates a "Rock, Paper, Scissors" match between the user and the computer. Everything is working fine except the for loop I have created is skipping the first iteration of the loop and going straight to my second match. Is there any way to fix this? Code and compilation below
main.c
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
int main(void) {
srand(time(0)); // This gives the random function a new seedallows me to use time in order to create "random" numbers. //
time_t t; // Allows the program to store system time values. //
int R; // This statement declares the variable for the move "Rock". //
int P; // This statement declares the variable for the move "Paper". //
int S; // This statement declares the variable for the move "Scissors". //
int numMatches; // This statement declares the variable for the number of matches that are to be played. //
int roundNumber; // This statement declares the variable for the current round of the match that is being played. //
int compMove; // This statement declares the variable that represents the move (rock, paper, or scissors) that the computer makes. //
char userMove; // This statement declares the variable that represents the move (rock, paper, or scissors) that the user of the program chooses. //
int randNumber; // This statement declares the variable for the random number that will be generated. //
printf("Starting the Rock, Paper, Scissors Game!\n");
printf("Enter the number of matches to play: ");
scanf(" %d", &numMatches); // This statement allows the user to input the number of matches he/she wishes to play. //
for (roundNumber = 1; roundNumber <= numMatches; roundNumber++) { // This for statement first initializes the number of rounds to 1. Then, the statement sets a parameter that the for loop will only continue as long as the number of matches completed is less that than the total matches that are to played. The last statement increments
printf("\nMatch %d: Enter R for rock, P for paper, or S for scissors: ", roundNumber);
fflush(stdin);
userMove = getchar();
randNumber = (rand() % 3) + 1; //1 to 3//
compMove = randNumber == 0 ? 'R' : randNumber == 1 ? 'P' : 'S';
if ((userMove == 'R') && (compMove == 'S')) { // These statements state the result of the game depending on the user's move and the computer's move. //
printf("The computer chose scissors. You won \n");
} else
if ((userMove == 'P') && (compMove == 'R')) {
printf("The computer chose rock. You won \n");
} else
if ((userMove == 'S') && (compMove == 'P')) {
printf("The computer chose paper. You won \n");
} else
if ((userMove == 'R') && (compMove == 'R')) {
printf("The computer chose rock. You tied \n");
} else
if ((userMove == 'P') && (compMove == 'P')) {
printf("The computer chose paper. You tied \n");
} else
if ((userMove == 'S') && (compMove == 'S')) {
printf("The computer chose scissors. You tied \n");
} else
if ((userMove == 'R') && (compMove == 'P')) {
printf("The computer chose paper. You lose \n");
} else
if ((userMove == 'P') && (compMove == 'S')) {
printf("The computer chose scissors. You lose \n");
} else
if ((userMove == 'S') && (compMove == 'R')) {
printf("The computer chose rock. You lose \n");
}
}
return 0;
}
compile

The line:
userMove = getchar();
Catches the char but lets a newline character \n in the buffer caused by pressing Enter, you need to discard it.
You can do, for instance, this:
userMove = getchar();
getchar(); // <-- catches and discards '\n'
I would also get rid of fflush(stdin), it causes undefined behaviour, reasons in Why should I use fflush(stdin) in this program?.
Replace it also with getchar(). Or use type specifier with discard in your scanf function like scanf(" %d%*c", &numMatches);
Here is a working sample
Another thing that is not very good is the fact that none these variables is being used:
time_t t; // Allows the program to store system time values. //
int R; // This statement declares the variable for the move "Rock". //
int P; // This statement declares the variable for the move "Paper". //
int S; // This statement declares the variable for the move "Scissors". //

Related

How to do loop menu in C

I'm trying to do loop menu with some basic functions, everything is working fine apart of looping menu
in my opinion i have something wrong with while loop but i can't figure out what it is.
int main(void) {
char letter;
char status = 0;
printf ("--------------------------------------\n");
printf("a – Calculate the area of a rectangle\n");
printf("b – Calculate the area of a circle\n");
printf("c – Display a multiplication table\n");
printf("d – Add two numbers\n");
printf("x - exit program\n");
printf ("--------------------------------------\n");
scanf("%c",&letter);
while (status == 0)
{
if (letter == 'a' || letter == 'A')
{
}
if (letter == 'b'|| letter == 'B')
{
}
if(letter == 'c'|| letter == 'C')
{
}
if (letter == 'd'|| letter == 'D')
{
}
if(letter == 'x' || letter == 'X')
{
printf("shut down\n");
break;
}
status ++
}
return 0;
}
You need to pace a scanf(" %c",&letter); inside the loop body; otherwise, you will not get a chance to ever enter an x...
Please note the space before the %c, i.e. the " %c"-format, which captures any new line in the input buffer from a previous input.
Maybe you meant that status will be int and not char?
You should read input also in the beginning of loop, otherwise you will take only one input
After the first iteration, you advance status so it will exit the loop. Is this what you tried to achieve? I guess you meant for:
if(letter == 'x' || letter == 'X')
{
printf("shut down\n");
status ++
break;
}
Your loop will run only one time cause 'status ++' will work no matter the condition you should use it inside the x case -
if(letter == 'x' || letter == 'X')
{
printf("shut down\n");
status ++;
}
This should break your loop only after 'x' is entered.

Scanf in visual studio not accepting multiple cases of characters

I'm creating a conversion project for letters/numbers ASCII table. My code is supposed to be 'interactive', so the user would type 'y' or 'n' to answer questions on the screen. However, it doesn't want to do this twice...
I have tried:
Just trying numbers instead of characters, but it's not exactly what I want
The %[\n]*c, and %[\n]c, and %[\n]*s ... technique but it doesn't help ;-;
Testing in a different project, but the only way I am able to do it is for multiple scanf()s to be in a row.
Here is the code:
printf("Would you like to convert a number today? \n");
printf("Please press Y or N \n");
scanf("%c", &input);
if (input == 'y' || input == 'Y') { //compare input if they said 'yes'
printf("\nThank you! \nWhat number?\n");
scanf("%d", &number);
flag = test(number);
if (flag == 0) { //if there is an equivalent letter
letter = conversion(number); //find the equivalent letter
printf("\nYour Number \t ASCII letter\n");
printf("%d\t %c\n", number, letter);
}
}
else if (input == 'n' || input == 'N') {
printf("\nWould you like to convert a letter instead? This time enter 0 or 1\!\n\n"); //problem here!!
printf("I wish I could say it was to \' Spice things up \' ...but it\'s not ;-; \n\n");
scanf("%d", &input2);
if (input2 == 0) { //this needs to be checking whether the user input Y/y
printf("Great choice adventurer!\n");
printf("What letter will it be today?\n\n");
//..I would go to a different funtion here ie: test2(letter)...
scanf("%d", &number); //I showed that it worked with multiple numbers, but I can't get this to work with multiple letters
printf("%d", number);
}
if (input2 == 1) { //this needs to be checking whether the user input N/n
printf("Difficult to please, I see...\n\n");
printf("I suggest you move on with that attitude!\n\n");
printf("Bye bye then\n");
}
}
else { //if they tried to break the code
printf("Sorry I did not recognise your command...please retry\n");
printf("Press Y or N next time!\n");
}
The first check works perfectly, I just want the second check to be like the first!
Some 'solutions' caused a overflow, which I don't want if possible
Even if someone could explain why this isn't working the way I intended would be very helpful!
I'm not sure what confuses you.
Use
char foo;
scanf(" %c", &foo);
for single characters, eg. letters and
int bar;
scanf("%d", &bar);
for numbers, integers. If you type a letter instead, scanf() will fail.
%[...] is for strings.
scanf() returns the number of successful conversions (or EOF), so for
int height;
int width;
scanf("%d %d", &height, &width);
it returns 2 if successful. It might return 1 if only height could be read.
So to check for errors on user input you should do:
int height;
int width;
if (scanf("%d %d", &height, &width) != 2) {
// handle the error, maybe exit the program.
}
Your code could look like that (without error handling):
#define _CRT_SECURE_NO_WARNINGS // you said Visual Studio? Without it you should get
// warnings about some functions being insecure.
#include <ctype.h> // isalpha() returns true if the value is a letter
#include <stdlib.h> // EXIT_SUCCESS
#include <stdio.h> // puts(), printf(), scanf()
int main(void)
{
for(;;) { // for-ever ... endless loop since the user exits by answering
// 'n' or 'N' two times
puts("Would you like to convert a number today?\nPlease press Y or N:");
char input;
if (scanf(" %c", &input) != 1) // We reached EOF ... end of file
break; // that's improbable for stdin,
// but input could be redirected to
// read from a file instead.
if (input == 'y' || input == 'Y') {
puts("\nThank you!\nWhat number?");
int number;
scanf("%d", &number);
if (isalpha((char unsigned)number)) // *)
printf("\nYour Number \t ASCII letter\n%d\t %c\n\n", number, number);
else
puts("Sorry, but that's not the ASCII code of a letter :(\n");
}
else if (input == 'n' || input == 'N') {
puts("\nWould you like to convert a letter instead?\nPlease press Y or N:");
scanf(" %c", &input);
if (input == 'y' || input == 'Y') {
puts("\nGreat choice adventurer!\nWhat letter will it be today?");
char letter;
scanf(" %c", &letter);
if (isalpha(letter))
printf("\nYour letter \t ASCII code\n%d\t %c\n\n", letter, letter);
else
puts("Sorry, but that's not a letter :(\n");
}
else if (input == 'n' || input == 'N') {
puts("\nDifficult to please, I see...\n\nI suggest you move on with that attitude!\n");
puts("Bye bye then.");
return EXIT_SUCCESS;
}
}
else {
puts("Sorry I did not recognize your command... Please retry.");
puts("Press Y or N next time!\n");
}
}
}
*) isalpha() (and the other functions in <ctype.h>) expects a value that fits in a unsigned char or the value EOF. It has undefined behaviour for other values. Since we read user input into an int we cannot be sure that's the case so we have to cast the value to unsigned char before passing it to isalpha() (and friends).
Next time you ask a question please include your full code, including variable declarations, functions like test() and conversion() and #includes. But please, post an example that focuses on your problem at hand. All that dialog you included would not have been necessary.

Change(?) user input character into another character c language

Writing a program for school to cause a user inputted character to identify a gas cylinder. Here is what i have written so far, but all inputs display ammonia.
#include <stdio.h>
int main()
{
char n;
printf("Please enter the first letter of color of gas cylinder\n");
scanf("%c", &n);
if(n = 'o' ){
printf("Ammonia\n");
}
else if(n = 'b'){
printf("Carbon Monoxide\n");
}
else if(n = 'y'){
printf("Hydrogen\n");
}
else if(n = 'g'){
printf("Oxygen\n");
}
else{
printf("Contents Unknown\n");
}
return 0;
}
You want to use ==—the equality operator—inside your if statements.
= is the assignment operator—it will set n to be 'o', so your first if statement always returns true ('o' is non-zero).

unintended loop (C)

I keep getting a duplicate loop when running a Rock Paper Scissors program in C:
#include <stdio.h>
#include <stdlib.h>
int getUserInput(userInput);
int getComputerInput(cpuInput);
int pickWinner(int player, int cpu);
int main()
{
int playerWins = 0;
int compWins = 0;
int ties = 0;
int userInput;
int cpuInput;
int userChoice =1;
int compChoice;
int decision;
while (userChoice != 4)
{
compChoice = getComputerInput();
userChoice = getUserInput(userInput);
printf("computer chose %d\n", compChoice); //for debugging
printf("you chose %d \n", userChoice);//for debugging
decision = pickWinner(userChoice, compChoice);
if (decision == 1)
{
playerWins++;
}
else if (decision == 2)
{
compWins++;
}
else if (decision == 3)
{
ties++;
}
}
printf("Final score is: \nPLAYER: %d \nCOMPUTER: %d \n", playerWins, compWins);
}
//generates a random number for computer, 1=rock 2= paper 3=scissors
int getComputerInput (int cpuInput)
{
srand(time(NULL));
int r = rand() %3 +1;
return r;
}
//prompts user for character input, then converts input into a number to return back to main
int getUserInput(userInput)
{
char playerPick ;
printf("Please choose R, P, or S. (Q for quit)\n");
playerPick = getchar();
switch(playerPick)
{
case 'R' | 'r':
printf("Player chose R. \n");
return 1;
break;
case 'p':
case 'P':
printf("Player chose P. \n");
return 2;
break;
case 's':
case 'S':
printf("Player chose S. \n");
return 3;
break;
case 'q':
case 'Q':
printf("player quit");
return 4;
break;
default:
printf("Invalid choice, choose again \n");
break;
}
}
//method for determining winner
int pickWinner(int player, int cpu)
{
if (player ==1 && cpu ==1)
{
printf("tie\n\n");
return 3;
}
else if (player==1 && cpu ==2)
{
printf("you lose, paper beats rock\n\n");
return 2;
}
else if (player ==1 && cpu ==3)
{
printf("you win, rock beats scissors\n\n");
return 1;
}
else if (player ==2 && cpu ==1)
{
printf("you win, paper beats rock\n\n");
return 1;
}
else if (player ==2 && cpu ==2)
{
printf("tie\n\n");
return 3;
}
else if (player ==2 && cpu ==3)
{
printf("you lose, scissors beats paper\n\n");
return 2;
}
else if (player ==3 && cpu ==1)
{
printf("you lose, rock beats scissors\n\n");
return 2;
}
else if (player ==3 && cpu ==2)
{
printf("you win, scissors beat paper\n\n");
return 1;
}
else if (player ==3 && cpu ==3)
{
printf("tie\n\n");
return 3;
}
}
Output:
it seems to be passing a zero back to the getUserInput method and I cant figure out why.
any hints in the right direction would be VASTLY appreciated.
apologies if this post is not formatted correctly.
thanks in advance
When you enter input, you end the input by pressing the Enter key. That key is actually placed into the input queue as a newline.
So when you read the first character, you will get the character entered (for example 'r'). However, the next character in the input queue is the newline, and that will be what the second call to getchar will give you.
There are ways to skip that. The simplest is simply doing an extra getchar call to discard the next character. However, if that's not the newline (for example if the user entered more than one letter as input) then that will not work.
Another possible solution is to use fgets to read a whole line, and the just get the first character from that line. The problem is if you don't provide a big enough buffer to store the line, you will have the same problem as before.
The only safe solution is to read the input from the user as a character. Then in a loop read until you get the newline character. The characters you read in the loop is simply discarded.
Perhaps something like this function:
void skip_past_newline(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF)
{
// Do nothing
}
}
Then just call it after you read the user input:
playerPick = getchar();
skip_past_newline();
Please do note a couple of things with the skip_past_newline function as presented above:
The variable that receives the result of getchar is an int variable. This is actually important.
I not only check for the newline in the loop, I also check for EOF. This indicates the used pressed the end-of-file key-combination (Ctrl-Z in the Windows console window) and that you should exit your program. This check is why you need to make the variable an int.
AFAICS, there are at least two problems with getUserInput()
When the user inputs an invalid choice, getUserInput returns without a value, because there is no loop around the code to ask again. I am pretty sure, the compiler warns about this.
To input a value, the user must enter a character and a newline. This is the character read the second time, which produces the output "invalid choice". To prevent this, you must skip the whitespace before reading the next input char.

C Booking Issues

typedef struct contact {
char firstname [40];
char lastname [40];
char address [100];
char phone[10];
}contact;
int main ()
{
FILE *pFile;
contact entry = {"", "", "", ""};
int choice;
char cont = 5;
pFile = fopen("C:\\contacts.txt", "w+");
if(!pFile){
printf("File could not be open");
return 1;
}
printf("Choose a selection\n\n");
printf("1. Enter First Name\n");
printf("2. Enter Last Name\n");
printf("3. Enter Address\n");
printf("4. Enter Phone Number\n\n");
scanf( "%d", &choice);
while (choice = 1|2|3|4|cont){
if (choice = 1){
printf ("First name: ");
fgets(entry.firstname, sizeof(entry.firstname),stdin);
}
else if(choice = 2){
printf ("Last name: ");
fgets(entry.lastname, sizeof(entry.lastname),stdin);
}
else if(choice = 3){
printf ("Address: ");
fgets(entry.address, sizeof(entry.address),stdin);
}
else if (choice = 4){
printf ("Phone number: ");
fgets(entry.phone, sizeof(entry.phone),stdin);
}
else
printf("Exiting");
break;
fwrite (&entry, sizeof (struct contact), 1, pFile);
printf ("Would you like to enter a new contact? (y/n)");
scanf ("%d", &cont);
if (cont = 'n'|'N')
return 0;
}
fclose(pFile);
getchar();
return 0;
}
is my code at the moment. Each time I give any option 1,2,3,4, put in a entry and press enter the window closes. I'm unsure if the logic makes sense and any suggestions are welcome but it "seems" okay to me but obviously I need another set of eyes. I want it where I don't have to enter all entries for every person I put in the file. Also, to note, I initially cont to 5 just because it was complaining.. bad practice I know. Any helpful information is appreciated
Your program ends because the break; isn't in the scope you think it is:
else if (choice = 4){
printf ("Phone number: ");
fgets(entry.phone, sizeof(entry.phone),stdin);
}
else
printf("Exiting");
break;
Even though you've indented the break, it doesn't belong to the else clause. So no matter what happens in the if/else block, the break gets executed and your program breaks out of the loop and ends.
To fix it, add braces to enclose the break inside the scope of the else.:
else if (choice = 4){
printf ("Phone number: ");
fgets(entry.phone, sizeof(entry.phone),stdin);
}
else
{
printf("Exiting");
break;
}
And once you fix that, this line will cause your program to terminate because it always evaluates to true and returns from main:
if (cont = 'n'|'N')
return 0;
You want that line to say
if (cont == 'n' || cont == 'N')
return 0;
These fixes will at least stop your program from terminating, but as others have pointed out there are numerous logical errors elsewhere that will prevent it from doing what you want.
For example, the following line:
while (choice = 1|2|3|4|cont){
belies a misunderstanding of some fundamental concepts.
First = is the assignment operator. The above code, among other things, changes the value of choice. Use == for equality comparison.
Second, the | operator is a bitwise or. The value of 1|2|3|4|5 is 7 (I'll leave it to you to figure out why sometime). Instead, use || like this:
while (choice == 1 || choice == 2 || choice == 3 || choice == 4 || choice == cont) {
There are other similar errors throughout your code.
A single = does assignment in C. if (a = 5) { /* always executed! */ } sets a to 5 and then executes the if-branch because a = 5 evaluates to 5 which is considered true.
You want == which compares values. Thus:
if (choice = 1){
Should be
if (choice == 1){
Another thing:
while (choice = 1|2|3|4|cont){
Does not do what you think it does. It's actually computing the bitwise or of 1, 2, 3, 4 and cont. (So just changing = to == wouldn't be sufficient.) You need to compare each value in turn:
while (choice == 1 || choice == 2 || choice == 3 || choice == 4 || choice == cont){
Also notice the use of || (logical OR) instead of bitwise or.
EDIT: The reason your program prematurely exits is because of the following:
else
printf("Exiting");
break;
You're missing curly braces ({ and }), so it actually means the following (despite misleading indention):
else
printf("Exiting");
break;
Your code probably has more errors.
By using if (choice = 1) you are saying "If I change choice to 1" which is virtually guaranteed to work, but it destroys the previous value choice held.
You want to start off with if (choice == 1) which means "If I compare choice to 2, is this equal?`.

Resources