The basic idea of my code is for the user to enter either the spelling of 0-9 i.e. zero, one etc. or the actual numeral and for it to output the numeral/spelling respectively.
I managed to do this with a while loop using while(cin >> number) (number being a string variable) and then use if statements to select the appropriate output option i.e. "zero" --> 0, and "0"--> zero.
At first though I tried to do it as follows;
while (cin >> number || cin >> n)
{
if (n == 0)
cout << digits[0] << endl;
.
.
.
else if (n == 9)
cout << digits[9] << endl;
if (number == digits[0])
cout << 0 << endl;
.
.
.
else if (number == digits[9])
cout << 9 << endl;
}
digits is just a vector class that stores the strings "zero", "one" etc.
This didn't work though, when a string was entered the output was correct but when an integer was entered the output was always "zero". I was wondering why this doesn't work? I figured its something to do with the while loop conditions. Can't the computer identify if a string/integer was entered and carry out the appropriate action?
The problem is that cin >> number is always going to succeed since number is a string (as long as you don't hit EOF or some other failure condition); if the user types in a digit, number is going to hold the number as a string. So cin >> n won't happen.
You should compare your number against the strings "0".."9" instead (in addition to testing the digit names). You should also use a loop instead of a chain of if/else if.
I don't think you understand the usage of the || operator. while (cin >> number || cin >> n) means do cin >> number and if that expression evaluates false, then do cin >> n, and if either one evaluates true, then do what's inside the brackets.
As nneonneo said, cin >> number will (almost) always evaluate true, so cin >> n will never happen, but that's actually the least of your problems.
If I might suggest, I think you ought to get rid of the while loop entirely for now, and just focus on doing it once. What you need is to cin >> number and then do a test on weather or not number is a "0","1",..."9" number, or a "zero","one",..."nine" number. Then you can decide on how to convert one to the other.
Related
Objective: Run a while loop that will repeat until the user inputs an integer between 1-3 (inclusive). So if an integer that is smaller than 1 or bigger than 3 is inputted or any character or string is inputted, the loop repeats.
My noob knowledge: I know how to compare user input when it is an integer, but when it is a char or string datatype input all I get is an infinite loop. Plus I declared the inputtable variable as an integer, so not sure how to go on about this.
I've done some Google searches but can't seem to find a question similar enough to mine.
Advice is highly appreciated :)
Code below:
int Decision1 = 4;
while ( Decision1 < 1 || Decision > 3)
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << "\n\n";
}
int Decision1;
while(std::cin >> Decision1) {
if(Decision1 >= 1 && Decision1 <= 3) break;
// todo
}
You can use ASCII codes for checking number or character.
#include <iostream>
int main() {
char Decision1 = '0';
while ( (Decision1 < 49 && Decision1 >=47) || (Decision1 >51 && Decision1 <=57 ))
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << Decision1;
std::cout << "\n";
}
}
I hope helpful for you.
Keep in mind: when you read input from std::cin you're reading text that's typed at the console. The stream extractor tries to convert that text to the target type. That is, in
int i;
std::cin >> i;
the >> operator looks for digit characters and figures out what value those characters represent. If the characters can't be converted to an integer value the extraction fails. Streams have a conversion to bool that tells you whether the stream is in a good state, or whether an attempted operation failed. So:
int i;
if (std::cin >> i)
std::cout << "got a value!\n";
To write a loop that prompts for valid input you need to reverse the test:
int i;
while (!(std::cin >> i) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To also check that the value is in the required range, just do it:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To clear the input stream, you have to reset its internal flags. You do that with std::cin.clear();. And, depending on what you think was typed in, you probably want to get rid of any additional characters that the user typed. You do that with std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n'). That tells the stream to discard character until it reaches a newline (press ENTER), or until it has read a huge number of characters.
Putting it all together:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
std::cin.clear();
std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Yes, this clears the stream state and flushes the input when the input was a valid integer but out of range; that's harmless. It's a waste of time, but the speed of keyboard input is limited by how fast the user types, which is much slower than anything that the code in this loop does.
I am currently trying to write a program at school involving a random number generator for rolling a dice. I have written the code successfully, but I am trying to improve it so that the size of the dice and the number the user is trying to roll can be chosen by the user.
I have written code that does this, and I have also added code that repeats the request for input if the wrong value (ie not one of the dice sizes offered or trying to roll a number outside the range of the dice) or input type (ie var instead of int) is entered. However, if a floating point number is entered, and the number to the left of the floating point is in the correct range of values, it is using that number.
For example:
int size = 0;
cout << "Please choose the size of the dice to roll (6, 12 or 20): ";
cin >> size;
while (size != 6 && size != 12 && size != 20 || !cin)
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid number entered. Choose the size of the dice to roll (6, 12 or 20): ";
cin >> size;
}
This will correctly ask to repeat the input if any letters or any numbers that aren't 6, 12 or 20 are entered, but if 20.125 (or any floating point number that is 6.- 12.- or 20.-) is entered it will take the number and move on to the next bit of code. This also happens if I enter a valid number followed by letters (ie 6f).
I tried modifying the condition of the while loop to:
while (size != 6 && size != 12 && size != 20 || !(cin >> size))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid number entered. Choose the size of the dice to roll (6, 12 or 20): ";
cin >> size;
}
And that fixes the problem, and it asks me for another input if I enter 12.5 or 20R etc, but then when I enter a correct input (6, 12 or 20) it just takes me to a new line in the debugger without moving to the next line of code. If I then enter a correct input again, it reads it at takes me to the next line of code.
I don't quite understand why one works 99% how I want it to with one error, and the other fixes that error but then gives me another one.
Thanks in advance, any advice guidance is much appreciated!
The way cin >> some_int_variable will interpret the input is character by character, until it stops making sense as an int. For instance, when it encounters . or f, cin is done reading that int.
If you want a different behavior, you will have to implement it yourself. Specifically, how do you stop processing one input, and starts processing the next?
cin >> some_int_variable will stop when it is no longer a valid it, cin >> some_std_string_variable will stop when it encounters an white-space character (new lines included). How about your problem? How do you want to separate one input from the next?
If white-space is a sensible approach, you can do so:
std::string word;
std::cin >> word;
int value;
bool error = false;
try {
size_t pos;
value = std::stoi(word, &pos);
// Was the full string used to build the int?
if(pos != word.size()) error = true;
} catch(std::logic_error&) {
error = true;
}
if(error) { /* something went wrong */ }
See the docs for std::stoi().
You could read a float, assign it to an integer variable and then compare the two. Something along these lines:
int integerSize;
float floatSize;
cin >> floatSize;
integerSize = floatSize; //Your program will perform a cast from float to integer, it will essentially truncate whatever appears after the floating point.
if (integerSize != floatSize) //Your program will now perform a cast from integer to float in order to compare the two, but if floatSize was not a whole number, this comparison should return false.
{
//code to ask for another value
}
That being said, floats (and doubles and long doubles) do experience rounding errors, so as another user suggested, the safest bet is to read a string and parse it yourself, or using a built-in function like std::stoi() (only for integers) and std::stof() (for floats).
template<typename T>
T typed_read_line(const std::string& prompt)
{
T result{};
std::string l;
std::cout << prompt << ":";
while (std::getline(std::cin, l)) {
std::istringstream line{l};
line >> result >> std::ws;
if (line.eof()) break;
//line contains more then expected
std::cout << "Again: " << prompt << ":";
}
return result;
}
https://godbolt.org/z/dfYKe3
Or version with extra validation or v3.
#include<iostream>
#include<limits>
int main()
{
int m;
std::cin >> m;
while (std::cin.fail() || m <= 0) {
std::cin.clear();
std::cin >> m;
}
return 0;
}
The above code is supposed to prompt for an input until a positive integer is entered. But even after entering a positive integer it keeps prompting for an input.
For example, lets say I have the input as
abc
c4
-3
1
2
.
.
So in principle the moment I enter 1, the execution should be transferred out of the loop. But it keeps prompting for an input and looks like an infinite loop.
After looking around for a while, I modified it as
cin >> m;
while (cin.fail() || m <= 0) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cin >> m;
}
As desired, entering a positive number terminates the loop.
I didn't get it. Why the new line character is stuck in the input buffer?
Suppose I have this
int a , b;
cin >> a;
cin >> b;
When my input is
1
2
It correctly sets a to 1 and b to 2, instead of setting b to \n.
Why is the behaviour different in the two cases?
It's not that there's a stray newline, but that the entire input is still in the stream.
cin >> m fails immediately if it can't extract an integer.
It does not read the next "word" and see if it's an integer, and then stop after that "word" if it wasn't - the "read pointer" is left at the point of initial failure.
The ignore skips ahead to the end of the line and ignores everything up to that point.
To illustrate the difference, this program tries to read the input first as int and if that fails, reads the same input again as a std::string for use in the error message:
int main() {
int n = 0;
string s;
while (!(cin >> n))
{
cin.clear();
cin >> s;
cout << "That wasn't an int, it was " << s << endl;
}
cout << "This is an int: " << n << endl;
}
The solution you found with ignore is pretty much the "standard" solution.
The newline will be eaten up when extraction succeeds (whether the extracted integer is positive or not).
It won't be eaten up when extraction fails.
I was wondering if there was anyways of stopping letters being entered for an integer. Here is the code which I have been using in my int main.
do
{
cout << "Player 1 please enter the value of the row you would like to take ";
cin >> row;
}while (row != 0 && row != 1 && row != 2 && row != 3);
My problem with this code is that if the user enters a letter it creates a never ending loop. Any help would be much appreciated.
Standard library doesn't provide anything that would filter characters that are entered through standard input. I believe you could use libraries like curses to do that.
What you can do, though, is check whether input suceeded. operator>> for int will set the stream's state to failbit if it couldn't extract an integer (for example, when it encountered an 'a' or something like that. You can use extraction operators in boolean context, something like this:
cout << "Player 1 please enter the value of the row you would like to take ";
while (!(cin >> row) || (row < 0 || row > 3)) {
cout << "Invalid input, try again!\n";
// clear the error flags and discard the contents,
// so we can try again
cin.clear();
cin.ignore(std:numeric_limits<std::streamsize>::max(), '\n');
}
Note that if you enter for example 1abc, the read will succesfuly read 1 and leave the abc in the stream. This might not be a desired behaviour. If you wish to treat that as an error you can say
if ((cin >> std::ws).peek() != EOF) { /* there's more input waiting */ }
and act accordingly, or just unconditionaly ignore everything from the stream once you've got a value.
Get characters one at a time and only add the number characters to the string. Use
cin.get();
in a loop.
I'm trying to have a program loop, accepting input and producing output until the user enters "0" as the input.
The problem is, my program accepts two values for input, like this:
cin >> amount >> currency;
So, I tried to have a while statement like this:
while (amount != 0 && currency != "") {
cin >> amount >> currency;
cout << "You entered " << amount << " " << currency << "\n";
}
However, the while statement always executes, even if I enter 0 as input.
How do I write the program such that it accepts two values as input except when the user enters 0, in which case it terminates?
You could use the fact that the right side of && is not executed if the left is false:
#include <iostream>
#include <string>
int main()
{
int amount;
std::string currency;
while (std::cin >> amount && amount != 0 && std::cin >> currency)
{
std::cout << "You entered " << amount << " " << currency << "\n";
}
}
test run: https://ideone.com/MFd48
The problem is that you do your check on the next iteration, after you've already printed the message. What you probably want is something like the following pseudo-code:
while successfully read amount and currency:
if amount and currency have values indicating that one should exit:
break out of the while loop
perform the action corresponding to amount and currency
I'll leave the actual code to you, since I suspect this is homework, however here are some hints:
You can use break to prematurely exit out of a loop.
Your while line should look like while (cin >> amount && cin >> currency)
What are the data types of 'currency' and 'amount'?
If 'amount' is of type 'char' then its integer value for '0' would be something else depending on the encoding ( 48 for ASCII ). Thus when you call 'cout << amount' you see '0' but when you evaluate 'amount != 0' it returns true instead of false.