C++: converting wstring to double - c++

Before converting wstring to double - how to validate it with regex? Java no problem, but C++ raising questions.. :)

I suppose you have a string and you want to know if it is a double or not. The following code does not use regular expressions. Instead it initializes a stringstream and reads a double from it. If the string starts with something non-numeric, then ss.fail() will be set. If it starts with a number, but does not read the whole string, then there's something non-numeric at the end of the string. So if everything went well and the string is really only a number, then ss.eof() && !ss.fail() will be true.
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss("123.456");
double mydouble;
ss >> mydouble;
if (ss.eof() && !ss.fail())
std::cout << "yay, success: " << mydouble << std::endl;
else
std::cout << "that was not a double." << std::endl;
return 0;
}
There's also std::wstringstream if you need to convert wide character strings.
You might also want to have a look at the boost libraries, especially at Boost.Lexical_Cast.
With this library you could do the following:
#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{
try
{
double mydouble = boost::lexical_cast<double>("123.456");
std::cout << "yay, success: " << mydouble << std::endl;
}
catch(const boost::bad_lexical_cast &)
{
std::cout << "that was not a double." << std::endl;
}
return 0;
}

Or maybe it is simpler to do that this way:
std::wstring strKeyValue = "147.sd44";
double value = (double) _wtof(strKeyValue.c_str());
And if strKeyValue==0 then it means it's not double.

Related

Convert boost::multiprecision::cpp_dec_float_100 to string with precision

In my code I want to have a function which performs some calculations based on boost::multiprecision::cpp_dec_float_100 and returns string as a result with some precision, but the question is how I should set the precision ? e.g. If the precision is 9, then I expect the following results for the following numbers:
for 2345.12345678910111213 I expect string "2345.123456789" but I have 12345.1235
for 1.12345678910111213 I expect string "1.123456789" but I have 1.12345679
So it always returns my exact number of characters provided to str() function with round. I know that I can do it like e.g. this:
std::stringstream ss;
ss << std::fixed << std::setprecision(9) << my_value;
return ss.str();
or use cout(but this is not my case) or do some find on string to find "." and take only 9 characters after it, but can I do it in an easier way ? maybe in boost is some function to do it correctly ?
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace bmp = boost::multiprecision;
std::string foo_1()
{
bmp::cpp_dec_float_100 val{"12345.12345678910111213"};
return val.str(9);
}
std::string foo_2()
{
bmp::cpp_dec_float_100 val{"1.12345678910111213"};
return val.str(9);
}
int main()
{
auto const val_1 = foo_1();
auto const val_2 = foo_2();
std::cout << "val_1: " << val_1 << std::endl;
std::cout << "val_2: " << val_2 << std::endl;
return 0;
}
online version: https://wandbox.org/permlink/HTAHsE5ZE3tgK9kf
Change the line:
return val.str(9);
To:
return val.str(9, std::ios::fixed);
You will get the expected strings.

How to remove trailing zeros with scientific notation when convert double to string?

Live On Coliru
FormatFloat
I try to implement one conversion of Golang strconv.FormatFloat() in C++.
#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
std::string convert_str(double d)
{
std::stringstream ss;
if (d >= 0.0001)
{
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else
{
ss << std::scientific;
ss << d;
return ss.str();
}
}
int main()
{
std::cout << convert_str(0.002) << std::endl; // 0.0020
std::cout << convert_str(0.00001234560000) << std::endl; // 1.234560e-05
std::cout << convert_str(0.000012) << std::endl; // 1.200000e-05
return 0;
}
Output:
0.0020
1.234560e-05 // should be 1.23456e-05
1.200000e-05 // should be 1.2e-05
Question> How can I setup the output modifier so that the trailing zero doesn't show up?
strconv.FormatFloat(num, 'e', -1, 64)
The special precision value (-1) is used for the smallest number of
digits necessary such that ParseFloat() will return f exactly.
At the risk of being heavily downvoted criticised for posting a C answer to a C++ question ... you can use the %lg format specifier in a call to sprintf.
From cpprefernce:
Unless alternative representation is requested the trailing zeros are
removed, also the decimal point character is removed if no fractional
part is left.
So, if you only want to remove the trailing zeros when using scientific notation, you can change your convert_str function to something like the following:
std::string convert_str(double d)
{
if (d >= 0.0001) {
std::stringstream ss;
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else {
char cb[64];
sprintf(cb, "%lg", d);
return cb;
}
}
For the three test cases in your code, this will give:
0.0020
1.23456e-05
1.2e-05
From C++20 and later, the std::format class may offer a more modern alternative; however, I'm not (yet) fully "up to speed" with that, so I cannot present a solution using it. Others may want to do so.
Yes, std::scientific don't remove trailing zeros from scientific notation. The good news, for your specific case, is that cout already format values below 0.0001 using scientific notation, and removing trailing zeros. So you can let your code like this:
#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
std::string convert_str(double d)
{
std::stringstream ss;
if (d >= 0.0001)
{
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else
{
ss << d;
return ss.str();
}
}
int main()
{
std::cout << convert_str(0.002) << std::endl; // 0.0020
std::cout << convert_str(0.00001234560000) << std::endl; // 1.23456e-05
std::cout << convert_str(0.000012) << std::endl; // 1.2e-05
return 0;
}
The wanted output can be generated with a combination of the std::setprecision and std::defaultfloat manipulators:
std::cout << std::setprecision(16) << std::defaultfloat
<< 0.002 << '\n'
<< 0.00001234560000 << '\n'
<< 0.000012 << '\n';
Live at: https://godbolt.org/z/67fWa1seo

What am I doing wrong here with find and string?

I am asking user to enter date in format with slashes. Then I try to find the slashes in the string using find. I get error saying I cannot compare pointer with integer on my if statement. Here is code.
// test inputing string date formats
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string dateString;
int month,day,year;
std::cout << "Enter a date in format of 5/14/1999: ";
std::getline(std::cin,dateString);
std::cout << "You entered " << dateString << std::endl;
if (std::find(dateString.begin(),dateString.end(),"/") != dateString.end()) {
std::cout << "Found slash in date.\n";
}
else {
std::cout << "screwed it up.\n";
}
}
Any help is appreciated.
if (std::find(dateString.begin(),dateString.end(),"/") != dateString.end()) {
"/" is a literal string, or a const char * (actually a const char[2] in this case, to be pedantic, but this is not germane) . The third parameter to std::find, in this case, should be a char, a single character.
You probably meant
if (std::find(dateString.begin(),dateString.end(),'/') != dateString.end()) {
I think you can use
if (dateString.find("/") != std::string::npos) {
std::cout << "Found slash in date.\n";
} else {
std::cout << "screwed it up.\n";
}
to find substring/char in a string. Note that std::string::find() works for char, const char * and std::string.

c++ String is shortening double when printing

This string operation prints out a double in short-hand, and I can't work out why. Why is this happening, and how can I get the full output like the first line of output?
string myString = "The value is ";
ss.str(""); // stringstream from ealier
ss.clear();
ss << myDouble; // Double with value 0.000014577
myString.append(ss.str());
cout << myDouble << endl;
cout << myString << endl;
$ ./myapp
0.000014577
The value is 1.4577e-05
its default behaviour you should use precision to use fixed precision
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double v = 0.000014577;
cout << fixed << v << endl;
}
Try this:
using std::fixed;
...
ss.setf(fixed);
ss << myDouble;
...
That is because this is the default formatting, you can override it with precision.

Convert a string into a double, and a int. How to?

I'm having trouble converting a string into a double.
My string has been declared using the "string" function, so my string is:
string marks = "";
Now to convert it to a double I found somewhere on the internet to use word.c_str(), and so I did. I called it and used it like this:
doubleMARK = strtod( marks.c_str() );
This is similar to the example I found on the web:
n1=strtod( t1.c_str() );
Apparently, that's how it's done. But of course, it doesn't work. I need another parameter. A pointer I believe? But I'm lost at this point as to what I'm suppose to do. Does it need a place to store the value or something? or what?
I also need to convert this string into a integer which I have not begun researching as to how to do, but once I find out and if I have errors, I will edit this out and post them here.
Was there a reason you're not using std::stod and std::stoi? They are at least 9 levels more powerful than flimsy strtod.
Example
#include <iostream>
#include <string>
int main() {
using namespace std;
string s = "-1";
double d = stod(s);
int i = stoi(s);
cout << s << " " << d << " " << i << endl;
}
Output
-1 -1 -1
If you must use strtod, then just pass NULL as the second parameter. According to cplusplus.com:
If [the second parameter] is not a null pointer, the function also sets the value pointed by endptr to point to the first character after the number.
And it's not required to be non-NULL.
Back in the Bad Old Dark Days of C, I'd do something ugly and unsafe like this:
char sfloat[] = "1.0";
float x;
sscanf (sfloat, "%lf", &x);
In C++, you might instead do something like this:
// REFERENCE: http://www.codeguru.com/forum/showthread.php?t=231054
include <string>
#include <sstream>
#include <iostream>
template <class T>
bool from_string(T& t,
const std::string& s,
std::ios_base& (*f)(std::ios_base&))
{
std::istringstream iss(s);
return !(iss >> f >> t).fail();
}
int main()
{
int i;
float f;
// the third parameter of from_string() should be
// one of std::hex, std::dec or std::oct
if(from_string<int>(i, std::string("ff"), std::hex))
{
std::cout << i << std::endl;
}
else
{
std::cout << "from_string failed" << std::endl;
}
if(from_string<float>(f, std::string("123.456"), std::dec))
{
std::cout << f << std::endl;
}
else
{
std::cout << "from_string failed" << std::endl;
}
return 0;
}
Personally, though, I'd recommend this:
http://bytes.com/topic/c/answers/137731-convert-string-float
There are two ways. C gives you strtod which converts between a char
array and double:
// C-ish:
input2 = strtod(input.c_str(), NULL);
The C++ streams provide nice conversions to and from a variety of
types. The way to use strings with streams is to use a stringstream:
// C++ streams:
double input2;
istringstream in(input);
input >> input2;
We can define a stringTo() function,
#include <string>
#include <sstream>
template <typename T>
T stringTo(const std::string& s) {
T x;
std::istringstream in(s);
in >> x;
return x;
}
Then, use it like
std::cout << stringTo<double>("-3.1e3") << " " << stringTo<int>("4");