I'm trying to get two space-separated variables and running into this error, as well as [no operator ">>" matches these operands] and [syntax error: ">>"].
#include <iostream>
#include <string>
#include <vector>
using namespace std;
...
void player(char array[][ROWS_AND_COLUMNS], char letter)
{
bool element_occupied = false;
do
{
int row = 0;
int column = 0;
cout << "Enter player " << letter << ", row and column:";
cin >> inputValidate(row, 1, 3) >> inputValidate(column, 1, 3);
if (array[(row - 1)][(column - 1)] == '*')
{
array[(row - 1)][(column - 1)] = letter;
element_occupied = true;
}
else
{
cout << "Sorry, that spot is taken." << endl;
element_occupied = false;
}
} while (element_occupied == false);
}
inputValidate() takes the input, minimum value, and maximum value, and returns the input value if it is 1, 2, or 3.
EDIT:
int inputValidate(int user_number, int lowest, int highest)
{
while (!(cin >> user_number) || (user_number < lowest || user_number > highest))
{
cout << "Error. Enter a number from " << lowest << " to " << highest << ": ";
cin.clear();
}
return user_number;
}
This is a tic-tac-toe game.
inputValidate() returns a temporary int, an rvalue, which operator>> can't read into. It expects an lvalue instead (ie, a variable with a name). That is why you are getting errors on the cin >> inputValidate(...) statement.
Even if the statement could compile, it simply doesn't make sense to use. inputValidate() does its own reading of cin, so player() shouldn't be trying to pass the return value of inputValidate() to cin >> to begin with. inputValidate() would read in a validated number and return it, then player would be trying to read in a new unvalidated number to overwrite it.
For that matter, there is no point in passing in the user_number parameter at all. You are passing it in by value, just to immediately overwrite it with user input. So the value passed in by player() is irrelevant. If you want to return the user's input then user_number should be a local variable inside of inputValidate(). Otherwise, it should be an output parameter passed by reference instead, and inputValidate()'s return value should be void.
Also, when operator>> fails inside of inputValidate() due to invalid input, you are not discarding the input that caused it to fail. cin.clear() only resets the stream's error state, it does not discard any data. You need to call cin.ignore() for that.
With that said, try something more like this:
#include <iostream>
#include <string>
#include <vector>
#include <limits>
using namespace std;
...
int inputValidate(int lowest, int highest)
{
int user_number;
do
{
if (!(cin >> user_number))
{
cout << "Invalid. Enter a valid number: ";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
else if (user_number < lowest || user_number > highest)
{
cout << "Error. Enter a number from " << lowest << " to " << highest << ": ";
}
else break;
}
while (true);
return user_number;
}
void player(char array[][ROWS_AND_COLUMNS], char letter)
{
int row, column;
do
{
cout << "Enter player " << letter << ", row and column:";
row = inputValidate(1, 3) - 1;
column = inputValidate(1, 3) - 1;
if (array[row][column] == '*')
break;
cout << "Sorry, that spot is taken." << endl;
}
while (true);
array[row][column] = letter;
}
Related
I'm learning C++, so I don't fully understand what's going on with my code here, but from what I've been able to glean, it seems like it could be some kind of buffer issue.
#include <stdio.h>
#include <vector>
#include <iostream>
#include <typeinfo>
using namespace std;
bool stopRun = true;
int height, average, total, count;
vector <int> heights;
int main ()
{
while (stopRun)
{
cout << "Enter a height, or 'end' to quit: ";
cin >> height;
if (typeid(height).name() == "i")
{
heights.push_back(height);
cout << heights[0];
count++;
}
else if (typeid(height).name() == "i")
{
cout << "\nPlease enter an integer: ";
continue;
}
if (count == 5)
{
stopRun = false;
}
}
for (int i = 0; i < heights.size(); i++)
{
total += heights[i];
cout << "\nTotal: " << total;
}
return 0;
}
For some reason, this code will continuously output: "Enter a height, or 'end' to quit: ". In an earlier version, it would output: "Enter a height, or 'end' to quit: Please enter an integer: ".
What I think is going on is that my "cin >> height;" line is pulling in the output from "Please enter an integer: " and treating it as my input, which identifies it as not being of type integer, which starts the infinite loop.
How do I clear the input buffer so that it doesn't bring in cout statements? Or is that even the issue I'm experiencing here?
Thanks in advance!
I suggest to catch the string. If string is not "end" then convert to number inside try/catch
you can use this function at the start of your program fflush(stdin). It will clear your input buffer.
You are attempting to read an int and a string in the same line of code. I suggest you use getline() to read the input and try to convert the string to int.
std::string input;
while (heights.size() != 5) {
cout << "Enter a height, or 'end' to quit: ";
if (std::getline(cin, input)) {
if (input == "end") break;
try {
heights.push_back(std::stoi(input));
}
catch (std::invalid_argument e) {
cout << "\nPlease enter an integer: ";
}
}
}
if (string(typeid(height).name()) == "i")
What you had wrong was the comparison of a pointer and string. Since typeid(height).name() returns a pointer to a c-string with the name for the object.
I was typing this and it asks the user to input two integers which will then become variables. From there it will carry out simple operations.
How do I get the computer to check if what is entered is an integer or not? And if not, ask the user to type an integer in. For example: if someone inputs "a" instead of 2, then it will tell them to reenter a number.
Thanks
#include <iostream>
using namespace std;
int main ()
{
int firstvariable;
int secondvariable;
float float1;
float float2;
cout << "Please enter two integers and then press Enter:" << endl;
cin >> firstvariable;
cin >> secondvariable;
cout << "Time for some simple mathematical operations:\n" << endl;
cout << "The sum:\n " << firstvariable << "+" << secondvariable
<<"="<< firstvariable + secondvariable << "\n " << endl;
}
You can check like this:
int x;
cin >> x;
if (cin.fail()) {
//Not an int.
}
Furthermore, you can continue to get input until you get an int via:
#include <iostream>
int main() {
int x;
std::cin >> x;
while(std::cin.fail()) {
std::cout << "Error" << std::endl;
std::cin.clear();
std::cin.ignore(256,'\n');
std::cin >> x;
}
std::cout << x << std::endl;
return 0;
}
EDIT: To address the comment below regarding input like 10abc, one could modify the loop to accept a string as an input. Then check the string for any character not a number and handle that situation accordingly. One needs not clear/ignore the input stream in that situation. Verifying the string is just numbers, convert the string back to an integer. I mean, this was just off the cuff. There might be a better way. This won't work if you're accepting floats/doubles (would have to add '.' in the search string).
#include <iostream>
#include <string>
int main() {
std::string theInput;
int inputAsInt;
std::getline(std::cin, theInput);
while(std::cin.fail() || std::cin.eof() || theInput.find_first_not_of("0123456789") != std::string::npos) {
std::cout << "Error" << std::endl;
if( theInput.find_first_not_of("0123456789") == std::string::npos) {
std::cin.clear();
std::cin.ignore(256,'\n');
}
std::getline(std::cin, theInput);
}
std::string::size_type st;
inputAsInt = std::stoi(theInput,&st);
std::cout << inputAsInt << std::endl;
return 0;
}
Heh, this is an old question that could use a better answer.
User input should be obtained as a string and then attempt-converted to the data type you desire. Conveniently, this also allows you to answer questions like “what type of data is my input?”
Here is a function I use a lot. Other options exist, such as in Boost, but the basic premise is the same: attempt to perform the string→type conversion and observe the success or failure:
template <typename T>
auto string_to( const std::string & s )
{
T value;
std::istringstream ss( s );
return ((ss >> value) and (ss >> std::ws).eof()) // attempt the conversion
? value // success
: std::optional<T> { }; // failure
}
Using the optional type is just one way. You could also throw an exception or return a default value on failure. Whatever works for your situation.
Here is an example of using it:
int n;
std::cout << "n? ";
{
std::string s;
getline( std::cin, s );
auto x = string_to <int> ( s );
if (!x) return complain();
n = *x;
}
std::cout << "Multiply that by seven to get " << (7 * n) << ".\n";
limitations and type identification
In order for this to work, of course, there must exist a method to unambiguously extract your data type from a stream. This is the natural order of things in C++ — that is, business as usual. So no surprises here.
The next caveat is that some types subsume others. For example, if you are trying to distinguish between int and double, check for int first, since anything that converts to an int is also a double.
There is a function in c called isdigit(). That will suit you just fine. Example:
int var1 = 'h';
int var2 = '2';
if( isdigit(var1) )
{
printf("var1 = |%c| is a digit\n", var1 );
}
else
{
printf("var1 = |%c| is not a digit\n", var1 );
}
if( isdigit(var2) )
{
printf("var2 = |%c| is a digit\n", var2 );
}
else
{
printf("var2 = |%c| is not a digit\n", var2 );
}
From here
If istream fails to insert, it will set the fail bit.
int i = 0;
std::cin >> i; // type a and press enter
if (std::cin.fail())
{
std::cout << "I failed, try again ..." << std::endl
std::cin.clear(); // reset the failed state
}
You can set this up in a do-while loop to get the correct type (int in this case) propertly inserted.
For more information: http://augustcouncil.com/~tgibson/tutorial/iotips.html#directly
You can use the variables name itself to check if a value is an integer.
for example:
#include <iostream>
using namespace std;
int main (){
int firstvariable;
int secondvariable;
float float1;
float float2;
cout << "Please enter two integers and then press Enter:" << endl;
cin >> firstvariable;
cin >> secondvariable;
if(firstvariable && secondvariable){
cout << "Time for some simple mathematical operations:\n" << endl;
cout << "The sum:\n " << firstvariable << "+" << secondvariable
<<"="<< firstvariable + secondvariable << "\n " << endl;
}else{
cout << "\n[ERROR\tINVALID INPUT]\n";
return 1;
}
return 0;
}
I prefer to use <limits> to check for an int until it is passed.
#include <iostream>
#include <limits> //std::numeric_limits
using std::cout, std::endl, std::cin;
int main() {
int num;
while(!(cin >> num)){ //check the Input format for integer the right way
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Invalid input. Reenter the number: ";
};
cout << "output= " << num << endl;
return 0;
}
Under C++11 and later, I have the found the std::stoi function very useful for this task. stoi throws an invalid_argument exception if conversion cannot be performed. This can be caught and handled as shown in the demo function 'getIntegerValue' below.
The stoi function has a second parameter 'idx' that indicates the position of the first character in the string after the number. We can use the value in idx to check against the string length and ascertain if there are any characters in the input other than the number. This helps eliminate input like 10abc or a decimal value.
The only case where this approach fails is when there is trailing white space after the number in the input, that is, the user enters a lot of spaces after inputting the number. To handle such a case, you could rtrim the input string as described in this post.
#include <iostream>
#include <string>
bool getIntegerValue(int &value);
int main(){
int value{};
bool valid{};
while(!valid){
std::cout << "Enter integer value: ";
valid = getIntegerValue(value);
if (!valid)
std::cout << "Invalid integer value! Please try again.\n" << std::endl;
}
std::cout << "You entered: " << value << std::endl;
return 0;
}
// Returns true if integer is read from standard input
bool getIntegerValue(int &value){
bool isInputValid{};
int valueFromString{};
size_t index{};
std::string userInput;
std::getline(std::cin, userInput);
try {
//stoi throws an invalid_argument exception if userInput cannot be
//converted to an integer.
valueFromString = std::stoi(userInput, &index);
//index being different than length of string implies additional
//characters in input that could not be converted to an integer.
//This is to handle inputs like 10str or decimal values like 10.12
if(index == userInput.length()) isInputValid = true;
}
catch (const std::invalid_argument &arg) {
; //you could show an invalid argument message here.
}
if (isInputValid) value = valueFromString;
return isInputValid;
}
You could use :
int a = 12;
if (a>0 || a<0){
cout << "Your text"<<endl;
}
I'm pretty sure it works.
Im trying to get the program to only accept x as an integer then ask for another integer, y. However when i enter a floating point into x it takes the decimal part of the input and makes that the y value. i am unsure of my mistake here.
#include <iostream>
#include <string>
#include <limits>
using namespace std;
int getInt()
{
int x = 0;
while (!(cin >> x))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Please input a proper 'whole' number: " << endl;
}
return (x);
}
int toobig()
{
cout << "Your number is too large, please enter something smaller: " << endl;
int x = getInt();
return (x);
}
int toosmall()
{
cout << "your number is negative, please enter a positive number: " << endl;
int x = getInt();
return (x);
}
int main()
{
cout << "your number please:-" << endl;
int x = getInt();
if (x>100000)
{
toobig();
}
else if (x<0)
{
toosmall();
}
int y = 0;
cout << "enter y " << endl;
cin >> y;
cout << "x = " << x << endl;
cout << "y = " << y << endl;
system("PAUSE");
return 0;
}
Most conversions to int stop as soon as they find something that can't be part of an int and only a few conversion functions tell you if they stop before parsing the whole string.
Let's use one of those few, shall we?
int getInt()
{
for ( ; ; ) // loop until user provides something we can use.
// This is dangerous. You probably want to give up after a while.
{
std::string input; // read in as string
if (std::cin >> input)
{
char * endp; // will be updated with pointer to where conversion stopped
errno = 0;
// convert string to int
long rval = std::strtol (input.c_str(), &endp, 10);
if (*endp == '\0') // check whole string was read
{
if (errno != ERANGE) // check converted number did not overflow long
{
if (rval >= std::numeric_limits<int>::min() &&
rval <= std::numeric_limits<int>::max())
// check converted number did not overflow int
// you could replace this min and max with your own passed-in
// min and max values if you want
{
return rval; // return the known-to-be-good int
}
}
}
}
else
{ // note: usually when cin fails to read a string, it's over.
// This is actually a good time to throw an exception because this
// just shouldn't happen.
std::cin.clear(); // but for now we'll just clear the error and
// probably enter an infinite loop of failure
}
// failed for any reason. Blow off all user input and re-prompt
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Please input a proper 'whole' number: " << std::endl;
}
return 0; // to satisfy compiler because a non-void function must always return.
// Never reached because of infinite for loop.
}
since every console input on C++ is treated as a string, then under your getInt() method I would do the following:
int GetInt(istream &stream)
{
char obtainChar; //read a character from input
int x;
stream >> x;
while(stream.fail() || (stream.peek() != '\r' && stream.peek() != '\n'))
{
stream.clear(); //clear the fail state of stream
obtainChar = stream.get(); //read a character from input
while(obtainChar != '\n' && obtainChar != EOF) //while gotten char is not a return key or EOF
obtainChar = stream.get(); //read a character from input iterate up to '\n' or EOF
//displays an error message if there was a bad input (e.g. decimal value)
cerr << endl << "Please input a proper 'whole' number: " << endl;
cout << endl << "Please re-enter x: "; //re-prompt to re-enter a value
x = GetInt(stream); //Try again by calling the function again (recursion)
}
return x; //will return after the user enters ONLY if an integer was inputted
}
the first while is basically saying, if the stream (console input) does fails or the next stream char (.peek()) is not a \r or a \n the clear the stream and get the first character.
while that char is not a \n and not End Of File (EOF) then obtain the next char, so on and so forth.
if a problem occurred then display a error message to the user and re-prompt the user for the value of x.
then call the same function to re-test the input (recursively), if all is well then return the value of x.
you can now call this function to evaluate the value of Y.
NOTE: istream is part of the iostream library is basically cin
NOTE: call the function like so:
int x;
cout << "your number please:-" << endl;
x = GetInt(cin);
is it possible, say your trying to do calculations so the primary variable type may be int... but as a part of the program you decide to do a while loop and throw an if statement for existing purposes.
you have one cin >> and that is to take in a number to run calculations, but you also need an input incase they want to exit:
Here's some code to work with
#include <iostream>
using namespace std;
int func1(int x)
{
int sum = 0;
sum = x * x * x;
return sum;
}
int main()
{
bool repeat = true;
cout << "Enter a value to cube: " << endl;
cout << "Type leave to quit" << endl;
while (repeat)
{
int input = 0;
cin >> input;
cout << input << " cubed is: " << func1(input) << endl;
if (input = "leave" || input = "Leave")
{
repeat = false;
}
}
}
I'm aware they wont take leave cause input is set to int, but is it possible to use a conversion or something...
another thing is there a better way to break the loop or is that the most common way?
One way to do this is read a string from cin. Check its value. If it satisfies the exit condition, exit. If not, extract the integer from the string and proceed to procss the integer.
while (repeat)
{
string input;
cin >> input;
if (input == "leave" || input == "Leave")
{
repeat = false;
}
else
{
int intInput = atoi(input.c_str());
cout << input << " cubed is: " << func1(intInput) << endl;
}
}
You can read the input as a string from the input stream. Check if it is 'leave' and quit.. and If it is not try to convert it to a number and call func1.. look at atoi or boost::lexical_cast<>
also it is input == "leave" == is the equal operator. = is an assignment operator.
int main() {
cout << "Enter a value to cube: " << endl;
cout << "Type leave to quit" << endl;
while (true)
{
string input;
cin >> input;
if (input == "leave" || input == "Leave")
{
break;
}
cout << input << " cubed is: " << func1(atoi(input.c_str())) << endl;
}
}
you can use like
int input;
string s;
cint>>s; //read string from user
stringstream ss(s);
ss>>input; //try to convert to an int
if(ss==0) //not an integer
{
if(s == "leave") {//user don't want to enter further input
//exit
}
else
{
//invalid data some string other than leave and not an integer
}
}
else
{
cout<<"Input:"<<input<<endl;
//input holds an int data
}
I am trying to have a loop continue to prompt the user for an option. When I get a string of characters instead of an int, the program loops indefinitely. I have tried setting the variable result to NULL, clearing the input stream, and have enclosed in try{}catch blocks (not in this example). Can anyone explain to me why this is?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int menu(string question, vector<string> options)
{
int result;
cout << question << endl;
for(int i = 0; i < options.size(); i++)
{
cout << '[' << i << ']' << options[i] << endl;
}
bool ans = false;
do
{
cin >> result;
cin.ignore(1000, 10);
if (result < options.size() )
{
ans = true;
}
else
{
cout << "You must enter a valid option." << endl;
result = NULL;
ans = false;
}
}
while(!ans);
return result;
}
int main()
{
string menuQuestion = "Welcome to my game. What would you like to do?";
vector<string> mainMenu;
mainMenu.push_back("Play Game");
mainMenu.push_back("Load Game");
mainMenu.push_back("About");
mainMenu.push_back("Exit");
int result = menu(menuQuestion, mainMenu);
cout << "You entered: " << result << endl;
return 0;
}
It looks like there is a random element here, since result is not initialized.
In any case, test cin directly
if ( cin && result < options.size() )
and reset it upon invalid input so it will again perform I/O operations
result = 0; // inappropriate to initialize an integer with NULL
cin.clear(); // reset cin to work again
cin.ignore(1000, '\n'); // use \n instead of ASCII code