I am having a problem with this function (part of a Battleship game) where it will run through it once perfectly fine, but in subsequent executions, it skips:
scanf("%c",&rChar);
For some reason, rChar turns into another value without user input from above code.
I have tried putting in printf statements showing the value of rChar all throughout the function.
The function Conv_rChar_Int() converts the Char the user inputs into an integer value. But because rChar isn't being passed around as a pointer, the value of rChar remains the same throughout until the user replaces it on the next iteration. (Verified yet again with printf). The weird thing is, it changes right in between these lines of code. and never prompts the user for rChar.
printf("please enter the row you want to place your %d ship in\n",length);
scanf("%c",&rChar);
Remember, it only happens AFTER the first time. Even if I reinitialize the variables rChar, r, c, and dir after every iteration, this problem still happens.
I am 99% certain the problem is within this function and not in any of the functions that gets called within it (because rChar remains the same after every single line except between the 2 lines above).
Thanks for help in advance. If you have any questions about the code I'll try to explain it more.
int Gen_Ship_Place(int length, int flag3, int PlayGrid[10][10]){
int ShipPlaceFlag = 0;
//coordinates and direction
int r;
char rChar;
int c;
int dir;
//this loops until a ship location is found
while(ShipPlaceFlag == 0)
{
//enters row
printf("please enter the row you want to place your %d ship in\n",length);
scanf("%c",&rChar);
r = Conv_rChar_Int(rChar);
//adjusts row
r--;
//enter column
printf("please enter the column you want to place your %d ship in\n",length);
scanf("%d",&c);
//adjust column
c--;
//enter direction
printf("please enter the direction you want your %d ship to go\nwith\n0 being north\n1 being east\n2 being south\n3 being west\n",length);
scanf("%d",&dir);
//checks ship placement
ShipPlaceFlag = Check_Ship_Place(length,dir,flag3,r,c,PlayGrid);
//tells player if the location is wrong or not
if(ShipPlaceFlag == 0)
{
printf("****the location and direction you have chosen is invalid please choose different coordinates, here is your current board*****\n\n");
}
else
{
printf("****great job, here is your current board*****\n\n");
}
//prints grid so player can check it for their next move
Print_Play_Grid(PlayGrid);
}
Your program prints this prompt:
please enter the row you want to place your 2 ship in
and calls scanf. You type 5 and press return. You have typed in two characters: the 5 and a newline character \n. (Or maybe it's \r on Windows.) That newline character sits in the input buffer until the next call to scanf, which reads the newline character and returns right away without you needing to enter more input.
You can make scanf skip past newlines (and other whitespace) when reading a single character by putting a space before the %c specifier, like this:
scanf(" %c", &c);
When the user presses enter, that is also a character which will be in the input buffer. You'll need to read past that.
//prints grid so player can check it for their next move
Print_Play_Grid(PlayGrid);
while (fgetc(stdin)!='\n') { }
Related
#include<stdio.h>
#include<conio.h>
int main()
{
int Dividend,divisor;
printf("Checking Divisiblity of 1st number with 2nd number \n\n") ;
printf("Enter Number \n") ;
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
if(Dividend % divisor == 0)
{
printf("Number %d is divisible by %d",Dividend,divisor) ;
}
else
{
printf("Number %d is not divisible by %d",Dividend,divisor) ;
}
getch();
return 0;
}
Above is my code that i have written in C ;
on running this program . Only on first execution of scanf function if i give two input space seperated , the second input is going on right variable . and on hitting enter i am getting result . I am not understanding how is this happing .
When space is pressed, scanf doesn't see anything yet. Something happens only after enter is pressed. It then takes everything to the left of the space character and assigns it to the first variable, and everything to the right of the space character and assigns it to the second variable.
If you don't press the spacebar, scanf will interpret everything you type as a single number and will assign it to the first variable.
Instead what you may want to do is use the %c format specifier to read a single character at a time. You can then check if the character is a space character and if it is, you can break out of the loop. Otherwise, you can keep reading characters until you reach a space character.
stdin is line based by default. Your program gets nothing until you press enter. Then your program has the entire line of text available.
Result of this is, that scanf, getchar, fgets, etc calls will not return until you press enter. After enter press, entire line is available and the function starts to process it.
scanf is kinda special, that if you have int parsed_count = scanf("%d%d", &a, &b);, it will read two integers, no matter how many times you press enter, so you can either do
1 2<enter>
Or you can do
<enter>
1<enter>
<enter>
2<enter>
and scanf will still read these two integers (it returns early if there is parse error, which is why you need to check the return value!).
And vice versa, if there is already input available, then scanf may return immediately, so if you have this code
scanf("%d",&Dividend);
printf("Enter Divisor = ");
scanf("%d",&divisor) ;
and enter text
1 2<enter>
Then first scanf will wait for enter press, then consume the first integer, leaving 2<enter> still unread. Then there's print, and then 2nd scanf starts reading, skipping the whitespace and immediately getting 2nd integer. So you see
1 2 <- this is your typing echoed, not print from your program
Enter Divisor = <- printf printed this
If you want to take only one input per enter press, you can simply read characters until newline, because scanf leaves them there. Example loop to read until newline, or exit program at end of file/error:
while(true) {
int ch = getchar();
if (ch == EOF) exit(1);
if (ch == '\n') break;
}
fairly new programmer here just trying to understand if there is a better way to do this and hoping to get some feedback.
TL;DR: Is there a better way to clear stdin when looking for a specific input?
For some background, I've been learning C for the past 3 weeks and scanf() has been our "go to" function for user input. After looking around for answers to this question, I'm beginning to learn that scanf() is not always preferred.
In this part of the assignment that I'm working on, I created this while loop that is supposed to run while the user input is a nonzero, positive integer. It took a while, but to get to this point I now understand that if a string is inputted instead of an integer when scanf("%d", &variable); is assigned while using leads to an infinite loop as stdin does not get cleared.
I tried to solve this problem by checking to see the return of the scanf() functions, and running the loop while the return is equal or less than 0 (which would mean that the scanf() function broke and did not return anything since it saw a char instead of an int).
The thing is, the code seems to work great until we encounter one scenario, which is where we have characters followed by an integer.
For example:
Input = 1
program runs with no issues
Input = string
program runs loop, asks for new valid input
Input = string string
program runs loop, asks for new valid input
Input = 123string
program proceeds, but then next loop with an int scanf() is infinite. 123 is stored as an int to variable.
My current understanding of the issue is that scanf() reads the integers until we get to the characters and then "string\n" gets stored to stdin, creating an infinite loop in the next part. To solve the issue, I added a fflush(stdin); before the next integer scanf() loop which seems to work.
So my question is: Would somebody be willing to show me some other ways to do this other than adding a fflush(stdin); line before every int scanf() loop? I'm sure there are better ways but I don't rightly know who to ask and the internet seemed like a good resource. Thank you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int squareLen = 0;
int numColors = 0;
int infiniteLoopStop;
// Asks for user input of desired Square Length
printf("Please enter the finished side length (in inches) of one square.\n> ");
while (squareLen < 1) {
infiniteLoopStop = scanf("%d", &squareLen);
if (infiniteLoopStop <= 0 || squareLen < 1) {
printf("\nInvalid input. Enter a nonzero, positive integer.\n> ");
fflush(stdin);
}
}
// Temporary solution to problem
fflush(stdin);
// Asks for int input of colors and loops while number of colors is not 2 or 3
printf("How many colors are you using? Enter 2 or 3.\n> ");
while (numColors < 2 || numColors > 3) {
infiniteLoopStop = scanf("%d", &numColors);
if (infiniteLoopStop <= 0 || numColors < 2 || numColors > 3) {
printf("Invalid, please enter 2 or 3.\n> ");
fflush(stdin);
}
}
printf("\n");
return 0;
}
First off I want to mention that I´m completely new to programming, I started my first course this week. This problem seems odd however, here´s my code in C calculating the area of a triangle:
#include <stdio.h>
int main(void) {
double base, height;
printf("Type the base of the triangle\n");
scanf("%lf\n", &base);
printf("Type the height of the triangle\n");
scanf("%lf\n", &height);
printf("Here is the area of the triangle: %.2lf\n", (base * height) / 2);
return 0;
}
It looks alright to me, however in the terminal I get the following result:
The terminal doesn´t "let me" continue to the next scanf unless I type in another number and press return. The value I choose for the height variable doesn´t matter aswell, as the result is (55)/2 instead of (56)/2. It ignores the value '6' and instead uses the second '5' that I typed in under "Type the base of the triangle".
Is anyone familiar with what the problem might be? I´m using MacOS High Sierra, if there are any more details required please let me know, and I appreciate any help I can get!
Let me start by urging you to read this article to know why you shouldn't use scanf and also how you should use it, in case you end up using it anyway:
http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
Now, putting \n in a scanf format string does not mean to expect a newline, but to read and discard any number of whitespace characters. Since %lf already discards leading whitespace, you don't need explicit whitespace in the format string anyway.
The \n in your case causes scanf to read characters until it finds a non-whitespace character, and it may need to read another line before it can find that non-whitespace character. This is why you are 'forced' to input another number (or any non-whitepace) before the code lets you move on. The fix here is just to use %lf, without the \n.
#include <stdio.h>
int main(void) {
double base, height;
printf("Type the base of the triangle\n");
scanf("%lf", &base);
printf("Type the height of the triangle\n");
scanf("%lf", &height);
printf("Here is the area of the triangle: %.2lf\n", (base * height) / 2);
return 0;
}
However, there are caveats with this approach too, as the article I've linked to above will tell you.
The \n on the format string of scanf tells the the scanf to get Newline character also, but since Newline is part of Whitespace which will be skipped by scanf which means that after matching first number, the scanf look forward for \n or a Non-Whitespace character (since Newline character is ignored, scanf stops when matching 2nd 5).
Let's say the input buffer is 5\n\5\n\6\n, 2 scanf parsing input same buffer(stdin), the first one stopped when reading first input 5, result saved to base , the second one will continue at the point where the first one stopped -> means 2nd input 5 will be read to height therefore 3rd input 6 will be ignored(it can be any Non-Whitespace key to stop the scanner). The result will be (5*5)/2 = 12.5.
I'm having a problem with a while loop. I have to enter a number which is bigger than 0 and below 81. when I use numbers like -1,0,1,2,82 it is going good and I get the expected result, but when I use a letter it keeps going through my while loop. I've used the debugger in eclipse and when I'm at the while loop amount is automatically set to '0' because of the failed scanf. Why does it keep looping when I insert a letter?
#include <stdio.h>
#include <stdlib.h>
int main(){
int amount = 0;
printf("Give a number:\n");
fflush(stdout);
scanf("%d",&amount);
while(amount <= 0 || amount >= 81){
printf("Wrong input try again.\n");
printf("Give a number:\n");
fflush(stdout);
scanf("%d",&amount);
}
return EXIT_SUCCESS;
}
You need to make sure the scanf() worked. Use the returned value to do that
if (scanf("%d", &amount) != 1) /* error */;
When it doesn't work (because eg a letter was found in input) you probably want to get rid of the cause of the error.
A better option to get input from users is to use fgets()
See this related question: scanf() is not waiting for user input
The reason is that when you press enter with a char, scanf failed and didn't eat up the char in the input feed. As a result, the next block begins having whatever you entered before.
You can check that by adding a getchar() before the scanf() inside the while loop. You'll notice that it'll repeat the while loop as many times as your line has invalid characters, then stop and wait for input. The getchar() ate one of the invalid chars in the input each time the loop ran.
It would be better not to use scanf like that, though. Take a look a this resource:
Reading a line using scanf() not good?
Can anyone tell me why my code works fine until I get to the final scant, where I ask the user if they'd like to play again? For some reason, the program seems to ignore this line of code. Please be gentle as I'm new to programming and trying to teach myself Objective-C. This program is typical for noobs, where I generate a random number, ask the user to guess, then ask if they'd like to play again. Thank you.
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
int randomNumber = arc4random_uniform(100); // This is a random number generator that gens a num betw 0 and 100
int userNumber; // This is the number that the user picks intially
int attempts = 0; // This is the number of attempts the user makes during each game
int games = 0; // This is the number of games the user has played
char play = 'n'; // This is whether the user wants to play again, intially set to 'y'
scanf("%c", &play);
while (play == 'y') {
NSLog(#"Random number is: %d", randomNumber);
NSLog(#"Enter a number between 0 and 100");
scanf("%d", &userNumber);
games++; // Increment the number of games the user has played to 1
if (userNumber == randomNumber) {
attempts++;
NSLog(#"Congratulations. You guessed correctly!");
}
attempts++;
while (userNumber != randomNumber) {
if (userNumber < randomNumber) { // Guess is too low
attempts++; // attempt is incremented
NSLog(#"Too low. Try again!"); // User tries again
scanf("%d", &userNumber);
}
if (userNumber > randomNumber) { // Guess is too high
attempts++; // attempt is incremented
NSLog(#"Too high. Try again!"); // User tries again
scanf("%d", &userNumber);
}
}
NSLog(#"Congratulations. You guessed correctly!");
NSLog(#"It took you %d attempts to guess correctly", attempts);
NSLog(#"Do you want to play again?");
scanf("%c", &play); // --------- Here is where things to wrong ---------
} // while play is yes
} // autoreleasepool
return 0;
} // main
Converting comments into answer:
Probably, the final scanf() reads a newline and continues (the numbers don't read the newline). Maybe put a blank before the %c:
scanf(" %c", &play);
Check the return value from scanf(), and maybe even check which character was read.
Riposte:
That space before the %c did the trick. How does anyone ever learn things like that? I think it was reading the \n char rather than what I wanted it to read, which was either 'y' or 'n'. For my understanding, the %d integer doesn't read in the newline, but the %c does? Is that correct? And the way to prevent this is to use a space? I just don't get how I would ever know to do that.
And the response:
By reading the manual page for scanf() very carefully, many times over, or by bitter experience (or by answering lots of questions on SO about it). The scanf() family of functions are extremely powerful and extremely difficult to use accurately. I generally recommend using fgets() to read lines of input:
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0)
{
...use line...
}
combined with sscanf() to parse the data on the line. It generally leads to fewer surprises of the sort you just ran into. You should always check that scanf() made as many conversions as you expected.
The role of white space in scanf()-family format strings is intricate. Most of the conversion specifiers skip leading white space (including newlines) automatically, so a format string "%d%d" will read to integer values where the first may be preceded by an arbitrary amount of white space, and the second may also be preceded by an arbitrary amount of white space. The conversion will stop at the first character that could not be part of the second integer (unless there was an error earlier). If you type 8 and newline as input, then the conversion stops on the newline (\n) and leaves if for the next input to read.
The numeric conversions and the string conversion %s all skip leading white space. The single-character format (%c) and the scan set %[a-z] do not skip leading white space.
When a white space character appears in the format, as in "%d %c", then it represents an arbitrary amount of white space in the data, including zero. Thus, in each of the following lines, the variable receiving the %c format will get Z each time:
123Z
123 Z
123 Z
123
Z
(The last two lines are read together for the last input.)