Floating point data unexpectedly succeeds on istream input into an integer
c++, double, int, templates
Solution
I'd try a slightly different take than you have. Specifically, I would not try to modify the error state of the input stream:
// Untested
template <class T> T clear_and_read(istream& inputstream) {
std::string inputString;
while(1) {
try {
// Grab one maximally-sized whitespace-delimited chunk of input
inputstream >> inputString;
// Note: lexical_cast throws if there are any extraneous characters.
return boost::lexical_cast<T>(inputString);
} catch (boost::bad_cast&) {
std::cout << "\nPlease ensure you are inputting correct data type. Suggested data type: "<< typeid(input).name() <<".\n";
}
}
}
Note: If you don't have boost available in your compilation environment, `lexical_cast` is fairly trivial to implement yourself. If you get stuck, just ask for help.
References:
- http://www.boost.org/doc/libs/1_49_0/doc/html/boost_lexical_cast.html
EDIT Here is a fully tested version, that does not rely upon Boost.
#include <exception>
#include <sstream>
#include <string>
#include <iostream>
#include <typeinfo>
template <class T> T clear_and_read(std::istream& inputstream) {
std::string inputString;
while(inputstream) {
// Grab one maximally-sized whitespace-delimited chunk of input
inputstream >> inputString;
std::istringstream itemstream(inputString);
// Convert it:
T t;
itemstream >> t;
// See if conversion worked and consumed everything
if(itemstream && (itemstream.get() == EOF)) {
// SUCCESS
return t;
}
// oops
std::cout << "\nPlease ensure you are inputting correct data type. Suggested data type: "<< typeid(T).name() <<".\n";
}
std::cout << "What to do with EOF?\n";
return T();
}
int main () {
clear_and_read<int>(std::cin);
clear_and_read<double>(std::cin);
}
Problem
I'm writing a template function that will check if the user has assigned the correct type of data that the answer should be in. For example: ``` int main(){ int E; cout<<"Enter an integer: "<<endl; E = clear_and_read<int>(cin); cout<<E<<endl; } ``` where the function `clear_and_read` is defined as: ``` template <class T> T clear_and_read(istream& inputstream){ cin.sync();//removes anything still in cin stream cin.clear(); T input; inputstream>>input; while(inputstream.fail()){ cout<<endl<<"Please ensure you are inputting correct data type. Suggested data type: "<< typeid(input).name() <<"."<<endl; cin.sync(); cin.clear(); inputstream>>input; } return input; } ``` Now this works if I try to enter a `string` instead of an `integer`, but when I enter a `double` it just assigns it's first value. e.g. 5.678 becomes 5. What can I do inside the template function to flag if a `double` is being read into an `int`?