Can I tell if a std::string represents a number using stringstream?
Apparently this is suposed to work in showing if a string is numerical, for example "12.5" == yes, "abc" == no. However I get a no reguardless of the input.
std::stringstream ss("2");
double d; ss >> d;
if(ss.good()) {std::cout<<"number"<<开发者_JAVA技巧std::endl;}
else {std::cout<<"other"<<std::endl;}
Don't use good()! Test if the stream is failed or not:
if (ss)
Good tells you if any of eofbit, badbit, or failbit are set, while fail() tells you about badbit and failbit. You almost never care about eofbit unless you already know the stream is failed, so you almost never want to use good.
Note that testing the stream directly, as above, is exactly equivalent to:
if (!ss.fail())
Conversely, !ss is equivalent to ss.fail().
Combining the extraction into the conditional expression:
if (ss >> d) {/*...*/}
Is exactly equivalent to:
ss >> d;
if (ss) {/*...*/}
However, you probably want to test if the complete string can be converted to a double, which is a bit more involved. Use boost::lexical_cast which already handles all of the cases.
If you want to check whether a string
contains only a number and nothing else (except whitespace), use this:
#include <sstream>
bool is_numeric (const std::string& str) {
std::istringstream ss(str);
double dbl;
ss >> dbl; // try to read the number
ss >> std::ws; // eat whitespace after number
if (!ss.fail() && ss.eof()) {
return true; // is-a-number
} else {
return false; // not-a-number
}
}
The ss >> std::ws
is important for accepting numbers with trailing whitespace such as "24 "
.
The ss.eof()
check is important for rejecting strings like "24 abc"
. It ensures that we reached the end of the string after reading the number (and whitespace).
Test harness:
#include <iostream>
#include <iomanip>
int main()
{
std::string tests[8] = {
"", "XYZ", "a26", "3.3a", "42 a", "764", " 132.0", "930 "
};
std::string is_a[2] = { "not a number", "is a number" };
for (size_t i = 0; i < sizeof(tests)/sizeof(std::string); ++i) {
std::cout << std::setw(8) << "'" + tests[i] + "'" << ": ";
std::cout << is_a [is_numeric (tests[i])] << std::endl;
}
}
Output:
'': not a number
'XYZ': not a number
'a26': not a number
'3.3a': not a number
'42 a': not a number
'764': is a number
' 132.0': is a number
'930 ': is a number
You should use an istringstream
so that it knows it's trying to parse input. Also, just check the result of the extraction directly rather than using good
later.
#include <sstream>
#include <iostream>
int main()
{
std::istringstream ss("2");
double d = 0.0;
if(ss >> d) {std::cout<<"number"<<std::endl;}
else {std::cout<<"other"<<std::endl;}
}
int str2int (const string &str) {
stringstream ss(str);
int num;
if((ss >> num).fail())
{
//ERROR: not a number
}
return num;
}
精彩评论