Hi I'm making a simple Hangman game in C
I have a while Loop that is suppose to wait for the user to input a character. However, it skips pass that on the 2nd iteration.
void startGuessing(char *word){
char dummyWord[13];
strcpy(dummyWord, word);
int dummyWordLength = strlen(dummyWord);
for (size_t i = 0; i < dummyWordLength; i++)
{
dummyWord[i] = '_';
}
int remaindingChances = 7;
while(remaindingChances > 0){
printf("Player 2 has so far guessed: %s\n", dummyWord);
printf("Player 2, you have %d guesses remaining. Enter your next guess:\n", remaindingChances);
char guess;
guess = getchar();
int wordLength = strlen(word);
for (size_t i = 0; i < wordLength; i++)
{
if(guess == word[i]){
dummyWord[i] = word[i];
}
}
remaindingChances--;
}
}
The following is the output I'm seeing:
Player 2 has so far guessed: ___
Player 2, you have 7 guesses remaining. Enter your next guess:
c
Player 2 has so far guessed: c__
Player 2, you have 6 guesses remaining. Enter your next guess:
Player 2 has so far guessed: c__
Player 2, you have 5 guesses remaining. Enter your next guess:
Am i doing something wrong? O.o I can't seem to figure out this issue.
The simplest fix is probably to consume whitespace by replacing the guess = getchar() with something like:
int guess;
while( isspace(guess = getchar()) ) { ; }
(Note that getchar returns an int, and you should get in the habit of declaring the variable as an int.)
If you want to allow words that contain whitespace, you could use while( (guess = getchar()) != '\n' ) or similar. Whatever logic you want to use, you need to handle all the data, including the newlines. (and be aware of the possibility of \r\n on the input)
Consider using
scanf(" %c", &guess);
for your input.
You can implement further logic to to make sure the input is a letter, but this should fix your current problem
Related
I'm creating a "mad lib" program that scans in four strings input by the user to fill in the "blanks" on the mad lib template (replacing part of the underscores used as placeholders -- just for the length of the word and not replacing the whole thing). This is what I'm trying to replicate.
I have a function with printf and scanf statements that takes in the first 3 strings without issue, but after the 4th string is input, the program just keeps scanning, even after pressing "enter," until I end it. I want to be able to print the completed sentence directly under the 4th printf/scanf line after calling the function in main, but I don't know how to get the rest of the code to execute. Here is a screenshot of the problem I'm having.
Does anyone know what the issue is and how I can fix it?
Here is my code so far (I know I haven't completed the rest of the function after the printf/scanf statements, and I'm probably not doing this in the most efficient way to begin with, so any other tips would be greatly appreciated, but the program runs and I'd like to focus on this issue before I continue):
#include <stdio.h>
#include <string.h>
void create_madlib(char *pmls);
int main() {
char mls[] = "Star Wars is a ___________ _________ of _________ versus evil in a __________ far far away." ;
create_madlib(mls);
printf("%s\n", mls);
return 0;
}
void create_madlib(char *mls)
{
char pmls[9][18];
char word1[15];
//i15 - i25
char word2[15];
//i27 - i35
char word3[15];
//i40 - i48
char word4[15];
//i67 - i76
printf("Please enter word 1: ");
scanf("%s", word1);
printf("Please enter word 2: ");
scanf("%s", word2);
printf("Please enter word 3: ");
scanf("%s", word3);
printf("Please enter word 4: ");
scanf("%s", word4);
for (int i = 0; i < 90; i++)
{
for (int a = 0; a < strlen(word1); a++)
{
while (i >= 15 && i <= 25)
{
mls[i] = word1[a];
}
}
for (int b = 0; b < strlen(word2); b++)
{
while (i >= 27 && i <= 35)
{
mls[i] = word2[b];
}
break;
}
}
}
Thank you
I'm trying to print a string of chars from an array and end the loop whenever I press the "Enter" key.
int i;
char charArry[MAXARY];
printf("Input an array of chars: \n\n");
for (i = 0; i < MAXARY && charArry[i] != 13; i++)
{
scanf(" %c", &charArry[i]);
}
for (i = 0; i < MAXARY; i++)
{
printf(" %c", charArry[i]);
}
For some reason whenever I press the Enter key it just goes to a new line instead of breaking the loop. Any suggestions?
P.S
MAXARY is a constant for the array length, currently 20.
Your close to having this working. Whilst I agree the use of scanf should be avoided, see: Why does everyone say not to use scanf? What should I use instead?, the reason your program doesn't do what you expect is due to a logic error.
Your for loop states:
for (i = 0; i < MAXARY && charArry[i] != 13; i++)
Now recapping how a for loop works, you have:
1. initalization (i=0)
2. conditional check (i < MAXARY && charArry[i] != 13)
3. conditional block (scanf)
4. increment (i++)
5. return to 2
You'll note your charArray[i] != 13check is happening after i has been incremented. Hence your not checking against the character you just read but the next character in charArray[i]. This is why your never breaking your loop at the \r character.
A recommended fix would be:
for (i = 0; i < MAXARY; i++)
{
int result = scanf("%c", &charArry[i]);
if( result != 1 || charArry[i] == '\n' )
break;
}
Which checks scanf was successful and charArry when i is the character that was read.
Also note as chux has pointed out the \r character is a carrage return, not the newline. Hence this check will only work if your working on windows (as unix doesn't use \r). If you want to be platform independant use \n
For some reason whenever I press the Enter key it just goes to a new line instead of breaking the loop.
The space in the format scanf(" %c", &charArry[i]); directs scanf() to consume and discard all optional leading white-space. charArry[i] will never be assigned 13 as 13 is typically '\r', a white-space.
An enter key is usually translated to '\n'.
Do not test values that have not been assigned #Red Alert
// v---------v not assigned yet.
for (i = 0; i < MAXARY && charArry[i] != 13
Repaired code
int i;
char charArry[MAXARY];
printf("Input an array of chars: \n\n");
for (i = 0; i < MAXARY; i++) {
if (scanf("%c", &charArry[i]) != 1) break; // End of file or error occurred
// If enter key encountered
// Usualy the charArry[i] == '\r' is not needed.
if (charArry[i] == '\n' || charArry[i] == '\r') break;
}
// Only print out characters that were read.
int j;
for (j = 0; j < i; j++) {
printf("%c", charArry[j]);
}
I want the user to be asked "how many circles" they wanna write until the user decides to end it with (Ctrl+d) which is EOF?
extra question: if I write a letter for example "k" it will spam out circles. How do I change that?
#include <stdio.h>
int main ()
{
int i;
int x;
printf("\nHow many circles do you want to write?\n");
scanf("%d", &x);
while(x != EOF)
{
for (i = 1; i <= x; i = i + 1)
{
putchar('o');
}
printf("\nHow many circles do you want to write?"
"(to end program click ctrl+d at the same time!))\n");
scanf("%d", &x);
}
printf("\n\n Bye! \n\n");
return 0;
}
The biggest problem with your program is that scanf will not read an EOF into a variable. However, fixing just this problem is not going to make your program entirely correct, because there are other issues in your code:
Your code repeats itself - when possible, you should unify the code that deals with the first iteration vs. subsequent iterations.
Your code will not handle invalid input - when an end-user enters non-numeric data, your program goes into an infinite loop.
Your code follows the old style of C - declaring all variables at the top has not been required for more than fifteen years. You should declare your loop variable inside the loop.
Here is how you fix all these shortcomings:
int x;
for (;;) {
printf("\nHow many circles do you want to write? (to end the program click Ctrl+D at the same time!)\n");
int res = scanf("%d", &x);
if (res == EOF) break;
if (res == 1) {
... // Draw x circles here
} else {
printf("Invalid input is ignored.\n");
scanf("%*[^\n]");
}
}
printf("\n\n Bye! \n\n");
return 0;
As per the man page, scanf() will return EOF, not scan EOF to x as a value.
Return Value
These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs......
Also,
if I write a letter for example "k" it will spam out circles, how do I change that?
In case of input of one char value, it causes matching failure, in your case, scanf() returns 0, instead of 1.
So, altogether, you've to collect the return value of scanf() and check check that value for the required condition. You can change your code as
int retval = 0;
while ((retval = scanf("%d", &x))!= EOF && (retval == 1))
if you're allowed to #include , there are two convenient functions bool kbhit() and char getch().
So you can write
char c=0;
if(kbhit()) c = getch();
if(c== whatever code ctrl+d returns) x=EOF;
Hint: Take a look at what scanf(%d,&x) returns when you enter a letter instead of a number.
You can read char by char input :
#include <stdio.h>
int main ()
{
int i;
int x = 0;
int nb = 0;
while(x != EOF)
{
printf("\nHow many circles do you want to write?\n");
nb = 0;
for (x = getchar(); x != '\n'; x = getchar()) {
if (x == EOF)
goto end;
if (x >= '0' && x <= '9') {
nb = nb * 10 + x - '0';
}
}
for (i = 0; i < nb; i++)
{
putchar('o');
}
}
end:
printf("\n\n Bye! \n\n");
return 0;
}
I've looked at multiple solutions but none of them worked for me.
I'm asking the user to enter numbers in a loop, but if the user enters a specific number the loop should break.
This is what I've got so far.
#include <stdio.h>
#include <stdlib.h>
#define MAXNUMBERS 5
int getNumbers(int array[])
{
int i;
int n = 0;
printf("Enter max. %d numbers, enter empty line to end:\n", MAXNUMBERS);
for (i = 0; i < MAXNUMBERS; i++)
{
scanf("%d", &array[i]);
fflush(stdin);
n++;
if (array[i] == '5')
{
break;
}
}
return n;
}
int main()
{
int array[MAXNUMBERS];
int amount_numbers;
amount_numbers = getNumbers(array);
printf("Numbers entered: %d\n", amount_numbers);
printf("First three: %d %d %d", array[0], array[1], array[2]);
return 0;
}
Input:
1
5
4
3
2
Output:
Numbers entered: 5
First three: 1 5 4
If the user enters 5 the loop should break.
I'm using 5 as an example, I later want it to do with an empty line. But it doesn't even work with 5.
It just keeps prompting the user to enter another number after he entered 5.
The actual problem is '5' != 5 the former is the character 5 which is in fact it's ascii value, and the latter is the number 5, since you are reading integers, i.e. using the "%d" specifier in scanf() you should use 5, but it would be better if it was just a int variable, and you could initialize it to any number you like before the loop starts.
Your loop is wrong anyway because if the user enters a non-numeric value then your program will invoke undefined behavior. Besides you already invoke undefined behavior with fflush(stdin), so
Remove fflush(stdin)1
7.21.5.2 The fflush function
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is
undefined.
So the behavior is undefined for an input stream like stdin, or even if the most recent operation was input.
You must check that the value was read properly, and then check in the loop condition if it equals the value you want to stop the loop with, try this
int readNumber()
{
int value;
printf("input a number > ");
while (scanf("%d", &value) == 1)
{
int chr;
printf("\tinvalid input, try again...\n");
do { /* this, will do what you thought 'fflush' did */
chr = getchar();
} ((chr != EOF) && (chr != '\n'));
printf("input a number > ");
}
return value;
}
int getNumbers(int array[])
{
int i;
int stop = 5;
printf("Enter max. %d numbers, enter empty line to end:\n", MAXNUMBERS);
array[0] = 0;
for (i = 0 ; ((i < MAXNUMBERS) || (array[i] == stop)) ; i++)
array[i] = readNumber();
return i;
}
1This is a quote from the C11 draft 1570.
if (array[i] == '5')
You're checking whether array[i] is equal to the ASCII value of the character '5'.
Remove the '' to make it compare against the integer 5.
You are checking if an integer is equal to the character '5', which is then being cast to an ascii value of '5'.
Try using this:
if (array[i] == 5)
Disregard everything!
I should have written
if (array[i] == 5)
without the quotes!
I'm an idiot!
I sat 2 hours at this error...
Newbie to C language and I'm trying to make a hangman game. I have the following code:
int main(void) {
char userResponse;//This is the response from the user on rather they want to continue or not.
do {
startGame();
printf("Do you want to continue (y or n): ");
scanf("%c", &userResponse);
} while(userResponse == 'y');
return 0;
}
int startGame(void) {
int num_letters = 0; //length of word array
int count = 0;
int tries = 0; //total tries player has used
int correctGuesses = 0; //number of correct guesses
int correctLetter = 0; //flag to check if the letter guessed was correct.
int repeatLetter = 0; //flag to check if the letter guessed was already guessed before.
int randomWord = 1+(rand()%6); //setting a variable that will pick a word from the word array at random.
char word[] = {"spot", "physicist", "penny", "klingon", "bazinga", "continuum"}; // should these be all lower char or does it matter?
char guess;
char incorrectGuesses[5] = " "; // all the incorrect letters chosen by the player will be stored in this array.
char gameWord[num_letters]; //starts to fill out the word as the player guesses correctly
srand(time(NULL)); // Don't really understand this line but the interweb said I needed it. Can you tell me why?
num_letters = strlen(word);
gameWord[num_letters] = '\0';
//This will show the player what letter they have typed incorrectly.
for(count = 0; count < num_letters; count++)
gameWord[count] = '-'; // This will display the length of the word represented with a "-".
printf("Welcome to Big Bang Hangman!\n\n");
printf("Time to guess the word!");
draw_hangman(tries);
while(tries < NUM_TRIES_ALLOWED) { //Player only gets 7 guesses. Found this on the interweb.
printf("Here is your word: %s\n", gameWord);
printf("Incorrect Letters: %s\n", incorrectGuesses);
printf("\nGuess a letter (and press 'Enter'): ");
fgets(&guess, sizeof(guess), stdin);
//This compares the current guess with the previous guesses so that you won't affect a turn if you pick the same incorrect letter.
for(count = 0; count < num_letters; count++)
if(guess == gameWord[count] || guess == incorrectGuesses[count]) { // If the player guess is equal to the size of the word or if its equal to the
repeatLetter = 1;
correctLetter = 1;
break;
}
if(repeatLetter == 0) // setting the flag back to 0 tells the compiler the game is over.
//Checks for matches in string
for(count = 0; count < num_letters; count++) {
if(guess == word[count]) { // can't understand why I'm getting this warrning.
gameWord[count] = guess;
correctGuesses++;
//if (correctGuesses == count) {
//printf("\n\nCONGRATULATIONS! You guessed the word %s!", gameWord);
//exit(0);
//}
if(correctGuesses == num_letters) {
printf("\n\nCONGRATULATIONS! You guessed the word %s!", gameWord);
exit(0);
}
correctLetter = 1;
}
}
if(correctLetter == 0) {
incorrectGuesses[tries] = guess;
tries++;
}
// reset both flags
repeatLetter = 0;
correctLetter = 0;
//startGame(); // Start the game over when the flag is reset.
}
printf("Sorry but you did not guess the word.\n");
printf("The word is: %s\n\n", gameWord);
return 0;
}
It is outputting the following:
Welcome to Big Bang Hangman!
Time to guess the word!
___
|
|
|
|
|
---
Here is your word: ----
Incorrect Letters:
Guess a letter (and press 'Enter'): Here is your word: ----
Incorrect Letters:
The last two lines continue on forever until I stop it. I'm completely lost.
Any advice would be great.
You have multiple (and I really mean that) problems in your code. But lets just pick one
char guess;
fgets(&guess, sizeof(guess), stdin);
is not the correct way to get the user to enter a letter. Maybe
scanf("%c", &guess);
would work better for you.
But really your approach is all wrong. Start again, write a few lines of code, get them working and then write a few more. You've written loads of code, lots of which is wrong. That's not a productive way to program.