double to std::string with dynamic precisicion (without trailing zeros) - c++

I want to convert a double value into a std::string. Currently I'm writing
return std::to_string(double_value);
But this only returns 7 digits because internally to_string() just uses std::vsnprintf with a %f format specifier (see also here).
I could now just call std::vsnprintf manually with %.15f as format specifier but this leads to trailing zeros.
My (in my eyes very obvious) goal now is to have an approach like this:
string o1 = to_string(3.14)
string o2 = to_string(3.1415926536)
assert(o1 == "3.14")
assert(o2 == "3.1415926536")
Here is a nice elaboration on trimming trailing zeros from the %.20 output but this answer is about 8 years old.
Maybe things have changed? Can I convert a double with double precision without trailing zeros in C++ today?
Solution:
Based on 2mans answer you can write a generic function like this:
template<typename T>
inline std::string tostr(T value) {
std::ostringstream s;
s.precision(std::numeric_limits<T>::digits10);
s << value;
return s.str();
}
which will behaves like desired for numeric types. Note that I took digits10 rather than max_digits10 to favor a nice decimal representation rather than more digits and trailing ..0000001
Also IMHO it's worth to add that [v][s][n]printf() together with the format string "%.15g" (rather than 'f') will also trim trailing zeros (won't work with more digits because they could not be represented with 64bit which would lead to things like a trailing '1', e.g. 3.12 -> "3.1200000000000001")
Still strange:
Maybe someone can tell me why std::to_string(double) which was introduced with C++-11 hard-codes to vsnprintf(..., "%f", ...) rather than so something like vsnprintf("%.15g") which would result in a more precise representation without affecting C code?

You can use string stream (sstring) with stream manipulators, see example below:
std::stringstream ss1;
std::stringstream ss2;
ss1.precision(15);
ss1 << 3.14;
std::cout << ss1.str()<<' '<<("3.14" == ss1.str())<<std::endl;
ss2.precision(15);
ss2 << 3.1415926536;
std::cout << ss2.str()<<' '<<("3.1415926536" == ss2.str())<<std::endl;
Or you can use boost format. Here's a link!
std::cout<<format("%.2f") % 3.14 <<std::endl;
std::cout<<format("%.10f") % 3.1415926536 <<std::endl;

Related

Converting integer to string in c++

This is the code I wrote to convert integer to string.
#include <iostream>
using namespace std;
int main()
{
string s;
int b=5;
s.push_back((char)b);
cout<<s<<endl;
}
I expected the output to be 5 but it is giving me blank space.
I know there is another way of doing it using stringstream but I want to know what is wrong in this method?
Character code for numbers are not equal to the integer the character represents in typical system.
It is granteed that character codes for decimal digits are consecutive (N3337 2.3 Character sets, Paragraph 3), so you can add '0' to convert one-digit number to character.
#include <iostream>
using namespace std;
int main()
{
string s;
int b=5;
s.push_back((char)(b + '0'));
cout<<s<<endl;
}
You are interpreting the integer 5 as a character. In ASCII encoding, 5 is the Enquiry control character as you lookup here.
The character 5 on the other hand is represented by the decimal number 53.
As others said, you can't convert an integer to a string the way you are doing it.
IMHO, the best way to do it is using the C++11 method std::to_string.
Your example would translate to:
using namespace std;
int main()
{
string s;
int b=5;
s = to_string(b);
cout<<s<<endl;
}
The problem in your code is that you are converting the integer 5 to ASCII (=> ENQ ASCII code, which is not "printable").
To convert it to ASCII properly, you have to add the ASCII code of '0' (48), so:
char ascii = b + '0';
However, to convert an integer to std::string use:
std::stringstream ss; //from <sstream>
ss << 5;
std::string s = ss.str ();
I always use this helper function in my projects:
template <typename T>
std::string toString (T arg)
{
std::stringstream ss;
ss << arg;
return ss.str ();
}
Also, you can use stringstream,
std::to_string doesn't work for me on GCC
If we were writing C++ from scratch in 2016, maybe we would make this work. However as it choose to be (mostly) backward compatible with a fairly low level language like C, 'char' is in fact just a number, that string/printing algorithms interpret as a character -but most of the language doesn't treat special. Including the cast. So by doing (char) you're only converting a 32 bit signed number (int) to a 8 bit signed number (char).
Then you interpret it as a character when you print it, since printing functions do treat it special. But the value it gets printed to is not '5'. The correspondence is conventional and completely arbitrary; the first numbers were reserved to special codes which are probably obsolete by now. As Hoffman pointed out, the bit value 5 is the code for Enquiry (whatever it means), while to print '5' the character has to contain the value 53. To print a proper space you'd need to enter 32. It has no meaning other than someone decided this was as good as anything, sometime decades ago, and the convention stuck.
If you need to know for other characters and values, what you need is an "ASCII table". Just google it, you'll find plenty.
You'll notice that numbers and letters of the same case are next to each other in the order you expect, so there is some logic to it at least. Beware, however, it's often not intuitive anyway: uppercase letters are before lowercase ones for instance, so 'A' < 'a'.
I guess you're starting to see why it's better to rely on dedicated system functions for strings!

C++ convert UTF8 string to hexadecimal and vice versa

It took time looking as utf8 convert string to hexadecimal string, and backwards
I found some examples and possible solutions, but all work well only without special characters.
I have a folowing :
string in="áéíóúñü"
The result shoud be:
"c3a1c3a9c3adc3b3c3bac3b1c3bc"
I try following post, and others:
C++ convert string to hexadecimal and vice versa
How to convert a string in hexadecimal string?
http://www.cplusplus.com/forum/beginner/161703/
I will try to explain better, but I can not speak English properly. Sorry.
I have to send some data using socket. For that I have to convert names to hexadecimal using UTF-8, but in some cases have specials characters for example á, é, í...
When converting normal letters get a string length of 2 per letter.
a-> "61"
e-> "65"
But special characters are encoded (on UTF-8) with length 4
á-> "c3a1" this is the correct conversion
é-> "c3a9" this is the correct conversion
I have attempted the conversion of all the ways I've found, including that suggested me down. But every time you convert a special character gives me an answer of 2 digits, that is not correct.
á-> "e1" this isnt correct
é-> "e9" this isnt correct
Loop over each "character" in the std::string object, output it's two-digit hexadecimal equivalent as an int.
For looping, I recommend you look into range-based for loops.
To set the number of digits to print, read about setting stream precision.
To print a number as hexadecimal, read about the base I/O manipulators.
To convert to an int read about static_cast.
Oh, and I recommend using an unsigned char for the single "characters".
Simple solution based on the above:
std::string stoh(std::string const& in)
{
std::ostringstream os;
for(unsigned char const& c : in)
{
os << std::hex << std::setprecision(2) << std::setw(2)
<< std::setfill('0') << static_cast<int>(c);
}
return os.str();
}

ostringstream to print float numbers in fixed notation avoiding scentific notation

I'm using the following code to print float number (value is of type float):
std::ostringstream ss;
ss << std::fixed << std::setprecision(9) << value;
which works fine most the cases. However, when value is very small I'm getting things like:
2.98e-07
while I'd would expect the following (fixed notation with 9 decimal numbers):
0.0000000289
Thus, what is the way of using std::ostringstream to achive this, please?
At the end, the problem was not in the C++ program that generates the float number (that as some users have report, it is ok) but in the program that I use to beautify the output of the C++ program. Thus this question is solved (although a new one about the beautifier opens).

A story of stringstream, hexadecimal and characters

I have a string containing hexadecimal values (two characters representing a byte). I would like to use std::stringstream to make the conversion as painless as possible, so I came up with the following code:
std::string a_hex_number = "e3";
{
unsigned char x;
std::stringstream ss;
ss << std::hex << a_hex_number;
ss >> x;
std::cout << x << std::endl;
}
To my biggest surprise this prints out "e" ... Of course I don't give up so easily, and I modify the code to be:
{
unsigned short y;
std::stringstream ss;
ss << std::hex << a_hex_number;
ss >> y;
std::cout << y << std::endl;
}
This, as expected, prints out 227 ...
I looked at http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ and http://www.cplusplus.com/reference/ios/hex/ but I just could not find a reference which tells me more about why this behaviour comes ...(yes, I feel that it is right because when extracting a character it should take one character, but I am a little bit confused that std:hex is ignored for characters). Is there a mention about this situation somewhere?
(http://ideone.com/YHt7Fz)
Edit I am specifically interested if this behaviour is mentioned in any of the STL standards.
If I understand correctly, you're trying to convert a string in
hex to an unsigned char. So for starters, since this is
"input", you should be using std::istringstream:
std::istringstream ss( a_hex_number );
ss >> std::hex >> variable;
Beyond that, you want the input to parse the string as an
integral value. Streams do not consider character types as
numeric values; they read a single character into them (after
skipping leading white space). To get a numeric value, you
should input to an int, and then convert that to unsigned
char. Characters don't have a base, so std::hex is
irrelevant for them. (The same thing holds for strings, for
example, and even for floating point.)
With regards to the page you site: the page doesn't mention
inputting into a character type (strangely enough, because it
does talk about all other types, including some very special
cases). The documentation for the std::hex manipulator is
also weak: in the running text, it only says that "extracted
values are also expected to be in hexadecimal base", which isn't
really correct; in the table, however, it clearly talks about
"integral values". In the standard, this is documented in
§27.7.2.2.3. (The >> operators for character types are not
member functions, but free functions, so are defined in
a different section.) What we are missing, however, is a good
document which synthesizes these sort of things: whether the
>> operator is a member or a free function doesn't really
affect the user much; you want to see all of the >> available,
with their semantics, in one place.
Let's put it simple: variable type is 'stronger' than 'hex'. That's why 'hex' is ignored for 'char' variable.
Longer story:
'Hex' modifies internal state of stringstream object telling it how to treat subsequent operations on integers. However, this does not apply to chars.
When you print out a character (i.e. unsigned char), it's printed as a character, not as a number.

Which is efficient, itoa or sprintf?

I am in the processes of building my first C++ application and choosing an efficient C++ libraries to rely on at this stage, is one of the design consideration I am looking at.
Consequently I want to convert an integer type to string and deciding on whether to use;
sprintf(string, "%d", x);
Or
Integer to ASCI
itoa(x, string);
Can anyone suggest which one of these route is efficient and possibly why?
Thanks.
They're both efficient. It's probably much more relevant to note that itoa() is not part of the C++ standard, and as such is not available in many common runtimes. (In particular, it's not part of libstdc++, so it's not available on Mac OS X or Linux.)
Don't use either of these. Use std::stringstream and so on.
std::stringstream ss;
ss << x;
ss.str(); // Access the std::string
Either way, it's quite unlikely that converting to string will be a significant part of your application's execution time.
From a pure algorithm viewpoint one can argue that itoa would be faster since sprintf has the additional cost of parsing the format descriptor string. However without benchmarking the cost of the two functions in an implementation, with a non-trivial work load, one cannot be sure.
Also this isn't apples to apples comparison since both functions aren't equivalent. sprintf can do much more formatting than itoa does, apart from the fact that the former is a standard function while the latter isn't.
Aside: If you can use C++11 you can use to_string which returns you an std::string. If you want representations other than decimal you may do this:
int i = 1234;
std::stringstream ss;
ss << std::hex << i; // hexadecimal
ss << std::oct << i; // octal
ss << std::dec << i; // decimal
std::bitset<sizeof(int) * std::numeric_limits<unsigned char>::digits> b(i);
ss << b; // binary
std::string str = ss.str();