In c++ we have std::to_string which converts int/float/double to strings. So just to test my understanding of templates I tried the code below:
#include "iostream"
#include "sstream"
#include "string"
using std::cout;
template <typename T>
std::string getString(const T& data){
std::stringstream ss;
cout << '\n' << data << '\n';
ss << data;
std::string s;
ss >> s;
return s;
}
int main(int argc , char** argv){
cout << getString(1.0000011);
cout <<' '<<std::to_string(1.0000011);
return 0;
}
However, the output doesn't make sense, to_string gives me 1.0000011, whereas getString gets 1 and gives me 1. As I am using templates shouldn't getString get 1.0000011 as well and give me 1.0000011 too?
You can use std::setprecision in the <iomanip> header to set the precision that std::stringstream will use when formatting numeric data.
For example:
std::stringstream ss;
ss << std::setprecision(9) << data;
cout << ss.str();
Will print:
1.0000011
Here's a quick demo online: cpp.sh/9v7xf
As a side note, you don't have to create a string and output from the stringstream - you can replace the last 3 lines in getString() with:
return ss.str();
Numeric values are often truncated for appearance. You can supply the std::fixed manipulator from the iomanip standard header to avoid this issue.
#include "iomanip" // <- Add this header
#include "iostream"
#include "sstream"
#include "string"
using std::cout;
template <typename T>
std::string getString(const T& data)
{
std::stringstream ss;
cout << '\n' << data << '\n';
ss << std::fixed << data;
// ^^^^^^^^^^^^^ Add this
std::string s;
ss >> s;
return s;
}
int main(int argc, char** argv)
{
cout << getString(1.0000011);
cout << ' ' << std::to_string(1.0000011);
return 0;
}
<iomanip> needs included, and std::setprecision must be used when outputting float values to streams. Using your example, this looks like:
#include <iostream>
#include <iomanip> //include this.
#include <sstream>
#include <string>
template <typename T>
std::string getString(const T& data){
std::ostringstream ss;
ss << std::setprecision(8);
std::cout << std::setprecision(8);
std::cout << data << '\n';
ss << data;
return ss.str();
}
int main(int argc , char** argv){
std::cout << getString(1.0000011) << "\n";
std::cout << std::to_string(1.0000011) << std::endl;
return 0;
}
Which prints:
1.0000011
1.0000011
1.000001
Program ended with exit code: 0
Note how to_string alone truncates the floating point number!!! I suspect this is undesired behavior, but to_string cannot be manipulated directly, so...
If desired, you can fix this with the solution found here.
Otherwise, just use std:set_precision() when inserting into streams for precisely converted strings.
Related
The next code returns an empty string in ss:
#include <string>
#include <iostream>
#include <sstream>
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
ss.basic_ios<char>::rdbuf(oss.rdbuf());
std::cout << ss.str() << "\n";
return 0;
}
How can I return from ss the text introduced in oss? I'm mainly interested in converting std::ostringstream into std::stringstream.
You could make use of the protected std::streambuf::swap member function that exchanges the contents of the stream buffer with those of another
To get access to it, you'll need a derived class:
#include <iostream>
#include <sstream>
struct swapper : std::streambuf {
using std::streambuf::streambuf;
void swap(std::streambuf& rhs) { // public proxy for protected swap
std::streambuf::swap(rhs);
}
};
// casting
void swapbuf(std::ostream& a, std::ostream& b) {
static_cast<swapper*>(a.rdbuf())->swap(*b.rdbuf());
}
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
swapbuf(oss, ss);
std::cout << "ss: " << ss.str() << "\n"; // prints Text
}
Following comments from #NathanOliver, I decided to convert std::ostringstream into std::stringstream by using str():
#include <string>
#include <iostream>
#include <sstream>
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
ss << oss.str();
std::cout << ss.str() << "\n";
return 0;
}
I have a string and I want to print hex value of each parts ascii code.
for example if the string is "0200" the output will be 30323030 .
and here's my code:
string bit_pattern;
bit_pattern = "5678008180000000";
cout << hex << bit_pattern;
but it prints 5678008180000000 instead of 35363738303038313830303030303030
how do i fix it???
You can use the following
for (int i=0; i<bit_pattern.length(); i++)
cout << hex << (int)bit_pattern[i];
to print the ascii value (in hex format) char by char.
You're just sending the same std::string right to std::cout. Just sending the hex manipulator isn't going to magically convert all those chars.
I admit this is complete overkill, but I was bored:
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
class ascicodes
{
std::ostringstream ss;
public:
friend std::ostream& operator <<(std::ostream& os, const ascicodes& obj)
{
os << obj.ss.str();
return os;
}
ascicodes(const std::string& s)
{
ss << std::hex << std::setfill('0');
std::for_each(s.begin(), s.end(),
[this](char ch)
{
ss << std::setw(2) << static_cast<unsigned int>(ch);
});
}
};
int main()
{
std::string bit_pattern = "5678008180000000";
std::cout << ascicodes(bit_pattern) << std::endl;
std::cout << ascicodes("A completely different string") << std::endl;
return 0;
}
Output
35363738303038313830303030303030
4120636f6d706c6574656c7920646966666572656e7420737472696e67
The following code converts an std::string to int and the problem lies with the fact that it cannot discern from a true integer or just a random string. Is there a systematic method for dealing with such a problem?
#include <cstring>
#include <iostream>
#include <sstream>
int main()
{
std::string str = "H";
int int_value;
std::istringstream ss(str);
ss >> int_value;
std::cout<<int_value<<std::endl;
return 0;
}
EDIT: This is the solution that I liked because it is very minimal and elegant! It doesn't work for negative numbers but I only needed positive ones anyways.
#include <cstring>
#include <iostream>
#include <sstream>
int main()
{
std::string str = "2147483647";
int int_value;
std::istringstream ss(str);
if (ss >> int_value)
std::cout << "Hooray!" << std::endl;
std::cout<<int_value<<std::endl;
str = "-2147483648";
std::istringstream negative_ss(str);
if (ss >> int_value)
std::cout << "Hooray!" << std::endl;
std::cout<<int_value<<std::endl;
return 0;
}
You may try to use Boost lexical_cast, it will throw an exception if the cast failed.
int number;
try
{
number = boost::lexical_cast<int>(str);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << str << "isn't an integer number" << std::endl;
}
EDIT
Accorinding to #chris, You may also try to use std::stoi since C++11. It will throw std::invalid_argument exception if no conversion could be performed. You may find more information here: std::stoi
WhozCraig's approach is much nicer and I wanted to expand on it using the approach that the C++ FAQ uses which is as follows:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline int convertToInt(std::string const& s,
bool failIfLeftoverChars = true)
{
std::istringstream i(s);
int x;
char c;
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
throw BadConversion("convertToInt(\"" + s + "\")");
return x;
}
int main()
{
std::cout << convertToInt( "100" ) << std::endl ;
std::cout << convertToInt( "-100" ) << std::endl ;
std::cout << convertToInt( " -100" ) << std::endl ;
std::cout << convertToInt( " -100 ", false ) << std::endl ;
// The next two will fail
std::cout << convertToInt( " -100 ", true ) << std::endl ;
std::cout << convertToInt( "H" ) << std::endl ;
}
This is robust and will know if the conversion fails, you also can optionally choose to fail on left over characters.
/* isdigit example */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main ()
{
char str[]="1776ad";
int year;
if (isdigit(str[0]))
{
year = atoi (str);
printf ("The year that followed %d was %d.\n",year,year+1);
}
return 0;
}
I'd like to convert a vector<char> to a std::string and do a conversion one the way.
I'm almost there, but the result of the code below is a vector<string>, while I'd like to have one string (a concatenation of all the string parts in the vector).
See my code example for details.
string ConvertHexToAscii(const char input)
{
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
return oss.str();
}
vector<char> readBuffer; // this is my input
readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);
vector<string> resultVec;
std::transform(readBuffer.begin(), readBuffer.end()
, back_inserter(resultVec)
, ConvertHexToAscii);
// resultVec[0] = "1C";
// resultVec[1] = "09";
The result I need is a string containing "1C09". How to achieve that with std::transform?
You were almost there; this works:
std::stringstream sstr;
std::transform(
input.begin(), input.end(),
std::ostream_iterator<std::string>(sstr, ""),
ConvertHexToAscii);
But unfortunately this instantiates quite a lot of string streams, which is inefficient. Ideally, the ConvertHexToAscii (misnamed, by the way! C++ doesn’t know about encodings) function would directly use the underlying stream.
#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <numeric>
std::string ConvertHexToAscii(std::string acc, char input)
{
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
return acc + oss.str();
}
int main() {
std::vector<char> readBuffer; // this is my input
readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);
std::cout << std::accumulate(readBuffer.begin(), readBuffer.end()
, std::string(), ConvertHexToAscii) << std::endl;
return 0;
}
create your own back_insert_iterator (look at the code in your stl lib, it's fairly simple) for string types of which operator = is defined as
template< class string_type, class value_type >
class back_insert_iterator
{
public:
back_insert_iterator< _string_type >& operator = ( const value_type& val )
{
container->append( val )
return *this;
}
};
You can do this with a function output iterator:
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <boost/function_output_iterator.hpp>
std::string ConvertHexToAscii(const char input)
{
std::ostringstream oss;
oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(input);
return oss.str();
}
int main() {
std::vector<char> readBuffer; // this is my input
readBuffer.push_back(0x1c);
readBuffer.push_back(0x09);
std::string temp;
std::transform(readBuffer.begin(), readBuffer.end()
, boost::make_function_output_iterator([&temp](const std::string& r) {temp.append(r);})
, ConvertHexToAscii);
std::cout << temp << std::endl;
}
I used a lambda to call the append() function on the result string, but if you don't have that available it's fairly easy to use boost::bind or just write an old fashioned functor to do that for you.
With boost::bind the function output iterator gets created as:
boost::make_function_output_iterator(boost::bind(static_cast<std::string& (std::string::*)(const std::string&)>(&std::string::append), &temp, _1))
instead. It's slightly clunky because you need to pick the right overload for std::string::append.
Whereas perreal's idea of using an accumulation isn't that bad, it may be more performant to operate on the stream directly instead of creating so many temporary strings (though move semantics may help with that):
std::ostringstream os;
std::string temp = std::accumulate(
readBuffer.begin(), readBuffer.end(), std::ref(os),
[](std::ostream &os, const char input)
-> std::reference_wrapper<std::ostream> {
return os << std::hex << std::setw(2)
<< std::setfill('0')
<< static_cast<int>(input);
}).str();
EDIT: But Ok, that's maybe a bit oversophistication here, a simple foreach would have done, too (even if not as semantically clean as an accumulation):
std::ostringstream os;
std::for_each(readBuffer.begin(), readBuffer.end(),
[&os](const char input) mutable {
os << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<int>(input);
});
std::string temp = os.str();
But anything might be better than creating a whole bunch of temporary strings.
I should know this already but... printf is to sprintf as cout is to ____? Please give an example.
It sounds like you are looking for std::ostringstream.
Of course C++ streams don't use format-specifiers like C's printf()-type functions; they use manipulators.
Example, as requested:
#include <sstream>
#include <iomanip>
#include <cassert>
std::string stringify(double x, size_t precision)
{
std::ostringstream o;
o << std::fixed << std::setprecision(precision) << x;
return o.str();
}
int main()
{
assert(stringify(42.0, 6) == "42.000000");
return 0;
}
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
ostringstream s;
s.precision(3);
s << "pi = " << fixed << 3.141592;
cout << s.str() << endl;
return 0;
}
Output:
pi = 3.142
Here's an example:
#include <sstream>
int main()
{
std::stringstream sout;
sout << "Hello " << 10 << "\n";
const std::string s = sout.str();
std::cout << s;
return 0;
}
If you want to clear the stream for reuse, you can do
sout.str(std::string());
Also look at the Boost Format library.
std::ostringstream
You can use this to create something like the Boost lexical cast:
#include <sstream>
#include <string>
template <typename T>
std::string ToString( const T & t ) {
std::ostringstream os;
os << t;
return os.str();
}
In use:
string is = ToString( 42 ); // is contains "42"
string fs = ToString( 1.23 ) ; // fs contains something approximating "1.23"
You have a little misunderstanding for the concept of cout. cout is a stream and the operator << is defined for any stream. So, you just need another stream that writes to string in order to output your data. You can use a standard stream like std::ostringstream or define your own one.
So your analogy is not very precise, since cout is not a function like printf and sprintf