I have the following code:
#include <string>
#include <iostream>
#include <sstream>
int main()
{
size_t x, y;
double a = std::stod("1_", &x);
double b = std::stod("1i", &y);
std::cout << "a: " << a << ", x: " << x << std::endl;
std::cout << "b: " << b << ", y: " << y << std::endl;
std::stringstream s1("1_");
std::stringstream s2("1i");
s1 >> a;
s2 >> b;
std::cout << "a: " << a << ", fail: " << s1.fail() << std::endl;
std::cout << "b: " << b << ", fail: " << s2.fail() << std::endl;
}
I want to parse a double and stop when an invalid character is hit. Here I try to parse "1_" and "1i", both of which should give me the double with value: 1.
here is my output:
a: 1, x: 1
b: 1, y: 1
a: 1, fail: 0
b: 0, fail: 1
So the stod function worked as expected, however the stringstream method did not. It makes no sense to me that 2 standard methods of parsing double, both in the standard library would give different results?
Why does the stringstream method fail when parsing: "1i"?
Edit:
this appears to give different results for some people. My compiler info is the following:
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Edit2:
Is this a bug with libc++, or is the specification just vague about what counts as valid parsing for a double?
This is a libc++ bug. Per [facet.num.get.virtuals] bullet 3.2, a character is only supposed to be accumulated if it is allowed as the next character of the input field of the conversion specifier determined in stage 1 (%g for double). Having accumulated 1, i is not allowed, so stage 2 should terminate.
libc++ is accumulating characters indiscriminately until it reaches a non-atom character (it also extended the atoms to include i, which is required to parse inf).
Related
I want to control the precision for a double during a comparison, and then come back to default precision, with C++.
I intend to use setPrecision() to set precision. What is then syntax, if any, to set precision back to default?
I am doing something like this
std::setPrecision(math.log10(m_FTOL));
I do some stuff, and I would like to come back to default double comparison right afterwards.
I modified like this, and I still have some errors
std::streamsize prec = std::ios_base::precision();
std::setprecision(cmath::log10(m_FTOL));
with cmath false at compilation, and std::ios_base also false at compilation. Could you help?
You can get the precision before you change it, with std::ios_base::precision and then use that to change it back later.
You can see this in action with:
#include <ios>
#include <iostream>
#include <iomanip>
int main (void) {
double d = 3.141592653589;
std::streamsize ss = std::cout.precision();
std::cout << "Initial precision = " << ss << '\n';
std::cout << "Value = " << d << '\n';
std::cout.precision (10);
std::cout << "Longer value = " << d << '\n';
std::cout.precision (ss);
std::cout << "Original value = " << d << '\n';
std::cout << "Longer and original value = "
<< std::setprecision(10) << d << ' '
<< std::setprecision(ss) << d << '\n';
std::cout << "Original value = " << d << '\n';
return 0;
}
which outputs:
Initial precision = 6
Value = 3.14159
Longer value = 3.141592654
Original value = 3.14159
Longer and original value = 3.141592654 3.14159
Original value = 3.14159
The code above shows two ways of setting the precision, first by calling std::cout.precision (N) and second by using a stream manipulator std::setprecision(N).
But you need to keep in mind that the precision is for outputting values via streams, it does not directly affect comparisons of the values themselves with code like:
if (val1== val2) ...
In other words, even though the output may be 3.14159, the value itself is still the full 3.141592653590 (subject to normal floating point limitations, of course).
If you want to do that, you'll need to check if it's close enough rather than equal, with code such as:
if ((fabs (val1 - val2) < 0.0001) ...
Use C++20 std::format and {:.2} instead of std::setprecision
Finally, this will be the superior choice once you can use it:
#include <format>
#include <string>
int main() {
std::cout << std::format("{:.3} {:.4}\n", 3.1415, 3.1415);
}
Expected output:
3.14 3.145
This will therefore completely overcome the madness of modifying std::cout state.
The existing fmt library implements it for before it gets official support: https://github.com/fmtlib/fmt Install on Ubuntu 22.04:
sudo apt install libfmt-dev
Modify source to replace:
<format> with <fmt/core.h>
std::format to fmt::format
main.cpp
#include <iostream>
#include <fmt/core.h>
int main() {
std::cout << fmt::format("{:.3} {:.4}\n", 3.1415, 3.1415);
}
and compile and run with:
g++ -std=c++11 -o main.out main.cpp -lfmt
./main.out
Output:
3.14 3.142
See also:
How do I print a double value with full precision using cout?
std::string formatting like sprintf
Pre C++20/fmt::: Save the entire state with std::ios::copyfmt
You might also want to restore the entire previous state with std::ios::copyfmt in these situations, as explained at: Restore the state of std::cout after manipulating it
main.cpp
#include <iomanip>
#include <iostream>
int main() {
constexpr float pi = 3.14159265359;
constexpr float e = 2.71828182846;
// Sanity check default print.
std::cout << "default" << std::endl;
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout << std::endl;
// Change precision format to scientific,
// and restore default afterwards.
std::cout << "modified" << std::endl;
std::ios cout_state(nullptr);
cout_state.copyfmt(std::cout);
std::cout << std::setprecision(2);
std::cout << std::scientific;
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout.copyfmt(cout_state);
std::cout << std::endl;
// Check that cout state was restored.
std::cout << "restored" << std::endl;
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout << std::endl;
}
GitHub upstream.
Compile and run:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Output:
default
3.14159
2.71828
modified
3.14e+00
2.72e+00
restored
3.14159
2.71828
Tested on Ubuntu 19.04, GCC 8.3.0.
You need to keep track of your current precison and then reset back to the same once done with your operations with required modified precison. For this you can use std::ios_base::precision:
streamsize precision ( ) const;
streamsize precision ( streamsize prec );
The first syntax returns the value of the current floating-point precision field for the stream.
The second syntax also sets it to a new value.
setprecision() can be used only for output operations and cannot be used for comparisons
To compare floats say a and b , you have to do it explicitly like this:
if( abs(a-b) < 1e-6) {
}
else {
}
You can use cout << setprecision(-1)
I'm simply trying stringstream in UTF-8:
#include<iostream>
#include<string>
#include<sstream>
int main()
{
std::basic_stringstream<char8_t> ss(u8"hello");
char8_t c;
std::cout << (ss.rdstate() & std::ios_base::goodbit) << " " << (ss.rdstate() & std::ios_base::badbit) << " "
<< (ss.rdstate() & std::ios_base::failbit) << " " << (ss.rdstate() & std::ios_base::eofbit) << "\n";
ss >> c;
std::cout << (ss.rdstate() & std::ios_base::goodbit) << " " << (ss.rdstate() & std::ios_base::badbit) << " "
<< (ss.rdstate() & std::ios_base::failbit) << " " << (ss.rdstate() & std::ios_base::eofbit) << "\n";
std::cout << c;
return 0;
}
Compile using:
g++-9 -std=c++2a -g -o bin/test test/test.cpp
The result on screen is:
0 0 0 0
0 1 4 0
0
It seems that something goes wrong when reading c, but I don't know how to correct it. Please help me!
This is actually an old issue not specific to support for char8_t. The same issue occurs with char16_t or char32_t in C++11 and newer. The following gcc bug report has a similar test case.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88508
The issue is also discussed at the following:
GCC 4.8 and char16_t streams - bug?
Why does `std::basic_ifstream<char16_t>` not work in c++11?
http://gcc.1065356.n8.nabble.com/UTF-16-streams-td1117792.html
The issue is that gcc does not implicitly imbue the global locale with facets for ctype<char8_t>, ctype<char16_t>, or ctype<char32_t>. When attempting to perform an operation that requires one of these facets, a std::bad_cast exception is thrown from std::__check_facet (which is subsequently silently swallowed by the IOS sentry object created for the character extraction operator and which then sets badbit and failbit).
The C++ standard only requires that ctype<char> and ctype<wchar_t> be provided. See [locale.category]p2.
The following code gives different results with the g++ 7 compiler and Apple clang++. Did I run into a bug in clang in the alignment of bool output when std::boolalpha is used, or did I make a mistake?
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
template<typename T>
void print_item(std::string name, T& item) {
std::ostringstream ss;
ss << std::left << std::setw(30) << name << "= "
<< std::right << std::setw(11) << std::setprecision(5)
<< std::boolalpha << item << " (blabla)" << std::endl;
std::cout << ss.str();
}
int main() {
int i = 34;
std::string s = "Hello!";
double d = 2.;
bool b = true;
print_item("i", i);
print_item("s", s);
print_item("d", d);
print_item("b", b);
return 0;
}
The difference is:
// output from g++ version 7.2
i = 34 (blabla)
s = Hello! (blabla)
d = 2 (blabla)
b = true (blabla)
// output from Apple clang++ 8.0.0
i = 34 (blabla)
s = Hello! (blabla)
d = 2 (blabla)
b = true (blabla)
At T.C. mentioned, this is LWG 2703:
No provision for fill-padding when boolalpha is set
N4582 subclause 25.4.2.2.2 [facet.num.put.virtuals] paragraph 6 makes
no provision for fill-padding in its specification of the behaviour
when (str.flags() & ios_base::boolalpha) != 0.
As a result I do not see a solution to this with Clang. However, notice that:
libc++ implements this exactly.
libstdc++ and MSVC apply padding and alignment.
PS: LWG stands for Library Working Group.
In C a space can be included in a printf formatting flag which results in positive numbers being prefixed with a space. This is a useful feature for aligning signed values. I can't figure out how to do the same in C++. In C:
double d = 1.2;
printf("%f\n",d);
printf("%+f\n",d);
printf("% f\n",d);
produces:
1.2
+1.2
1.2
Using ostream, I can do the first two, but how do I do the third?
int d = 1.2;
std::cout << d << std::endl;
std::cout << std::showpos << d << std::endl;
// ??????????????
EDIT: There seems to be some confusion about whether or not I just want to prefix all of my values with a space. I only want to prefix positive values with a space, similar to a) like the printf space flag does and b) similar to what showpos does, except a space rather than a '+'. For example:
printf("%f\n", 1.2);
printf("%f\n", -1.2);
printf("% f\n", 1.2);
printf("% f\n", -1.2);
1.2
-1.2
1.2
-1.2
Note that the third value is prefixed with a space while the fourth (negative) value is not.
You can use setfill and setw, like this:
cout << setw(4) << setfill(' ') << 1.2 << endl;
cout << setw(4) << setfill(' ') << -1.2 << endl;
This produces the following output:
1.2
-1.2
Don't forget to include <iomanip> in order for this to compile (link to ideone).
I don't have my standard with me and I'm doing this stuff too rarely to be confident about it: There are two ingredients to achieving this with IOStreams:
Use std:: showpos to have an indicator of positive values be shown. By default this will use +, of course.
I think the + is obtained using std::use_facet<std::ctype<char> >(s.get_loc()).widen('+'). To turn this into a space you could just use a std::locale with a std::ctype<char> facet installed responding with a space to the request to widen +.
That is, something like this:
struct my_ctype: std::ctype<char> {
char do_widen(char c) const {
return c == '+'? ' ': this->std::ctype<char>::do_widen(c);
}
};
int main() {
std::locale loc(std::locale(), new my_ctype);
std::cout.imbue(loc);
std::cout << std::showpos << 12.34 << '\n';
}
(the code isn't tested and probably riddled with errors).
How about
std::cout << (d >= 0 ? " ":"") << d << std::endl;
std::cout << " " << my_value;
If you need space only for positive:
if (my_value >=0 ) cout << " "; cout << my_value;
I want to control the precision for a double during a comparison, and then come back to default precision, with C++.
I intend to use setPrecision() to set precision. What is then syntax, if any, to set precision back to default?
I am doing something like this
std::setPrecision(math.log10(m_FTOL));
I do some stuff, and I would like to come back to default double comparison right afterwards.
I modified like this, and I still have some errors
std::streamsize prec = std::ios_base::precision();
std::setprecision(cmath::log10(m_FTOL));
with cmath false at compilation, and std::ios_base also false at compilation. Could you help?
You can get the precision before you change it, with std::ios_base::precision and then use that to change it back later.
You can see this in action with:
#include <ios>
#include <iostream>
#include <iomanip>
int main (void) {
double d = 3.141592653589;
std::streamsize ss = std::cout.precision();
std::cout << "Initial precision = " << ss << '\n';
std::cout << "Value = " << d << '\n';
std::cout.precision (10);
std::cout << "Longer value = " << d << '\n';
std::cout.precision (ss);
std::cout << "Original value = " << d << '\n';
std::cout << "Longer and original value = "
<< std::setprecision(10) << d << ' '
<< std::setprecision(ss) << d << '\n';
std::cout << "Original value = " << d << '\n';
return 0;
}
which outputs:
Initial precision = 6
Value = 3.14159
Longer value = 3.141592654
Original value = 3.14159
Longer and original value = 3.141592654 3.14159
Original value = 3.14159
The code above shows two ways of setting the precision, first by calling std::cout.precision (N) and second by using a stream manipulator std::setprecision(N).
But you need to keep in mind that the precision is for outputting values via streams, it does not directly affect comparisons of the values themselves with code like:
if (val1== val2) ...
In other words, even though the output may be 3.14159, the value itself is still the full 3.141592653590 (subject to normal floating point limitations, of course).
If you want to do that, you'll need to check if it's close enough rather than equal, with code such as:
if ((fabs (val1 - val2) < 0.0001) ...
Use C++20 std::format and {:.2} instead of std::setprecision
Finally, this will be the superior choice once you can use it:
#include <format>
#include <string>
int main() {
std::cout << std::format("{:.3} {:.4}\n", 3.1415, 3.1415);
}
Expected output:
3.14 3.145
This will therefore completely overcome the madness of modifying std::cout state.
The existing fmt library implements it for before it gets official support: https://github.com/fmtlib/fmt Install on Ubuntu 22.04:
sudo apt install libfmt-dev
Modify source to replace:
<format> with <fmt/core.h>
std::format to fmt::format
main.cpp
#include <iostream>
#include <fmt/core.h>
int main() {
std::cout << fmt::format("{:.3} {:.4}\n", 3.1415, 3.1415);
}
and compile and run with:
g++ -std=c++11 -o main.out main.cpp -lfmt
./main.out
Output:
3.14 3.142
See also:
How do I print a double value with full precision using cout?
std::string formatting like sprintf
Pre C++20/fmt::: Save the entire state with std::ios::copyfmt
You might also want to restore the entire previous state with std::ios::copyfmt in these situations, as explained at: Restore the state of std::cout after manipulating it
main.cpp
#include <iomanip>
#include <iostream>
int main() {
constexpr float pi = 3.14159265359;
constexpr float e = 2.71828182846;
// Sanity check default print.
std::cout << "default" << std::endl;
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout << std::endl;
// Change precision format to scientific,
// and restore default afterwards.
std::cout << "modified" << std::endl;
std::ios cout_state(nullptr);
cout_state.copyfmt(std::cout);
std::cout << std::setprecision(2);
std::cout << std::scientific;
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout.copyfmt(cout_state);
std::cout << std::endl;
// Check that cout state was restored.
std::cout << "restored" << std::endl;
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout << std::endl;
}
GitHub upstream.
Compile and run:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Output:
default
3.14159
2.71828
modified
3.14e+00
2.72e+00
restored
3.14159
2.71828
Tested on Ubuntu 19.04, GCC 8.3.0.
You need to keep track of your current precison and then reset back to the same once done with your operations with required modified precison. For this you can use std::ios_base::precision:
streamsize precision ( ) const;
streamsize precision ( streamsize prec );
The first syntax returns the value of the current floating-point precision field for the stream.
The second syntax also sets it to a new value.
setprecision() can be used only for output operations and cannot be used for comparisons
To compare floats say a and b , you have to do it explicitly like this:
if( abs(a-b) < 1e-6) {
}
else {
}
You can use cout << setprecision(-1)