Using while>>cin to keep asking user for input in C++ - c++

Code for a blackjack card counting program.
the issue is that it does not exit the while loop upon receiving no cin input from the user.
for example)
User would input x chars and then hit enter to exit the while loop.
#include<iostream>
using namespace std;
int main(){
int count = 0;
char currcard;
cout<<"Enter cards seen on table: "<<endl;
while (cin>>currcard)
{
switch (currcard)
{
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
count++;
break;
case '7':
case '8':
case '9':
break;
case 'A':
case 'J':
case 'Q':
case 'K':
count--;
break;
default:
cout<<"Invalid Entry";
break;
}
}
cout <<"Current count: "<< count << endl;
//user enter cards seen on table and if below 7 increment
//based on count the program returns if you should hit or quit
return 0;
}
Expecting program to exit when enter is hit by user

You can use cin.get() like this.
while (cin>>currcard)
{
// your logic
if (cin.get() == '\n') {
break;
}
}
In this way, your input is supposed to be something like 1 2 3 4 A J Q ending with Enter.

EDIT
As OP wants undetermined length of input, I suggest to switch the input itself from char to std::string.
This way access is gained to more intuitive and effective I\O operations:
#include <iostream> // std::cin, cout, endl
#include <string> // std::string: can omit this line
#include <cctype> // isspace(): can omit
int main(){
int count = 0;
std::string currcard{""};
std::cout << "Enter cards seen on table: "<< std::endl;
std::getline(std::cin, currcard);
for (char c : currcard) {
if (isspace(c))
continue;
switch (c) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
++count;
break;
case '7':
case '8':
case '9':
break;
case 'A':
case 'J':
case 'Q':
case 'K':
--count;
break;
default:
//std::cout << "Invalid Entry\n";
break;
}
}
std::cout <<"Current count: "<< count << std::endl;
//user enter cards seen on table and if below 7 increment
//based on count the program returns if you should hit or quit
return 0;
}
Notice I have added a check for white spaces, and removed the message for invalid entries: both simply get ignored. But if needed that line can be uncommented.
Old solution
You can use cin.getline() as suggested in the comments, in conjunction with a flag that triggers exit from the loop once three inputs are given:
#include <iostream>
int main(){
static int count = 0, flag = 0;
char currcard;
std::cout << "Enter cards seen on table: "<< std::endl;
while(std::cin.getline(&currcard, 3)){
switch (currcard)
{
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
++count;
break;
case '7':
case '8':
case '9':
break;
case 'A':
case 'J':
case 'Q':
case 'K':
--count;
break;
default:
std::cout << "Invalid Entry\n";
--flag;
break;
}
++flag;
if (flag == 3)
break;
}
std::cout <<"Current count: "<< count << std::endl;
//user enter cards seen on table and if below 7 increment
//based on count the program returns if you should hit or quit
return 0;
}
There is also a flag decrement for invalid entries.

Related

How can reduce recursion within this function

can't figure out how to prevent recursion within this function, any suggestions or
recommendations? I've tried a couple of my own solutions but ran into the error of having
the program crash if wrong inputs and repeatedly entered.
Thanks in advance, DK.
static void CheckPlayerInput()
{
// gets the character entered (as a char)
cin >> input;
//check is actually a char
if (cin.fail())
{
//more recursion, could cause issues, could you find another way?
cout << "Invalid character, try again!" << endl;
CheckPlayerInput();
}
//converts char to upper case
input = toupper(input);
//check the input character
// maps the input keys to the grid reference
//calling the FillSquare method
switch (input)
{
case '1': FillSquare(0, 0); break; //top-left
case '2': FillSquare(0, 1); break; //top-centre
case '3': FillSquare(0, 2); break; //top-right
case '4': FillSquare(1, 0); break; //middle-left
case '5': FillSquare(1, 1); break; //middle-centre
case '6': FillSquare(1, 2); break; //middle-right
case '7': FillSquare(2, 0); break; //bottom-left
case '8': FillSquare(2, 1); break; //bottom-centre
case '9': FillSquare(2, 2); break; //bottom-right
//IF NOT ANY OF THE ABOVE
default:
{
//more recursion, could cause issues
//
cout << "Invalid character, try again!" << endl;
CheckPlayerInput();
}
break;
}
}
Use a do while loop instead
static void CheckPlayerInput()
{
bool invalid = false;
do
{
invalid = false;
// gets the character entered (as a char)
cin >> input;
...
default:
{
//more recursion, could cause issues
//
cout << "Invalid character, try again!" << endl;
invalid = true;
}
break;
}
}
while(invalid);
}
The while loop will repeat as long as the input is invalid
I guess there are many different ways to implement it.
The below might be my approach.
Note:
Filling the square feels like a dedicated task and should therefore be inside it's own function.
Maybe you should use non-static / non-global methods and instead use objects.
Your method CheckPlayerInput is not checking the input. Instead, it's processing it.
static bool
_fillSquare(char type)
{
switch (type)
{
case '1': FillSquare(0, 0); break; //top-left
case '2': FillSquare(0, 1); break; //top-centre
case '3': FillSquare(0, 2); break; //top-right
case '4': FillSquare(1, 0); break; //middle-left
case '5': FillSquare(1, 1); break; //middle-centre
case '6': FillSquare(1, 2); break; //middle-right
case '7': FillSquare(2, 0); break; //bottom-left
case '8': FillSquare(2, 1); break; //bottom-centre
case '9': FillSquare(2, 2); break; //bottom-right
default : return false;
}
return true;
}
// this method does not `check` the player input, but it
// `processes` it. The name should reflect that.
static void
processPlayerInput()
{
// try to retrieve and process input until
// a valid input was given
while (true)
{
cin >> input;
if (!cin.fail ())
continue;
input = toupper(input);
bool success = _fillSquare(input);
if (!success)
{
cout << "Invalid character, try again!" << endl;
continue;
}
return;
}
}

Creating a loop in C++ (still learning)

new here, trying to figure out how to repeat my program. I need to understand how to insert a loop, i think a "do while" loop will work for this, but I am unsure because I have tried a few places of insertion and cannot get it to work right.
So my program is a telephone program, I am sure everyone here has done this in school, I am learning to do this and this is the part that I am confused on. My code is below.
I just need to make it possible for the user to keep entering phone numbers, over and over again.
I feel like I should be inserting a "do" before line14 "for (counter = 0...
Then insert the "while" portion at line 94 between the brackets. For some reason, that doesn't work for me and I am now stumped.
NOTE This is an assignment for school, so please explain to me rather than just show me. Thanks for everyones help.
#include <iostream>
using namespace std;
int main() {
int counter;
char phoneNumber;
cout << "\nEnter a phone number in letters only." << endl;
for (counter = 0; counter < 7; counter++)
{
cin >> phoneNumber;
if (counter == 3)
cout << "-";
if (phoneNumber >= 'A' && phoneNumber <= 'Z'
|| phoneNumber >= 'a' && phoneNumber <= 'z')
switch (phoneNumber)
{
case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
cout << 2; // keypad starts with 2 for letters ABC, abc
break;
case 'D':
case 'd':
case 'E':
case 'e':
case 'F':
case 'f':
cout << 3; //for letter DEF, def
break;
case 'G':
case 'g':
case 'H':
case 'h':
case 'I':
case 'i':
cout << 4; //for letters GHI, ghi
break;
case 'J':
case 'j':
case 'K':
case 'k':
case 'L':
case 'l':
cout << 5; //for letter JKL, jkl
break;
case 'M':
case 'm':
case 'N':
case 'n':
case 'O':
case 'o':
cout << 6; //for letters MNO, mno
break;
case 'P':
case 'p':
case 'Q':
case 'q':
case 'R':
case 'r':
case 'S':
case 's':
cout << 7; //for letters PQRS, pqrs
break;
case 'T':
case 't':
case 'U':
case 'u':
case 'V':
case 'v':
cout << 8; //for letters TUV, tuv
break;
case 'W':
case 'w':
case 'X':
case 'x':
case 'Y':
case 'y':
case 'Z':
case 'z':
cout << 9; //for letters WXYZ, wxyz
break;
}
}
return 0;
}
As already said by pb772 an infinite loop of type
do { //Stuff you'd like to do } while(1);
would be fine, especially since it's a school assignment, but not ideal as always stated by pb772.
I've seen advises to cycle a finite number of times and then exit but I would instead do something like a special character like '#' or '!' that will trigger a condition to exit the loop. I would see this like an exit/escape character. In the end is up to you, if you want you can do anything and what I'm proposing is just an idea to inspire you. For example another idea would be, if you'd like to go deeper, wait for another input to define what action to perform, you trigger the "command console" with '!' and then type 'q' to exit or also read the characters into a string at first so you could do complex "commands" like "!q".
Here's the simple version:
bool loop_condition = true;
do
{
if(input == '!')
{
loop_condition = false;
}
else
{
//Stuff you'd like to do if the read character is not !
}while(loop_condition == true);
Just to provide context here is what's happening:
I declare a variable named loop_condition
Inside the loop I check if the typed character is !
If so set the variable loop_condition to false with subsequent exit from the loop
Else just execute your code and loop
As I already said this is a very simple example just to give you an idea and can be improved a lot.
I suggest wrapping the for (counter=0... loop with a while (!cin.eof()) { block. This will allow the user to continue to enter in characters, until an EOF character (e.g. ctrl-D).
You may find you want to output a newline after every 7th character, to make the display look nice.
do {
//your code here;
} while (1);
This will repeatly infinitely which is not a good practice.
int number_of_phones = 10; // total number of phones you want
int i = 0;
do {
//your code here;
i=i+1;
} while (i<number_of_phones);
This will make it run 10 times for example
You can have whatever condition you want in a for loop, including nothing at all, which is treated as true.
for(;;) {
// code
}
is the same as
while (true) {
// code
}
is the same as
do {
// code
} while (true)
It sounds like you mixed up the placement of braces when you tried do { ... } while (true). You may want to move your big switch into a function, so that it's more obvious what scope a partiular } ends.
#include <iostream>
int phone_key(char key)
{
switch (key)
{
case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
return 2;
case 'D':
case 'd':
case 'E':
case 'e':
case 'F':
case 'f':
return 3;
case 'G':
case 'g':
case 'H':
case 'h':
case 'I':
case 'i':
return 4;
case 'J':
case 'j':
case 'K':
case 'k':
case 'L':
case 'l':
return 5;
case 'M':
case 'm':
case 'N':
case 'n':
case 'O':
case 'o':
return 6;
case 'P':
case 'p':
case 'Q':
case 'q':
case 'R':
case 'r':
case 'S':
case 's':
return 7;
case 'T':
case 't':
case 'U':
case 'u':
case 'V':
case 'v':
return 8;
case 'W':
case 'w':
case 'X':
case 'x':
case 'Y':
case 'y':
case 'Z':
case 'z':
return 9;
}
return 0;
}
int main() {
for (;;)
{
std::cout << "\nEnter a phone number in letters only." << std::endl;
for (int counter = 0; counter < 7; counter++)
{
char phoneNumber;
cin >> phoneNumber;
if (counter == 3)
std::cout << "-";
std::cout << phone_key(phoneNumber);
}
}
}

How to convert a hex char to binary in C++?

I am trying to convert two (2) inputs from the user.
I am taking input in variable M. The K variable is unused.
I tried to solve it using for loop, but, I could not do it. The first loop could not stop.
Is it wrong to use an array?
And, can I use for loop after to input the binary output into a new array?
Here's my code:
include<iostream>
using namespace std;
int main()
{
char M[64],K[64];
long int i=0;
cout<<"Enter M: ";
cin>>M;
cout<<"M= ";
while(M[i])
{
switch(M[i])
{
case '0':
cout<<"0000";
break;
case '1':
cout<<"0001";
break;
case '2':
cout<<"0010";
break;
case '3':
cout<<"0011";
break;
case '4':
cout<<"0100";
break;
case '5':
cout<<"0101";
break;
case '6':
cout<<"0110";
break;
case '7':
cout<<"0111";
break;
case '8':
cout<<"1000";
break;
case '9':
cout<<"1001";
break;
case 'A':
cout<<"1010";
break;
case 'B':
cout<<"1011";
break;
case 'C':
cout<<"1100";
break;
case 'D':
cout<<"1101";
break;
case 'E':
cout<<"1110";
break;
case 'F':
cout<<"1111";
break;
case 'a':
cout<<"1010";
break;
case 'b':
cout<<"1011";
break;
case 'c':
cout<<"1100";
break;
case 'd':
cout<<"1101";
break;
case 'e':
cout<<"1110";
break;
case 'f':
cout<<"1111";
break;
default:
cout<<"nInvalid hexadecimal digit "<<M[i];
}
i++;
}
return 0;
cout<<"\nEnter K: ";
cin>>K;
cout<<"K: ";
while(K[i])
{
switch(K[i])
{
case '0':
cout<<"0000";
break;
case '1':
cout<<"0001";
break;
case '2':
cout<<"0010";
break;
case '3':
cout<<"0011";
break;
case '4':
cout<<"0100";
break;
case '5':
cout<<"0101";
break;
case '6':
cout<<"0110";
break;
case '7':
cout<<"0111";
break;
case '8':
cout<<"1000";
break;
case '9':
cout<<"1001";
break;
case 'A':
cout<<"1010";
break;
case 'B':
cout<<"1011";
break;
case 'C':
cout<<"1100";
break;
case 'D':
cout<<"1101";
break;
case 'E':
cout<<"1110";
break;
case 'F':
cout<<"1111";
break;
case 'a':
cout<<"1010";
break;
case 'b':
cout<<"1011";
break;
case 'c':
cout<<"1100";
break;
case 'd':
cout<<"1101";
break;
case 'e':
cout<<"1110";
break;
case 'f':
cout<<"1111";
break;
default:
cout<<"nInvalid hexadecimal digit "<<K[i];
}
i++;
}
return 0;
}
first of all, you are using 2 parts of the code, repetitively, you should consider using a function for higher scalability (Imagine if you wanted to convert 5 inputs, it is not a good practice to copypaste the switch 5 times.
Then, the for loop is mostly used for known sized collections, and the while for unknown sized ones, so for the for you can just put the size of your array:
for(int i = 0;i<64;i++){
convert(M[i]);
}
If you want to have a good scalability you should consider using sizeof(M)/sizeof char or things like a global constant or #define for the maximun string you can have...
Hope it helped.

Somewhy the program always returns 'false'?

Why does this code always return 'false' and activates the goto even when I type a digit? Can anyone please help me? Thank you!
char userValue = '4';
auto h = true;
tryAgain:
std::cout << "Please type a digit: ";
std::cin >> userValue;
switch (userValue) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
h = true;
default:
h = false;
}
switch (h) {
case true:
std::cout << "This character is a digit.";
case false:
std::cout << "Wrong! Try again!" << std::endl;
goto tryAgain;
}
You simply forgot to break out of the case if it has been processed.
That way it will fall through the cases and handle the false case after the true case has been handled.
switch (h) {
case true:
std::cout << "This character is a digit.";
break;
case false:
std::cout << "Wrong! Try again!" << std::endl;
goto tryAgain;
//not necessarily needed because goto leaves the scope anyway.
//break;
}
The same issue here, break if you wan't to stop the fallthrough:
switch (userValue) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
h = true;
break;
default:
h = false;
break;
}

I can't find an error in my first switch statement

I'm reading the book programming principles and practice using C++ and the book has introduced the concept of switch statement and an example of what we can do when we want to perform the same action for a series of case labels :
cout << "Please enter a digit : ";
char a = 0;
cin >> a;
switch (a) {
case '0': case '2': case '4': case '6': case '8':
cout << "is even\n";
break;
case '1': case '3': case '5': case '7': case '9':
cout << "is odd\n";
break;
default:
cout << "is not a digit\n";
break;
}
The compiler doesn't report any error but when i execute the program if I enter the value 11 for example the program prints out : is odd. Why ? I expected to see : is not a digit but I can't understand where the problem is. This problem happens also if I enter the value 999 or some other values, why ?
You read a single character, '1'. 1 is odd.
The next character is still there to be read.
cout << "Please enter a digit : ";
You are asking user to enter a digit. Why are you storing it in char?:
char a = 0;
You need to store it in an int:
int a = 0;
Then all you cases have chars:
case '0': case '2': case '4': case '6': case '8':
This should be changed to ints:
case 0: case 2: case 4: case 6: case 8:
Similarly change for other cases.