the loop in magic 8 ball has a bug - c

I'm trying to make a Magic 8 Ball program but my loop has a bug.
If you play again, the loop messes up and behaves like you were hitting enter all the time for about three cycles until it will work again.
Also, there is a delay when you enter you question. You have to hit enter twice to get the answer.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
void ans(int x);
int main()
{
system("color 0A");
srand(time(0));
int num,i;
do{
char question[100] = {" "};
num = rand()%10;
puts("MAGIC 8 BALL!");
puts("Press Enter When Ready.");
getch();
system("cls");
puts("Input Yes or No questions only!");
printf("\n");
scanf("%s",&question);
getch();
printf("\nTHE ANSWER | ");
ans(num);
getch();
system("cls");
printf("Press any key to try again.\nPress [x] to Exit.");
if(getch()=='x'){
system("cls");
break;
}
system("cls");
}while(1);
}
void ans(int x){
switch(x){
case 1 : printf("YES!");break;
case 2 : printf("NO!");break;
case 3 : printf("It's a thumbs down.");break;
case 4 : printf("Positive!");break;
case 5 : printf("As I see it Yes.");break;
case 6 : printf("Certainly!");break;
case 7 : printf("Negative!");break;
case 8 : printf("Don't Count on it.");break;
case 9 : printf("You don't want to know, trust me.");break;
case 10: printf("I can't say right now.");break;
default : printf("Cannot be determined right now");break;
}
}

Fixed your problem. Added comments explaining. Hopefully I caught everything. Tested the program, and it works fine now.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <string.h>
//#include <unistd.h>
#define MAX_QUESTION 1000
#define STATEMENT_AMOUNT 10
int random_num_generator();
void statement_picker(int x);
int main(void) {
char temp;
int rand;
// Your while condition really just needs to be scanning 1 character.
// No point in scanning the entire string, because we don't even use the string
// The scanning jus tells us when to start the loop again
while (1) {
// The introduction of our program
system("cls");
printf("MAGIC 8 BALL!\n");
printf("Press Enter When Ready.\n");
getch();
// Asking user to enter in their question
system("cls");
printf("What is your question?\n");
printf("Only enter yes or no questions!\n");
// You have to flush (aka clear) stdin. Because it uses your previous inputs
// automatically. For example, if you type "I am the best?". The program will not work
// properly for num_of_words - 1 iterations. So 4 - 1. Will not work properly for
// 3 iterations
// Also you don't need to scan in the word, because we don't really care what question
// the user typed. You can save some memory by only scanning in a single character.
// We only use scanf to give a real magic 8 ball experience by stopping and waiting
// for the user to type their question.
scanf("%c", &temp);
fflush(stdin);
// Generating a random number
printf("The answer you seek: ");
rand = random_num_generator();
statement_picker(rand);
// So I noticed here you cls, but you cls without waiting. This the user won't
// be able to read your answer in time. So you should cls after you ask the user
// to quit, or have a timer. Commented a timber for you below. You also need to
// include the unistd.h library to use the sleep function. Just uncomment it
// in the #includes section if you want the timer.
// sleep(10);
// system("cls");
// Asking the user if they want to try again
printf("Would you like to ask another question?\n");
printf("Press [x] to quit\n");
printf("Press any other character to continue\n");
scanf("%c", &temp);
if (temp == 'x') break;
// Flush at the end too, just in case the person types multiple things rather than
// one characters
fflush(stdin);
}
system("cls");
return 0;
}
// Generates a random number between 0 - 10.
/* I noticed in your switch statement you start at case 1. You should start at case 0,
* because you are using the modulus operator Just for example, if rand generators 30 and
* you have 10 cases you will be doing (30 % 10) which is equal to 0 because 10 goes into 10,
* 3 times with no remainders If you really want to start your switch case at 1,
* then you have to plus one to the return value in random_num_generator
*/
int random_num_generator() {
time_t t;
srand((unsigned) time(&t));
return rand() % STATEMENT_AMOUNT;
}
// Picks a statement and prints it, depending on the value of x
void statement_picker(int x){
switch(x){
// Your case should start at 0, not 1 because you will never print out case 0
// the way you had it before.
case 0 : printf("YES!\n");break;
case 1 : printf("NO!\n");break;
case 2 : printf("It's a thumbs down.\n");break;
case 3 : printf("Positive!\n");break;
case 4 : printf("As I see it Yes.\n");break;
case 5 : printf("Certainly!\n");break;
case 6 : printf("Negative!\n");break;
case 7 : printf("Don't Count on it.\n");break;
case 8 : printf("You don't want to know, trust me.\n");break;
case 9 : printf("I can't say right now.\n");break;
// No need for default because you'll never get to it
// (just because of how we implemented this software)
// default : printf("Cannot be determined right now");break;
}
}

You may try this
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void ans(int x);
int main()
{
srand(time(0));
int num,i;
do{
num = rand()%10;
char question[1000];
puts("MAGIC 8 BALL!");
puts("Press Enter When Ready.");
puts("Input Yes or No questions only!\n");
scanf("%s",question);
printf("\nTHE ANSWER | ");
ans(num);
printf("\n\n");
printf("Press any key to try again.\nPress [x] to Exit.\n\n");
char c = getchar();
c=getchar();
if(c=='x'){
break;
}
}while(1);
}
void ans(int x){
switch(x){
case 1 : printf("YES!");break;
case 2 : printf("NO!");break;
case 3 : printf("It's a thumbs down.");break;
case 4 : printf("Positive!");break;
case 5 : printf("As I see it Yes.");break;
case 6 : printf("Certainly!");break;
case 7 : printf("Negative!");break;
case 8 : printf("Don't Count on it.");break;
case 9 : printf("You don't want to know, trust me.");break;
case 10: printf("I can't say right now.");break;
default : printf("Cannot be determined right now");break;
}
}

Related

C code Calculations not outputting correctly after adding exit for program

Hey guys n gals first time poster first time learning code.
I am sure I am missing something very small that comes naturally when you stare at code long enough. Why are my calculations not working? what am I missing ?
I can get it working without implelemting the # exit but im sure im missing something here.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char input;
int a,b,c;
while(1) {
printf("\nPlease Enter Temperature in kelvin \n\nThen enter # when you have had enough:\n ");
scanf(" %c", &input);
if(input == '#'){
break;
}
if(input != '#') {
scanf("%d",&c);
printf("\n1.Convert to celcius\n2.Convert to fahrenheit\nEnter choice now\n");
scanf("%d",&a);
switch(a) {
case 1:
b=(c-273);
printf("Temperature in celcius is %d\n\n",b);
break;
case 2:
b=((c*9)/5)-460;
printf("Temperature in fahrenheit is %d\n\n",b);
break;
default:
printf("You selected wrong choice");
break; /// End of code here
}
}
getchar ();
}
return 0;
}
the following proposed code:
appropriately horizontal spaced
appropriately vertically spaced
includes the suggested changes from the comments to the question
displays how to cleanly display menu
displays how to honor the right margin (column 72 or 80)
replaces 'magic' numbers with meaningful names
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#define CONVERT_KEVIN_TO_CELCIUS 273
#define OFFSET_KEVIN_TO_FAREN 460
int main( void )
{
char input;
int a,b,c;
while(1)
{
printf("%s",
"\nPlease Enter Temperature in kelvin"
"\n\nThen enter # when you have had enough:\n");
scanf(" %c", &input);
if(input == '#')
{
break;
}
ungetc( c, stdin );
scanf("%d",&c);
printf("%s",
"\n1.Convert to celcius"
"\n2.Convert to fahrenheit"
"\nEnter choice now\n");
scanf("%d",&a);
switch(a)
{
case 1:
b=(c-CONVERT_KEVIN_TO_CELCIUS);
printf("Temperature in celcius is %d\n\n",b);
break;
case 2:
b=((c*9)/5)-OFFSET_KEVIN_TO_FAREN;
printf("Temperature in fahrenheit is %d\n\n",b);
break;
default:
printf("You selected wrong choice");
break;
}
}
getchar ();
return 0;
}
Why are my calculations not working?
Code has various technical problem well addressed elsewhere.
Thought I'd mention some numeric issues.
To convert K to °F:
°C = 0K − 273.15
°F = °C×9/5 + 32
To do so with integer math and get the best answer
// (K − 273.15)×9/5 + 32
// (K*100 − 27315)×9/(5*100) + 32
// ((K*100 − 27315)×9 + 32×500)/500
// ((K*100 − 27315)×18 + 32×1000)/1000
// above using real math, below using integer C math
// t = (K*100 − 27315)×18 + 32×1000; (t + signof(t)*500)/1000
// More simplifications possible
int t = (K*100 - 27315) * 18 + 32*1000;
t += (t < 0) ? -500 : 500; // round by adding half the divisor, correctly signed
F = t/1000;
To do so with FP math and get a good integer answer
#include <math.h>
F = lround((K − 273.15)*9.0/5.0 + 32);

I can not get the loop to cycle 20 times and ask for a number between 1 and 6. Can anyone see what I have coded wrong?

I am trying to ask for 20 integers and count when then number 2 and 5 are selected with a static variable. This is what I can up with using code blocks. it is not asking for 20 number only 1.
#include <stdio.h>
#include <stdlib.h>
int totalCount2(int ); \*this is where i added the function call*\
int totalCount5(int );
void output( int, int);
int main()
{
int count2;
int count5;
int yourNumber;
int yourNumberCounter;
yourNumberCounter = 1;
count2 =0;
count5 =0;
printf("Please enter a number between 1 and 6.\n");
scanf("%d", &yourNumber);
while(yourNumberCounter<= 20)
{
if(yourNumber ==2){
totalCount2(count2);
break;
}
else if(yourNumber ==5){
totalCount5(count5);
break;
}
else if(yourNumber <= 6 || yourNumber >=1){
yourNumberCounter = yourNumberCounter +1;
}
else if(yourNumber >6 || yourNumber <6){
printf("You have to choose a number between 1 and 6. try again");
}
}
return 0;
}
int totalCount2(int count2){
static int count2only;
count2only = count2++;
return count2only;
}
int totalCount5(int count5){
static int count5only;
count5only += count5;
return count5only;
}
void output(count2, count5){
printf("Out of the 20 numbers you input. You entered the number two %d times\n You entered the number five %d times\n", count2, count5);
return;
}
I am not sure if I am using static variables count2 and count5 correctly. I am studying from a book and think maybe someone sees something I am doing wrong.
printf("Please enter a number between 1 and 6.\n");
scanf("%d", &yourNumber);
while(yourNumberCounter<= 20)
is outside of the loop
should be
while(yourNumberCounter<= 20){
printf("Please enter a number between 1 and 6.\n");
scanf("%d", &yourNumber);
The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.
delete all the breaks.
also learn to use the debugger.
google: "how to debug c code" and the name of your IDE - the program you write code with.

Returning integer array values from a function in c

I am really struggling on an assignment i have. I have searched the internet and youtube but i am still none the wiser.
The program will have 5 functions in total, but i am stuck on the first. The program should use a 1-D array to read a 4 digit code(must be 4 single digit numbers) entered by the user. My problem arises when i am trying to return that code from the function. All i am getting is the first number. I am aware that you cannot return an array from a function in c and that you have to use pass by reference, this is where i have a problem i do not completely understand how to do this. my code is below along with the output i recieve.
Any help you can give me would be much appreciated, as ive said before i am really struggling.
//program to enter a code and return the code to main
#include <stdio.h>
#include <stdlib.h>
#define CODE 4
//function prototypes
int enter_code(int* code_arr);
main()
{
int code =0;
int option;
int exit1=0;
do
{
//print the menu on screen
printf("\t \t \t1 - Enter the access code\n");
printf("\t \t \t2 - Encrypt code and verify\n");
printf("\t \t \t3 - Exit the program \n");
scanf("%d",& option);
switch(option)
{
case 1:
{
//call enter_code function
code= enter_code(&code);
printf("\n The returned code is %d \n",code);
break;
}
case 2:
{
break;
}
case 3:
{
// prompt user to a key to exit
printf("\n You choose to exit the program.\n Press a key to exit\n ");
getchar();
exit(0);
break;
}
default:
{
printf("You must enter a number between 1-5\n");
}
}
}//end do()
while(exit1!=5 & exit1 <6);
}//end main
int enter_code (int* code_arr)
{
int password[CODE];
int i;
printf("Enter your 4 digit code \n");
for(i=0;i<CODE;i++)
{
scanf("%d",&password[i]);
}
printf("The code entered is:");
for(i=0;i<CODE;i++)
{
printf("%d",password[i]);
}
return(*password); //how do i return the full array
}
Your function can return the code through the array passed as an argument, and use the function return value to indicate an error. You can pass that to another function too. Your simplified code:
#include <stdio.h>
#include <stdlib.h>
#define CODE 4
int enter_code (int* code_arr)
{
int i;
printf("Enter your 4 digit code\n");
for(i=0;i<CODE;i++)
if (scanf("%d", &code_arr[i]) != 1)
return 0;
return 1;
}
int check_code (int* pass_code, int* user_code)
{
int i;
for(i=0;i<CODE;i++)
if (pass_code[i] != user_code[i])
return 0;
return 1;
}
int main(void)
{
int password[CODE] = {0}, passOK[CODE] = {42,24,0,12345678};
if (!enter_code(password))
printf ("Bad password entry\n");
else {
if (check_code(passOK, password))
printf("You unlocked the vault\n");
else
printf("You don't know the passcode\n");
}
return 0;
}
Program output:
Enter your 4 digit code
42
24
0
12345678
You unlocked the vault

Stored data gets corrupted in C

i'm learning myself programming in c witch basicly no previous programming experience and now i have a weird bug and would like to ask some advice.
In the program flow some of the input data gets suddenly changed and i can't see nor reason why that happens.
1.program starts -> user gets a menu choice -> selects case 1 -> program provides and additional input posiblity.... So far everything works correctly as i could see in debug mode.
2.The user puts in some numbers and the variable gets set to that number.
(this happens in input.c)
3.Then the program continues in main.c to info_bottom().
(in circlemenu.c)
4.In there the function getRadius() gets called that should calculate a radius based on the user input set in input.c in point 2.
5.That calculation function is located in circlefunctions.c
But here/there is the strange thing.
If i look in the debugger, i see that the variable diameter and radius are both changed to some weird numbers and not the number that the user specified in point 2.
Somehow the data stored in the pointer gets corrupted as far as i can judge.
Unfortunately im still to inexperienced with debugging to find this out on my own so hopefully someone can please tell me what is going on.
This problem occured while trying to get rid of all global variables in my program.
Im beginning to get a whole new respect and understanding for professional programmers and why it can take so long sometimes to fix bugs o0.
(i also made the corresponding header files but no need to put them up i think?)
main.c
#include <stdio.h>
#include "menu/menu.h"
#include "circle/circlemenu.h"
#include "input/input.h"
int main(void)
{
while(1)
{
menu();
switch(menu_user_input())
{
case 1:
info_top();
cir_user_input();
info_bottom();
break;
case 2:
system("cls");
break;
case 3:
system("cls");
break;
case 8:
system("cls");
break;
case 9:
system("cls");
break;
case 0:
return(0);
default:
system("cls");
printf("\n **Wrong choice try again...**\n");
break;
}
}
return 0;
}
menu.c
#include <stdio.h>
#include "menu.h"
void menu()
{
printf(" \n Made by ************* 2015.\n");
printf(" ----------------------------------------\n\n");
printf(" 1. Calculate circle measurements. \n");
printf(" 2. \n");
printf(" 3. \n");
printf(" 8. Info. \n");
printf(" 9. Clear screen. \n");
printf(" 0. Exit. \n \n");
printf(" Make your choice and press enter: ");
}
input.c
#include <stdio.h>
#include "input.h"
int menu_user_input()
{
static int number;
scanf(" %i", &number);
return number;
}
float cir_user_input()
{
static float diameter;
scanf("%f", &diameter);
return diameter;
}
circlemenu.c
#include <stdio.h>
#include "circlemenu.h"
#include "circlefunctions.h"
void info_top()
{
system("cls");
printf(" ----------------------------------------\n");
printf(" Typ the diameter of the circle: ");
return;
}
void info_bottom()
{
printf(" ----------------------------------------\n");
printf(" The radius = %f \n\n" , getRadius());
printf(" The surface = %f \n\n" , getSurface());
printf(" The outline = %f \n" , getOutline());
printf(" ----------------------------------------\n");
return;
}
circlefunctions.c
#include "circlefunctions.h"
#include "../input/input.h"
#define PI 3.14
double getRadius()
{
static diameter = (*cir_user_input);
double radius = diameter / 2;
return radius;
}
double getSurface()
{
double radius = getRadius();
return PI * (radius * radius);
}
double getOutline(){
double radius = getRadius();
return 2 * PI * radius;
}
You are using your cir_user_input in your getRadiusfunction like a variable/pointer, although it is a function. It is surprising that this works without any warnings or errors (would be interesting to know what compiler you are using).
I think what you actually intended was something like this, i.e., a call to cir_user_input which stores the result in a float variable.
double getRadius()
{
float diameter = cir_user_input(); //float type; not static (see below)
double radius = diameter / 2;
return radius;
}
Furthermore, the switch statement in your main function only calls the user input function cir_user_input, but none of the calculation routines (case 1). Since the return value of the function is not store, it cannot be used later.
In addition, you have seem to be confused about the use of the static key word:
This problem occured while trying to get rid of all global variables in my program.
When you use the static key word to declare variables inside a function, they retain their values throughout function calls, i.e., they are effectively global.
Conversely, if you use the static key word for a global variable/function etc., it is only visible inside the file you specified it in. For beginners, this is often confusing since the key word is written in exactly the same way, see What does "static" mean?.
Best regards
Andreas
here is a good implementation of the main() function
#include <stdio.h>
#include "menu/menu.h"
#include "circle/circlemenu.h"
#include "input/input.h"
int main(void)
{
int done = 0;
while( !done )
{
menu();
switch(menu_user_input())
{
case 0:
done = 1;
break;
case 1:
info_top();
cir_user_input();
info_bottom();
break;
case 2:
system("cls");
break;
case 3:
system("cls");
break;
case 8:
system("cls");
break;
case 9:
system("cls");
break;
default:
system("cls");
printf("\n **Wrong choice try again...**\n");
break;
} // end switch
} // end while
return 0;
} // end function: main

Bug in a simplified (and incomplete) version of hangman game

I have written a first version of hangman. The game will be completed later, when this part of code will work.
The code:
#include <stdio.h>
#include <conio.h>
int main()
{
char word[]={"name"};
char word0[]={"----"};
char lett;
int i;
int c;
int e=0;
while(e<12)
{
gotoxy(2,2);
printf("\n%s\n",word0);
scanf("%c",&lett);
for(i=0,c=0;i<4;i++)
{
if(lett==word[i])
{
word0[i]=word[i];
c++;
}
}
printf("%d",c);
if(c==0)
{
e++;
printf("%d",e);
}
}
printf("You lose");
getchar();
}
The program ends before I make 12 errors and prints two values per cycle (not 1, which it should do) which don't coincide with the actual number of errors. Why?
The second 'cycle', as you call it, is reading the newline character. Try changing your scanf to this:
scanf("%c\n",&lett);
The second entry you get is the new line when you press, says, "a", then "Enter". The "Enter" is a new char which is then processed by your program.
Instead of using scanf("%c",&lett);, use scanf(" %c",&lett); (with a space before the '%' => this will ignore any spaces, new lines, etc.
Some minor changes make the code work.
Note that I had to change the I/O a bit (don't have gotoxy() function, and no interactive input since I was running this on codepad.org). See where the logic of your code is different and you should have your solution.
I added intermediate printf statements so you can follow the flow more clearly - usually a good idea when you are debugging.
Note - you might want to use case insensitive string comparison...
#include <stdio.h>
#include <string.h>
int main()
{
char word[]="name";
char word0[]="----";
char guess[]="bnexacdfm";
char lett;
int i;
int c;
int e=0;
int gi = 0;
while(e<12 && gi < strlen(guess))
{
// gotoxy(2,2);
printf("\n%s\n",word0);
lett = guess[gi++];
printf("you guessed: %c\n", lett);
// scanf("%c",&lett);
for(i=0,c=0;i<4;i++)
{
if(lett==word[i]) // really want case insensitive comparison here
{
word0[i]=word[i];
printf("found %c at position %d\n", lett, i);
c++;
}
}
printf("Number correct in this guess: %d\n",c);
if(c==0)
{
e++;
printf("Total number of incorrect guesses: %d\n",e);
}
}
if(strcmp(word, word0)==0) {
printf("well done! you win\n");
}
else {
printf("Sorry - you lose\n");
}
return 0;
// getchar();
}
Output:
----
you guessed: b
Number correct in this guess: 0
Total number of incorrect guesses: 1
----
you guessed: n
found n at position 0
Number correct in this guess: 1
n---
you guessed: e
found e at position 3
Number correct in this guess: 1
n--e
you guessed: x
Number correct in this guess: 0
Total number of incorrect guesses: 2
n--e
you guessed: a
found a at position 1
Number correct in this guess: 1
na-e
you guessed: c
Number correct in this guess: 0
Total number of incorrect guesses: 3
na-e
you guessed: d
Number correct in this guess: 0
Total number of incorrect guesses: 4
na-e
you guessed: f
Number correct in this guess: 0
Total number of incorrect guesses: 5
na-e
you guessed: m
found m at position 2
Number correct in this guess: 1
well done! you win
Link to code sample: http://codepad.org/56dC0stD

Resources