I have a string which can be either a double, float or int. I would like to convert the string to the data type by making function calls. I am currently using functions such as stof and stoi which throw exceptions when the input is not a float or int. Is there another way to convert the strings without having to catch exceptions? Perhaps some function that passes a a pointer to a float as argument and just returns a boolean which represents the success of the function of call. I would like to avoid using any try catch statements in any of my code.
Use a std::stringstream and capture the result of operator>>().
For example:
#include <string>
#include <iostream>
#include <sstream>
int main(int, char*[])
{
std::stringstream sstr1("12345");
std::stringstream sstr2("foo");
int i1(0);
int i2(0);
//C++98
bool success1 = sstr1 >> i1;
//C++11 (previous is forbidden in c++11)
success1 = sstr1.good();
//C++98
bool success2 = sstr2 >> i2;
//C++11 (previous is forbidden in c++11)
success2 = sstr2.good();
std::cout << "i1=" << i1 << " success=" << success1 << std::endl;
std::cout << "i2=" << i2 << " success=" << success2 << std::endl;
return 0;
}
Prints:
i1=12345 success=1
i2=0 success=0
Note, this is basically what boost::lexical_cast does, except that boost::lexical_cast throws a boost::bad_lexical_cast exception on failure instead of using a return code.
See: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast.html
For std::stringstream::good, see: http://www.cplusplus.com/reference/ios/ios/good/
To avoid exceptions, go back to a time when exceptions didn't exist. These functions were carried over from C but they're still useful today: strtod and strtol. (There's also a strtof but doubles will auto-convert to float anyway). You check for errors by seeing if the decoding reached the end of the string, as indicated by a zero character value.
char * pEnd = NULL;
double d = strtod(str.c_str(), &pEnd);
if (*pEnd) // error was detected
Mark Ransom, you hit the nail on the head. I understand RagHaven because in certain situations exceptions are a nuisance, and converting alphanumeric chains to doubles should be something light and fast, not subject to the exception handling mechanism. I found that a five-alphanumeric string sorting algorithm took more than 3 seconds because exceptions were thrown in the process and somewhere in the software something was complaining.
In my search for conversion functions without launching exceptions I found this (I work with C++ Builder):
double StrToFloatDef(string, double def);
That function tries to return a float, and, if it does not succeed, instead of launching an exception it returns the value that is passed in the 2nd argument (which could for example be put to std::numeric_limits<double>::max()). Checking if the return value matches 'def' you can control the result without exceptions.
Mark's proposal, std::strtod, is just as good but much faster, standard and safe. A function like the one RagHaven asks for could look like this:
bool AsDouble(const char* s, double& v) const noexcept
{
char* pEnd = nullptr;
v = std::strtod(s, &pEnd);
return *pEnd == 0;
}
Related
I'm trying to convert std::string to float/double.
I tried:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
But it always returns zero. Any other ways?
std::string num = "0.6";
double temp = ::atof(num.c_str());
Does it for me, it is a valid C++ syntax to convert a string to a double.
You can do it with the stringstream or boost::lexical_cast but those come with a performance penalty.
Ahaha you have a Qt project ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Extra note:
If the input data is a const char*, QByteArray::toDouble will be faster.
The Standard Library (C++11) offers the desired functionality with std::stod :
std::string s = "0.6"
std::wstring ws = "0.7"
double d = std::stod(s);
double dw = std::stod(ws);
Generally for most other basic types, see <string>. There are some new features for C strings, too. See <stdlib.h>
Lexical cast is very nice.
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
using std::endl;
using std::cout;
using std::string;
using boost::lexical_cast;
int main() {
string str = "0.6";
double dub = lexical_cast<double>(str);
cout << dub << endl;
}
You can use std::stringstream:
#include <sstream>
#include <string>
template<typename T>
T StringToNumber(const std::string& numberAsString)
{
T valor;
std::stringstream stream(numberAsString);
stream >> valor;
if (stream.fail()) {
std::runtime_error e(numberAsString);
throw e;
}
return valor;
}
Usage:
double number= StringToNumber<double>("0.6");
Yes, with a lexical cast. Use a stringstream and the << operator, or use Boost, they've already implemented it.
Your own version could look like:
template<typename to, typename from>to lexical_cast(from const &x) {
std::stringstream os;
to ret;
os << x;
os >> ret;
return ret;
}
You can use boost lexical cast:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
Note: boost::lexical_cast throws exception so you should be prepared to deal with it when you pass invalid value, try passing string("xxx")
If you don't want to drag in all of boost, go with strtod(3) from <cstdlib> - it already returns a double.
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main() {
std::string num = "0.6";
double temp = ::strtod(num.c_str(), 0);
cout << num << " " << temp << endl;
return 0;
}
Outputs:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
Why atof() doesn't work ... what platform/compiler are you on?
I had the same problem in Linux
double s2f(string str)
{
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
}
it works.
With C++17, you can use std::from_chars, which is a lighter weight faster alternative to std::stof and std::stod. It doesn't involve any memory allocation or look at the locale, and it is non-throwing.
The std::from_chars function returns a value of type from_chars_result, which is basically a struct with two fields:
struct from_chars_result {
const char* ptr;
std::errc ec;
};
By inspecting ec we can tell if the conversion was successful:
#include <iostream>
#include <charconv>
int main()
{
const std::string str { "12345678901234.123456" };
double value = 0.0;
auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
if (ec != std::errc()) {
std::cout << "Couldn't convert value";
}
return 0;
}
NB: you need a fairly up-to-date compiler (e.g. gcc11) for std::from_chars to work with floating point types.
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
The C++ 11 way is to use std::stod and std::to_string. Both work in Visual Studio 11.
This answer is backing up litb in your comments. I have profound suspicions you are just not displaying the result properly.
I had the exact same thing happen to me once. I spent a whole day trying to figure out why I was getting a bad value into a 64-bit int, only to discover that printf was ignoring the second byte. You can't just pass a 64-bit value into printf like its an int.
As to why atof() isn't working in the original question: the fact that it's cast to double makes me suspicious. The code shouldn't compile without #include <stdlib.h>, but if the cast was added to solve a compile warning, then atof() is not correctly declared. If the compiler assumes atof() returns an int, casting it will solve the conversion warning, but it will not cause the return value to be recognized as a double.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
should work without warnings.
Rather than dragging Boost into the equation, you could keep your string (temporarily) as a char[] and use sprintf().
But of course if you're using Boost anyway, it's really not too much of an issue.
You don't want Boost lexical_cast for string <-> floating point anyway. That subset of use cases is the only set for which boost consistently is worse than the older functions- and they basically concentrated all their failure there, because their own performance results show a 20-25X SLOWER performance than using sscanf and printf for such conversions.
Google it yourself. boost::lexical_cast can handle something like 50 conversions and if you exclude the ones involving floating point #s its as good or better as the obvious alternatives (with the added advantage of being having a single API for all those operations). But bring in floats and its like the Titanic hitting an iceberg in terms of performance.
The old, dedicated str->double functions can all do 10000 parses in something like 30 ms (or better). lexical_cast takes something like 650 ms to do the same job.
My Problem:
Locale independent string to double (decimal separator always '.')
Error detection if string conversion fails
My solution (uses the Windows function _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";
// Use this for error detection
wchar_t* stopString;
// Create a locale for "C". Thus a '.' is expected as decimal separator
double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C"));
if (wcslen(stopString) != 0)
{
// ... error handling ... we'll run into this because of the separator
}
HTH ... took me pretty long to get to this solution. And I still have the feeling that I don't know enough about string localization and stuff...
I'm working on a project where I want to accept an input of the form {float}{single-letter-identifier}, for example 15.6E, or 10W.
To do this, I thought that I could take the input string, strip off the last letter and then check to see if a conversion could be performed to float, using std::stof. This would be nested in a try-catch block, and allow me to notify the user of invalid input.
The open-standard of the STL here (page 653) states that std::stof throws:
invalid_argument if wcstod or wcstold reports that no conversion could be performed.
However, it doesn't throw when passed something it cannot convert, e.g. "48East". A code sample to reproduce this behavior is below:
std::wstring szString = L"48East";
try{
float f = std::stof(szString);
} catch( ... )
{
std::cout << "test" << std::endl;
}
This is compiled on MSVC10 in debug mode with /Od, so I'm assuming the call is not optimized away.
I'd appreciate any help (or guidance as to where I've misunderstood/misread the spec!).
As I read it, stof converts as much of the input string as it can until it finds something it can't convert. if it can't convert anything it throws invalid_argument.
The MSVC implementation parses the valid characters from the beginning and converts them successfully so your result is 48F in the above case. If instead you had "East48" you would get the invalid argument exception as expected.
Edit: Furthermore if you pass the optional index out parameter the function will report the index of the insignificant characters not used for the conversion. In the above example this would allow you to do something like this:
std::wstring szString = L"48East";
try{
size_t i(0);
float f = std::stof(szString, &i);
std::cout << f << szString.substr(i).c_str() << std::endl;
} catch( ... )
{
std::cout << L"test" << std::endl;
}
which produces the output 48East
I am writing a program that converts a parathensized expression into a mathematical one, and evaluates it. I've got the calculation bit written already.
I am using a stack for the operands, and a queue for the numbers. Adding operands to the stack isn't an issue, but I need to identify whether the input character is an integer, and if so, add it to the queue. Here's some code:
cout << "Enter the numbers and operands for the expression";
string aString;
do
{
cin >> aString
if (aString = int) // function to convert to read if int, convert to int
{
c_str(...);
atoi(...);
istack.push(int);
}
}
That's where I'm stuck now. I know I'm going to have to use c_str and atoi to convert it to an int. Am I taking the wrong approach?
Use the .fail() method of the stream.
If you need the string too, you can read to a string first, then attempt to convert the string to an integer using a stringstream object and check .fail() on the stringstream to see if the conversion could be done.
cin >> aString;
std::stringstream ss;
ss << aString;
int n;
ss >> n;
if (!ss.fail()) {
// int;
} else {
// not int;
}
I'll probably get flamed for this by the C++ purists.
However, sometimes the C++ library is just more work than the C library. I offer this
solution to C developers out there. And C++ developers who don't mind using some of the
features of the C library.
The whole check and conversion can be done in 1 line of C using the sscanf function.
int intval;
cin >> aString
if (sscanf(aString.c_str(), "%d", &intval)){
istack.push(intval);
}
sscanf returns the number of input arguments matched and assigned. So in this case, it's looking for one standard signed int value. If sscanf returns 1 then it succeeded in assigning the value. If it returns 0 then we don't have an int.
If you expect an integer, I would use boost::lexical_cast.
std::string some_string = "345";
int val = boost::lexical_cast<int>(some_string);
If it fails to cast to an integer, it will throw. The performance is pretty reasonable, and it keeps your code very clean.
I am unaware of any non-throwing version. You could use something like this, though I usually try to avoid letting exceptions control program flow.
bool cast_nothrow(const std::string &str, int &val) {
try {
val = boost::lexical_cast<int>(str);
return true;
} catch (boost::bad_lexical_cast &) {
return false;
}
}
Edit:
I would not recommend your integer validation checking for structure like you described. Good functions do one thing and one thing well.
Usually you'd want a more formal grammar parser to handle such things. My honest advice is to embed a scripting language or library in your project. It is non-trivial, so let someone else do the hard work.
If I actually tried to implement what you propose, I would probably do a stack based solution keeping the parenthesis levels at their own stack frame. The simplest thing would just be to hard code the simple operators (parenthesis, add, sub, etc) and assume that the rest of everything is a number.
Eventually you'd want everything broken down into some expression type. It might look something like this:
struct Expression {
virtual ~Expression() {}
virtual float value() const = 0;
};
struct Number : public Expression {
virtual float value() const {return val;}
float val;
};
struct AdditionOper : public Expression {
virtual float value() const {return lhs->value() + rhs->value();}
boost::shared_ptr<Expression> lhs;
boost::shared_ptr<Expression> rhs;
};
I'd start by parsing out the parenthesis, they will determine the order of your expressions. Then I'd split everything based on the numerical operands and start putting them in expressions. Then you're left with cases like 3 + 4 * 6 which would require some some care to get the order of operations right.
Good luck.
You can either run your function that converts a string representation of a number to a double and see if there's an error, or you can look at the contents of the string and see if it matches the pattern of a number and then do the conversion.
You might use boost::lexical_cast<double>() or std::stod() (C++11) where errors are reported with an exception, or istringstream extractors where the error is reported by setting the fail bit, or with C conversion functions that report errors by setting the global (thread local, rather) variable errno.
try {
istack.push_back(std::stod(aString));
} catch(std::invalid_argument &e) {
// aString is not a number
}
or
errno = 0;
char const *s = aString.c_str();
char *end;
double result = strtod(s,&end);
if(EINVAL==errno) {
// the string is not a number
} else {
istack.push_back(result);
}
An implementation of the second option might use a regex to see if the string matches the pattern you use for numbers, and if it does then running your conversion function. Here's an example of a pattern you might expect for floating point values:
std::regex pattern("[+-]?(\d*.\d+|\d+.?)([eE][+-]?\d+)?");
if(std::regex_match(aString,pattern)) {
istack.push_back(std::stod(aString));
} else {
// aString is not a number
}
Also, this probably doesn't matter to you, but most any built in method for converting a string to a number will be locale sensitive one way or another. One way to isolate yourself from this is to use a stringstream you create and imbue with the classic locale.
I guess the C++ (no boost) way would be this :
do
{
std::stringstream ss;
std::string test;
cin >> test;
ss << test;
int num;
if (ss >> num) // function to convert to read if int, convert to int
{
std::cout << "Number : " << num << "\n";
}
}while(true); // don't do this though..
Can you not use ctype.h http://www.cplusplus.com/reference/clibrary/cctype/. I have used this before and did not get into trouble.
Especially if you're doing base-10 input, I find the most blatant thing to do is read the string, then check that it only contains valid characters:
string s;
cin >> s;
if(strrspn(s.c_str(), "0123456789")==s.length()){
//int
} else{
//not int
}
I'm trying to figure out how to print a string several times. I'm getting errors. I just tried the line:
cout<<"This is a string. "*2;
I expected the output: "This is a string. This is a string.", but I didn't get that. Is there anything wrong with this line? If not, here's the entire program:
#include <iostream>
using namespace std;
int main()
{
cout<<"This is a string. "*2;
cin.get();
return 0;
}
My compiler isn't open because I am doing virus scans, so I can't give the error message. But given the relative simplicity of this code for this website, I'm hoping someone will know if I am doing anything wrong by simply looking.
Thank you for your feedback.
If you switch to std::string, you can define this operation yourself:
std::string operator*(std::string const &s, size_t n)
{
std::string r; // empty string
r.reserve(n * s.size());
for (size_t i=0; i<n; i++)
r += s;
return r;
}
If you try
std::cout << (std::string("foo") * 3) << std::endl
you'll find it prints foofoofoo. (But "foo" * 3 is still not permitted.)
There is an operator+() defined for std::string, so that string + string gives stringstring, but there is no operator*().
You could do:
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string str = "This is a string. ";
cout << str+str;
cin.get();
return 0;
}
As the other answers pointed there's no multiplication operation defined for strings in C++ regardless of their 'flavor' (char arrays or std::string). So you're left with implementing it yourself.
One of the simplest solutions available is to use the std::fill_n algorithm:
#include <iostream> // for std::cout & std::endl
#include <sstream> // for std::stringstream
#include <algorithm> // for std::fill_n
#include <iterator> // for std::ostream_iterator
// if you just need to write it to std::cout
std::fill_n( std::ostream_iterator< const char* >( std::cout ), 2, "This is a string. " );
std::cout << std::endl;
// if you need the result as a std::string (directly)
// or a const char* (via std::string' c_str())
std::stringstream ss;
std::fill_n( std::ostream_iterator< const char* >( ss ), 2, "This is a string. " );
std::cout << ss.str();
std::cout << std::endl;
Indeed, your code is wrong.
C++ compilers treat a sequence of characters enclosed in " as a array of characters (which can be multibyte or singlebyte, depending on your compiler and configuration).
So, your code is the same as:
char str[19] = "This is a string. ";
cout<<str * 2;
Now, if you check the second line of the above snippet, you'll clearly spot something wrong. Is this code multiplying an array by two? should pop in your mind. What is the definition of multiplying an array by two? None good.
Furthermore, usually when dealing with arrays, C++ compilers treat the array variable as a pointer to the first address of the array. So:
char str[19] = "This is a string. ";
cout<<0xFF001234 * 2;
Which may or may not compile. If it does, you code will output a number which is the double of the address of your array in memory.
That's not to say you simply can't multiply a string. You can't multiply C++ strings, but you can, with OOP, create your own string that support multiplication. The reason you will need to do that yourself is that even std strings (std::string) doesn't have a definition for multiplication. After all, we could argue that a string multiplication could do different things than your expected behavior.
In fact, if need be, I'd write a member function that duplicated my string, which would have a more friendly name that would inform and reader of its purpose. Using non-standard ways to do a certain thing will ultimately lead to unreadable code.
Well, ideally, you would use a loop to do that in C++. Check for/while/do-while methods.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count;
for (count = 0; count < 5; count++)
{
//repeating this 5 times
cout << "This is a string. ";
}
return 0;
}
Outputs:
This is a string. This is a string. This is a string. This is a string. This is a string.
Hey there, I'm not sure that that would compile. (I know that would not be valid in c# without a cast, and even then you still would not receive the desired output.)
Here would be a good example of what you are trying to accomplish. The OP is using a char instead of a string, but will essentially function the same with a string.
Give this a whirl:
Multiply char by integer (c++)
cout<<"This is a string. "*2;
you want to twice your output. Compiler is machine not a human. It understanding like expression and your expression is wrong and generate an error .
error: invalid operands of types
'const char [20]' and 'int' to binary
'operator*'
I'm trying to convert std::string to float/double.
I tried:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
But it always returns zero. Any other ways?
std::string num = "0.6";
double temp = ::atof(num.c_str());
Does it for me, it is a valid C++ syntax to convert a string to a double.
You can do it with the stringstream or boost::lexical_cast but those come with a performance penalty.
Ahaha you have a Qt project ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Extra note:
If the input data is a const char*, QByteArray::toDouble will be faster.
The Standard Library (C++11) offers the desired functionality with std::stod :
std::string s = "0.6"
std::wstring ws = "0.7"
double d = std::stod(s);
double dw = std::stod(ws);
Generally for most other basic types, see <string>. There are some new features for C strings, too. See <stdlib.h>
Lexical cast is very nice.
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
using std::endl;
using std::cout;
using std::string;
using boost::lexical_cast;
int main() {
string str = "0.6";
double dub = lexical_cast<double>(str);
cout << dub << endl;
}
You can use std::stringstream:
#include <sstream>
#include <string>
template<typename T>
T StringToNumber(const std::string& numberAsString)
{
T valor;
std::stringstream stream(numberAsString);
stream >> valor;
if (stream.fail()) {
std::runtime_error e(numberAsString);
throw e;
}
return valor;
}
Usage:
double number= StringToNumber<double>("0.6");
Yes, with a lexical cast. Use a stringstream and the << operator, or use Boost, they've already implemented it.
Your own version could look like:
template<typename to, typename from>to lexical_cast(from const &x) {
std::stringstream os;
to ret;
os << x;
os >> ret;
return ret;
}
You can use boost lexical cast:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
Note: boost::lexical_cast throws exception so you should be prepared to deal with it when you pass invalid value, try passing string("xxx")
If you don't want to drag in all of boost, go with strtod(3) from <cstdlib> - it already returns a double.
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main() {
std::string num = "0.6";
double temp = ::strtod(num.c_str(), 0);
cout << num << " " << temp << endl;
return 0;
}
Outputs:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
Why atof() doesn't work ... what platform/compiler are you on?
I had the same problem in Linux
double s2f(string str)
{
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
}
it works.
With C++17, you can use std::from_chars, which is a lighter weight faster alternative to std::stof and std::stod. It doesn't involve any memory allocation or look at the locale, and it is non-throwing.
The std::from_chars function returns a value of type from_chars_result, which is basically a struct with two fields:
struct from_chars_result {
const char* ptr;
std::errc ec;
};
By inspecting ec we can tell if the conversion was successful:
#include <iostream>
#include <charconv>
int main()
{
const std::string str { "12345678901234.123456" };
double value = 0.0;
auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
if (ec != std::errc()) {
std::cout << "Couldn't convert value";
}
return 0;
}
NB: you need a fairly up-to-date compiler (e.g. gcc11) for std::from_chars to work with floating point types.
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
The C++ 11 way is to use std::stod and std::to_string. Both work in Visual Studio 11.
This answer is backing up litb in your comments. I have profound suspicions you are just not displaying the result properly.
I had the exact same thing happen to me once. I spent a whole day trying to figure out why I was getting a bad value into a 64-bit int, only to discover that printf was ignoring the second byte. You can't just pass a 64-bit value into printf like its an int.
As to why atof() isn't working in the original question: the fact that it's cast to double makes me suspicious. The code shouldn't compile without #include <stdlib.h>, but if the cast was added to solve a compile warning, then atof() is not correctly declared. If the compiler assumes atof() returns an int, casting it will solve the conversion warning, but it will not cause the return value to be recognized as a double.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
should work without warnings.
Rather than dragging Boost into the equation, you could keep your string (temporarily) as a char[] and use sprintf().
But of course if you're using Boost anyway, it's really not too much of an issue.
You don't want Boost lexical_cast for string <-> floating point anyway. That subset of use cases is the only set for which boost consistently is worse than the older functions- and they basically concentrated all their failure there, because their own performance results show a 20-25X SLOWER performance than using sscanf and printf for such conversions.
Google it yourself. boost::lexical_cast can handle something like 50 conversions and if you exclude the ones involving floating point #s its as good or better as the obvious alternatives (with the added advantage of being having a single API for all those operations). But bring in floats and its like the Titanic hitting an iceberg in terms of performance.
The old, dedicated str->double functions can all do 10000 parses in something like 30 ms (or better). lexical_cast takes something like 650 ms to do the same job.
My Problem:
Locale independent string to double (decimal separator always '.')
Error detection if string conversion fails
My solution (uses the Windows function _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";
// Use this for error detection
wchar_t* stopString;
// Create a locale for "C". Thus a '.' is expected as decimal separator
double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C"));
if (wcslen(stopString) != 0)
{
// ... error handling ... we'll run into this because of the separator
}
HTH ... took me pretty long to get to this solution. And I still have the feeling that I don't know enough about string localization and stuff...