how to get a specific character from input? - c++

i done a tutorial about getchar:
getChar - c++ tutorial
this all worked till i wanted to make some modifications.
char c;
puts("enter . to exit");
do{
c=getchar();
} while (c != '.'); {
if(c == 's'){
upgradeOne();
cout << "upgrade1 is done" << endl;
}
if (c == 'a'){
upgradeTwo();
cout << "upgrade2 is done" << endl;
}
}
while (total < 999){
total += i;
cout << total << endl;
}
i want to use specific methods when the user input equels an specific character.
if the user types a the method upgradetwo() must be activated.
how am i supposed to do this?

The repetitive processing of your input takes place in the do...while loop. The loop is left only when '.' is pressed.
If you want to react on specific chars, you have to move your if(c==...) statements into this loop (i.e. Between the getchar() and the while).

If you want to run the loop until the user enters period(.), then you can use some bool flag which will be set to true initially. Then write a while which will run until the flag is false. In the while read the character and if it is a period then set the flag to false.
or you can run the while loop infinitely and break the loop if the char is a period else continue.

Related

Setting up a loop waiting for user input (C++)

I'm trying to get a simple tic-tac-toe program to function in the console as a way to make sure I understand loops and arrays.
It compiles, and runs as expected, with the exception that if a user inputs something that isn't a number the program races through the first if statement infinitely without a chance to add a new input. I really can't see how to fix this.
I think the issue is that chosenSquare is an integer as it needs to be compared to values, but cin can take anything in. Expected behaviour would be to check if the input is an integer between 0 and 8 (the 9 spaces on the board), and if not return a message and repeat, waiting for a new input.
Is there a simple fix for this? I'm trying to avoid specialist packages and namespaces for now while I grok the basics. I've looked at similar problems but don't follow them.
Thanks.
Code snippet:
// Input loop
bool valid = false;
while (valid != true)
{
int chosenSquare = 0;
cout << "Player " << currentPlayer << ", enter a number between 1 and 9:" << endl;
cin >> chosenSquare;
chosenSquare--; // For array indexing
if ((chosenSquare < 0) || (chosenSquare > 8)) // <--- PROBLEM IS THIS LOOP
{
cout << "Invalid input. Try again." << endl;
continue;
}
else if ((board[chosenSquare] == currentPlayer) || (board[chosenSquare] == lastPlayer))
{
cout << "Square not availible. Try again." << endl;
continue;
}
else
{
board[chosenSquare] = currentPlayer;
valid = true;
break;
}
}
There are a couple of things culminating causing this.
The first is that when an alpha character is put into the console, the error bit is set, and 0 is written to the variable you're writing to:
The behavior you want to observe changed in 2011. Until then:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
But since C++11:
If extraction fails, zero is written to value and failbit is set. [...]
(From cppr.)
That means chosenSquare is 0 after the read, so chosenSquare-- makes it -1. -1, as you know, is less than 0, so the first if-statement is true.
As to why it stays this way infinitely, you need to clear the fail-bit.
So I changed the first loop after a bit of reading and experiementation:
if (cin.fail()) // <--- PROBLEM IS THIS LOOP
{
cout << "Invalid input. Try again." << endl;
cin.clear();
cin.ignore();
continue;
}
This works, but I can't figure out what it's actually doing.
Could anyone elaborate?

Understanding why unwanted iterations of a cout statement occur [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 3 years ago.
I am working with some C++ code. I have a while-loop set up to allow me to run through some code x-number of times. The while loop terminates once the user indicates that they do not want to run through the code again.
#include <iostream>
#include <string>
using namespace std;
char request;
int main() {
while (request != 'N')
{
string getCode = "";
while (getCode.length() != 3)
{
cout << "Please enter your container's region code (A or B followed by two-number identification)" << endl;
getline(cin, getCode);
if (getCode.length() != 3)
{
cout << "Error" << endl;
}
}
//clear the screen
system("cls");
//get letter
if (getCode.at(0) == 'A' || getCode.at(0) == 'B')
{
if ((getCode.at(1) >= '0' && getCode.at(1) <= '9') && (getCode.at(2) >= '0' && getCode.at(2) <= '9'))
{
if (getCode.at(0) == 'A')
{
cout << "The shipping charge is $25" << endl;
}
else if (getCode.at(0) == 'B')
{
cout << "The shipping charge is $30" << endl;
}
}
else
{
cout << "Error" << endl;
}
}
else
{
cout << "Error...Please enter the code as A or B followed by two numbers" << endl;
}
//Again?
cout << "Would you like to enter in another shipping identification number?" << endl;
cin >> request;
}
cout << "Thank you" << endl;
//End Program
system("pause");
return 0;
}
When I indicated that yes (entering 'Y' to the 'Would you like to enter in another shipping identification number question') I would like to run through the code again, the program outputs an unwanted 'Please enter your container's region code (A or B followed by two-number identification' and 'error' statement. Also please note, the code is inside 'int main()' and that I have properly formatted my 'include' statements.
Your question is to understand why this is happening, so here's the explanation. The code you wrote states thusly:
string getCode = "";
while (getCode.length() != 3)
{
cout << "Please enter your container's region code...
As you see, getCode is always initialized to an empty string. Immediately afterwards, if its length is not 3, this question is outputted.
You need to understand that your computer will always do exactly what you tell it to do. Your computer will not do what you want it to do, but only what you tell it to do. The above is what you told your computer to do, and your computer will always obediently follow its strict instructions, every time it runs this code. That's pretty much the explanation, and there's nothing more to understand.
This section of code is inside another loop, and you indicated that you do not wish the prompt to appear on second and subsequent iteration of the loop, only on the initial one.
However, there's nothing in your instructions to your computer, above, that specify this. You didn't tell your computer that this is what it should do, so why do you expect your computer to do that, entirely on its own? Every time your computer executes these statements shown above, this is exactly what will happen. Nothing more, nothing less. Whether it's the first time inside the outer while loop, or on each subsequent time the while loop iterates, it doesn't matter. The code always does exactly the same thing: getCode gets created and set to an empty string, and because its length is not 3, the inner while loop runs, prints the prompt and calls std::getline to read a line of text from std::cin. At the end of your while loop, if your instructions to your computer indicate that it should run the code in the while loop again, from the beginning (because that's what the while loop does), then the above instructions get executed.
If you now understand why your computer does this (because that's what you told it to do), then you should easily figure out what to tell your computer so it doesn't do this. If you want your computer to print the prompt only the first time it executes the while loop, then this is exactly what you need to tell your computer: set a flag before the while loop, print the prompt only if the flag is set (with all other existing logic remaining the same), and then clear this flag afterwards, so the next time the while loop runs, your computer will do exactly what you told it to do, and not print the prompt.
when I indicate 'Y' to the prompt 'Would you like to enter in another shipping identification number?', it outputs the following: 'Please enter your container's region code (A or B followed by two-number identification)' 'error' 'Please enter your container's region code (A or B followed by two-number identification' . When I input 'Y' I only want it to output 'Please enter your container's region code (A or B followed by two-number identification)'...I only want it to output once
Now that I understand your question, what's happening is an newline (\n) is getting added to the std::cin buffer at these lines right here:
//Again?
cout << "Would you like to enter in another shipping identification number?" << endl;
cin >> request;
This makes even more sense especially when combined with your other comment:
Before int main() there should be a 'char request;
So request a single char. That means when you type something like this:
Y
The newline is added to std::cin as well. That can't be stored in a single char, and the >> may not remove it either. That means it's just sitting here.
What this does is when you get to your if statement at the beginning of the loop again:
while (request != 'N')
{
string getCode = "";
while (getCode.length() != 3)
{
cout << "Please enter your container's region code (A or B followed by two-number identification)" << endl;
getline(cin, getCode);
if (getCode.length() != 3)
{
cout << "Error" << endl;
}
}
getline() sees the newline you added previously and instantly returns an empty string. Empty strings have a length of 0, so it fails your if statement, which prints the error.
The solution is simple, just tell std::cin to ignore the newline:
//Again?
cout << "Would you like to enter in another shipping identification number?" << endl;
cin >> request;
cin.ignore(1, '\n');

while loop and getchar()

I have the simple program below that I wrote for a college course. I know it doesn't really do anything, but it's just an assignment for a course.
The part that I can't figure out, is why doesn't the outer loop work?
The user needs to press '1' to continue, and any other key the program exits.
However, it still doesn't continue if the user presses '1' and instead exits anyway.
I tried adding a cin.clear() before cin >> repeat, but that doesn't work.
I also tried playing around with cin.ignore(), but that didn't seem to help either.
Any ideas?
Thanks
int main()
{
int repeat = '1';
stack<char> cstr;
char c;
while (repeat == '1')
{
cout << "Enter in a name: ";
while (cin.get(c) && c != '\n')
{
cstr.push(c);
}
cout << "\n Enter another name? 1 = Continue, any other key to exit the program";
cin >> repeat;
repeat = getchar();
}
}
There is nothing at all wrong with your code. It seems to be working fine for me.
EDIT: Sorry it doesn't work until you remove the getchar. Forgot to mention that. Simple way of finding out the error is to just display the value of the variable repeat to see what the value is and where it is going wrong.
Screenshot to show you that your codes work
Everything seems to be working fine. I would like to comment on your program structure though. For small programs like this it's ok but always best to practice the logical way. For questions like this you should implement the do while loop instead of the while loop so that it goes in without checking and then accepts the user input and checks with the post condition. Example below.
char repeat;
do
{
//Your codes in here
}while (repeat == '1');
It is more logical to use this method instead unless your question specifies you to use while loop. Anyhow hope this helps.
Run this . it will solve your problem somehow repeat=getchar was making repeat=10.
int main()
{
char repeat = '1';
stack<char> cstr;
char c;
while (repeat == '1')
{
cout << "Enter in a name: ";
cin.ignore();
while (cin.get(c) && c != '\n')
{
cstr.push(c);
}
cout << "\nEnter another name ? \nPress 1 to Continue : ";
cin >> repeat;
cout << endl;
}
system("pause");
}
The line cin >> repeat is tring to read an integer from the keyboard because repeat is a variable of type int. However, you are verifying if the integer read from the keyboard is equal to 49 (the ASCII code for the character '1'), which is not what you want. A solution would be to replace the line
int repeat = '1';
with
int repeat = 1;
and also replace
while (repeat == '1')
with
while (repeat == 1)
because then you are comparing the integer read from the keyboard with the integer 1 (rather than the character '1'). Also, at the end of the loop you read input from the keyboard and store it in repeat but then you immediately read input again and store that value in repeat, replacing its previous value. To solve this, replace the line
repeat = getchar();
with
getchar();
and that should do it.
cin >> repeat;
it reads repeat as int. (1 is not equal '1')
repeat = getchar();
It reads int code of special char '\n' - symbol end of line.
You must use
char repeat = '1';
Or write
int repeat = 1;
and not use getchar()

How to end a loop early if a user says to C++

Note: This is a homework assignment.
I am trying to make a program that plays the game Pig! Pig is a game with the following rules:
1. First to get 100 GAME POINTS is the victor.
2. On your turn, you roll a dice. If you get a 1 at any roll, you end your turn and add 0 to your GAME SCORE.
3. If you roll any value other than a 1, you have the option to HOLD or PLAY. If you PLAY, your roll is added to your TURN SCORE and you roll again. If you HOLD, your TURN SCORE is added to your GAME SCORE and the turn passes to the computer.
The game is coming along very easily until I get to the following problem (see code):
int player(){
char PlayAgain = 'Y';
int turn_score = 0;
while (PlayAgain != 'N' || PlayAgain != 'n'){
int dice;
srand(time(NULL));
dice = rand() % 6 + 1;
turn_score = turn_score + dice;
if (dice != 1){
cout << "You rolled a " << dice << "! Would you like to roll again? [Y/N]: ";
cin >> PlayAgain;
if (PlayAgain == 'N' || PlayAgain == 'n'){
/*END TURN AND return turn_score;*/
}
}
if (dice == 1){
cout << endl << "Oops! You rolled a 1! Your turn is ended, and you add nothing to your score.\n";
system("PAUSE");
/*END TURN, NO SCORE ADDED*/
}
}
}
How can I have the program end the loop prematurely (if either the play HOLDS or dice == 1) and return the proper value (if HOLD, return turn_score. Else return 0)? [See two noted sections]
You can use break to get out of a loop. Since you're saying that you want to return "the right value" then you should do something like that:
On the first if clause
if (PlayAgain == 'N' || PlayAgain == 'n'){
/**Game-Specific logic here**/
return turn_score
}
and on the second one:
if (dice == 1){
cout << endl << "Oops! You rolled a 1! Your turn is ended, and you add nothing to your score.\n";
/**Game-Specific logic here**/
cin.get();
return turn_score;
}
A return statement doesn't need to be at the end of the function and more than one return statements can co-exist inside the same function
Rather then correcting your code I would like to make you clear about what actually is needed here.
Ever heard of break; statement.Let us understand with a simple example
see the following code snippet where your program is taking input from the user,it keeps on taking input from the user until you press 'A'
char var;
while(true)
{
cin>>var;
if(var=='A') break;
}
Now in this program,the while loop is set to true and will keep on running and taking input from the user,and the if statement will not run until the user have entered 'A'. AND the moment 'A' is given as the input,break will take the control out of the while loop for you.
How about having your 'return' statement (with the proper value depending on the case) inside your loop? This will break both the loop and the function, but returning the value you needed.

while statement is unable to read the correct char input

hi i am new to c++ and i dont understand why my while statement doesnt work now. it was working when i tried to do it earlier.
Full code is available at: http://pastebin.com/aeH5fKwh
basically here is the while loop (i excluded all the unnecessary parts, i left the inside of the while loop intact for viewing purpose)
int main()
{
unsigned int seed;
char input;
bool done;
for (int round = 0; round < 5; round++)
{
done = false;
cout << "\nEnter seed: ";
cin >> seed;
cout << "\nRound 1" << endl;
while(!done)
{
cout << "\nDo you wish to draw another card [y][n]: ";
cin >> input;
while (input != 'y' && input != 'n')
{
cout << "Invalid input! Please enter [y][n]!" << endl;
cin >> input;
}
if (input == 'y')
{
dealExtra(playerHand, deck, gameInfo);
cout << "Your cards are ";
printHand(playerHand, gameInfo.playerCardCount);
}
else
done = true;
}
}
cout << endl;
return 0;
}
when i try entering anything that is not 'y', 'n', it will tell me that my input is invalid. But when i try to enter 'y' or 'n', it kinda just ignored it and nothing else happened.. i checked with cout statement and found that it manage to get into the if (input == 'y') statement, but it doesnt seem like it is doing anything else. Everything was fine till 20 minutes ago and i really couldnt figure out whats wrong.
Edit: i ran another test using "cout << '[' << input << ']' << endl;".. it seems like the program is able to get my first input, but then it just hangs there afterwards.. what i get is something like:
Do you wish to draw another card [y][n]: y
[y]
y
y
y
y
I compiled this on linux terminal using g++
if extra codes is needed, i'll edit and add them.. thanks!
When you ask for input from the console, most implementations buffer characters until a newline key is pressed.
After the newline is received, the first character of the buffer is returned. The newline still remains in the buffer as well as any extra characters.
In your case, the second cin >> input statement will read the newline from the buffer.
As an experiment, try entering "frog" and single step through your program. This should illustrate the case of residual characters in the buffer.
Try cin.ignore(1000, '\n') after the first cin >> input. The ignore method will eat up any remaining characters in the buffer until the newline is found.
Make below statements inactive
dealExtra(playerHand, deck, gameInfo);
printHand(playerHand, gameInfo.playerCardCount);
and check if it works, then try making one of the above statements active alternately to find out in which function the flow is getting lost. And so on.
If you feel lazy to run a debugger, and plan to use cout<< statements to find a hanging call, you should flush you cout:
( cout << "I am here and going to hang" ).flush() ;
Otherwise you can't see recent output just because it's still in the output buffer. Try this and you well might see what call hangs your program.
You have an infinite loop inside checkComputerHand:
bool done = false;
while(!done)
{
if(sum == 11 && checkAce == true)
{
computerHand[aceLocation].value = 11;
done = true;
}
if(sum > 11 && checkAce == true)
{
computerHand[aceLocation].value = 1;
done = true;
}
// What if checkAce wasn't true? Infinite loop!
}
Also, the first two lines of newGame do not make any sense:
void newGame(Card playerHand[], Card computerHand[], Statistics &gameInfo)
{
playerHand = '\0';
computerHand = '\0';
// ...
}
Array parameters are silently rewritten by the compiler as pointer parameters. So all you're doing is assigning the null pointer to those local pointers. Probably not what you intended...