std::stringstream to return char * - c++

This is my code:
#include <iostream>
#include <sstream>
void serialize(std::ostream& os)
{
int r1 = 10;
int r2 = 12;
os.write(reinterpret_cast<char const*>(&r1), sizeof(r1));
os.write(reinterpret_cast<char const*>(&r2), sizeof(r2));
}
int main()
{
std::stringstream ss;
serialize(ss);
std::cout<<" Buffer length : " << ss.str().length() <<'\n'; //This print correct length
const char *ptrToBuff = ss.str().c_str();// HERE is the problem. char * does not contain anything.
std::cout <<ptrToBuff; // NOTHING is printed
}
How to get a char pointer to the stream buffer?
The problem is std::cout << ptrToBuff; does not print anything

A pointer to the stream will leave a dangling pointer, you can copy the string though:
const std::string s = ss.str();
And then point your const char* to it:
const char *ptrToBuff = s.c_str();
In your serialize function you should use << operator to write to ostream:
os << r1 << " " << sizeof(r1) << std::endl;
os << r2 << " " << sizeof(r2) << std::endl;
So the whole code will be: (see here)
void serialize(std::ostream& os)
{
int r1 = 10;
int r2 = 12;
os << r1 << " " << sizeof(r1) << std::endl;
os << r2 << " " << sizeof(r2) << std::endl;
}
int main()
{
std::stringstream ss;
serialize(ss);
std::cout<<"Buffer length : " << ss.str().length() <<'\n';
const std::string s = ss.str();
const char *ptrToBuff = s.c_str();
std::cout << ptrToBuff;
}

Related

Format a decimal to string, whilst removing any trailing zeros and avoiding scientific notation [duplicate]

What is the most elegant way to output a floating point number in C++ with no scientific notation or trailing zeros?
float a = 0.000001f;
float b = 0.1f;
cout << "a: " << a << endl; // 1e-006 terrible, don't want sci notation.
cout << "b: " << b << endl; // 0.1 ok.
cout << fixed << setprecision(6);
cout << "a: " << a << endl; // 0.000001 ok.
cout << "b: " << b << endl; // 0.100000 terrible, don't want trailing zeros.
I am not sure about the "most elegant way" but here's one way.
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std ;
string fix( float x, int p )
{
ostringstream strout ;
strout << fixed << setprecision(p) << x ;
string str = strout.str() ;
size_t end = str.find_last_not_of( '0' ) + 1 ;
return str.erase( end ) ;
}
int main()
{
float a = 0.000001f ;
float b = 0.1f ;
cout << "a: " << fix( a, 6 ) << endl; // 0.000001 ok.
cout << "b: " << fix( b, 6 ) << endl; // 0.1 ok.
return 0;
}
You could perhaps create your own I/O manipulator if you need to to a lot of this kind of output. That is arguably more elegant, but the implementation could be similar.
If string manipulating doesn't hurt your eyes:
std::string fixedfloat(float x)
{
std::ostringstream ss;
ss << std::fixed << std::setprecision(std::cout.precision()) << x;
std::string str = ss.str();
return str.substr(0, str.find_last_not_of('0') + 1);
}
int main()
{
float b = 0.1f;
std::cout << std::setprecision(6) << fixedfloat(b);
}
or
class fixedfloat
{
public:
fixedfloat(float x) : x(x) {}
float value() const { return x; }
private:
float x;
};
ostream &operator<<(ostream &out, const fixedfloat &f)
{
ostringstream ss;
ss << fixed << setprecision(out.precision()) << f.value();
string str = ss.str();
out << str.substr(0, str.find_last_not_of('0') + 1);
return out;
}
int main()
{
float b = 0.1f;
cout << setprecision(6) << fixedfloat(b);
}
the other example like mine actually output "200." or did "200" >> "2".
this should work for everything (as I took it from a string to val function I use).
string fix(float in) {
string s = to_string(in);
size_t dot = s.find_first_of('.'), last = s.find_last_not_of(".0");
if (dot!=string::npos) return s.substr(0, max(dot,last+1));
else return s;
}

How to parse a const char* from a double / long without the std::string library?

How can I parse a const char* from a double or long?
Mainly because my code is a lot faster when I use a const char*, so i decided to create a small base string class. But my code to parse a double has some bugs.
My code only works partially. Some help would be very appreciated.
I am using macos, g++ & c++17.
Code:
#include <iostream>
class bstring {
public:
const char* characters;
bstring(const char* c = "") { characters = c; }
static bstring parse(const double number, int precision = 100) {
// Convert.
int decimal, sign;
char *buffer;
buffer = ecvt(number, precision, &decimal, &sign);
int n = strlen(buffer);
// Add decimal.
char before[decimal];
strncpy(before, 0 + buffer, decimal);
char after[n - decimal - 1];
strncpy(after, decimal + buffer, n - decimal - 1);
// Remove zero padding.
int removed = 0;
while (true) {
size_t n = sizeof(after) - removed;
size_t index_to_remove = n - 1;
if (after[index_to_remove] == '0') {
for (size_t i = index_to_remove; i < n - 1; ++i) {
after[i] = after[i + 1];
}
removed += 1;
} else { break; }
}
bool is_zero = removed == sizeof(after);
int after_size = sizeof(after)-removed;
char* nafter = (char*)malloc(sizeof(char) * after_size);
// Concat.
char* new__{ new char[strlen(before) + 1 + after_size] };
new__ = strcpy(new__, before);
new__ = strcat(new__, ".");
if (is_zero) {
char a[] = "0";
new__ = strcat(new__, a);
} else {
new__ = strcat(new__, after);
}
// Assign.
bstring s = new__;
delete[] new__; new__ = NULL;
return s;
//
}
};
std::ostream& operator <<(std::ostream &s, bstring x) { return s << x.characters; }
int main() {
std::cout << "Should be " << "-1234.39950" << ": " << bstring::parse(-1234.39950) << std::endl;
std::cout << "Should be " << "-1.0" << ": " << bstring::parse(-1.0) << std::endl;
std::cout << "Should be " <<"0.0" << ": " << bstring::parse(0.0) << std::endl;
std::cout << "Should be " <<"0.3897495" << ": " << bstring::parse(0.3897495) << std::endl;
std::cout << "Should be " <<"1.0" << ": " << bstring::parse(1.0) << std::endl;
std::cout << "Should be " <<"100.00" << ": " << bstring::parse(1000.0) << std::endl;
std::cout << "Should be " <<"10000.000" << ": " << bstring::parse(1000000.0) << std::endl;
std::cout << "Should be " <<"1000000.0000" << ": " << bstring::parse(1000000000.0) << std::endl;
std::cout << "Should be " <<"1000000000.0000" << ": " << bstring::parse(1000000000000.0) << std::endl;
std::cout << "Should be " <<"1000000000000.0000" << ": " << bstring::parse(1000000000000000.0) << std::endl;
}
Edit:
Is this piece of code okay? Or am I doing something wrong by not deleting it / By where I assign the new__ to.
// Concat.
bstring concat(const char* c) {
int n = ::strlen(characters) + ::strlen(c);
if (n == 0) { return bstring(); }
if (::strlen(c) == 0) { return bstring(characters); }
char* new__{ new char[n + 1] };
new__ = strcpy(new__, characters);
new__ = strcat(new__, c);
// const char* n = new__;
// delete[] new__; new__ = NULL;
bstring s = new__;
return s;
}

Binary char array into stringstream and pop from the buffer

I have 20byte binary char array. I want to divide into 3 parts: 4byte, 8byte, 8byte. I implemented it like the following. It works but seems I might be able to use buffer stream. I want to know how to use it.
Now
void main()
{
// _data is 20byte binary char array. 0000000000000000000000000000000000000000000001111001110001111111001110000010110000001011101101000000000000000000000000000000000000000000000000000000000000000001
// strA (4 byte)
string strA;
for (std::size_t i = 0; i < 4; ++i) {
strA += bitset<8>(_data.c_str()[i]).to_string();
}
cout << strA << endl; // 00000000000000000000000000000000
// strB (8 byte)
string strB;
for (std::size_t i = 4; i < 12; ++i) {
strB += bitset<8>(_data.c_str()[i]).to_string();
}
cout << strB << endl; // 0000000000000111100111000111111100111000001011000000101110110100
// strC (8 byte)
string strC;
for (std::size_t i = 12; i < 20; ++i) {
strC += bitset<8>(_data.c_str()[i]).to_string();
}
cout << strC << endl; // 0000000000000000000000000000000000000000000000000000000000000001
}
Expectation
I want to implement like this.
void main()
{
stringstream ss = _data;
strA = ss.pop(4);
strB = ss.pop(8);
strC = ss.pop(8);
}
Update 1
Thank you guys. I'm trying all of answers you gave me one by one. I'm newbie in c++ so it takes time to understand it. The following is Anders K's one.
struct S { char four[4]; char eight1[8]; char eight2[8]; };
struct S *p = reinterpret_cast<S*>(&_data);
cout << p->four << endl; // => Output "(" I think I can find way to output
Update 2
It works using string::substr. Thanks Zakir.
int main()
{
// I don't know how to change to string value in smart way..
string str;
for (std::size_t i = 0; i < _data.size(); ++i) {
str += bitset<8>(_data.c_str()[i]).to_string();
}
cout << str << endl; // 0000000000000000000000000000000000000000000001111001110001111111001110000010110000001011101101000000000000000000000000000000000000000000000000000000000000000001
std::string d = str; // Your binary stream goes here
int lenA = (4*8); // First 4 Bytes
int lenB = (8*8); // Second 8 Bytes
int lenC = (8*8); // Last 8 Bytes
std::string strA = d.substr(0, lenA);
std::string strB = d.substr(lenA + 1, lenB - 1);
std::string strC = d.substr(lenA + lenB + 1, lenC - 1);
cout << strA << endl; // 00000000000000000000000000000000
cout << strB << endl; // 000000000000111100111000111111100111000001011000000101110110100
cout << strC << endl; // 000000000000000000000000000000000000000000000000000000000000001
}
Update 3
I got an error when I try Scheff's way. This is my fault and I think I can solve it. And I think I should reconsider about _data's type.
int main
{
const char data = _data;
const char *iter = data;
string strA = pop(iter, 4);
string strB = pop(iter, 8);
string strC = pop(iter, 8);
cout << "strA: '" << strA << "'" << endl;
cout << "strB: '" << strB << "'" << endl;
cout << "strC: '" << strC << "'" << endl;
}
Make Error Message
error: no viable conversion from 'string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to
'const char'
const char data = _data;
It is not possible to make a new method for std::stringstream. (At least, I would not recommend this.)
Instead, I would suggest to make it a function. The usage would be similar.
#include <bitset>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
string pop(istream &in, size_t n)
{
string ret;
while (n--) {
unsigned char byte = (unsigned char)in.get();
ret += bitset<8>(byte).to_string();
}
return ret;
}
int main()
{
string data(
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa"
"\xbb\xcc\xdd\xee\xff\xde\xad\xbe\xef\x00", 20);
istringstream in; in.str(data);
string strA = pop(in, 4);
string strB = pop(in, 8);
string strC = pop(in, 8);
cout << "strA: '" << strA << "'" << endl;
cout << "strB: '" << strB << "'" << endl;
cout << "strC: '" << strC << "'" << endl;
return 0;
}
Output:
strA: '00010001001000100011001101000100'
strB: '0101010101100110011101111000100010011001101010101011101111001100'
strC: '1101110111101110111111111101111010101101101111101110111100000000'
Note:
Using a std::istream makes it applicable to any stream derived from std::istream.
There is no error handling in pop(). Thus, the returned result of pop() might be wrong if the passed stream isn't good() afterwards.
Btw. I agree with the comments that a std::stream might be "over-engineered". Thus, here the "light-weight" version:
#include <bitset>
#include <iostream>
#include <string>
using namespace std;
string pop(const char *&iter, size_t n)
{
string ret;
while (n--) {
ret += bitset<8>((unsigned char)*iter++).to_string();
}
return ret;
}
int main()
{
const char data[] =
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa"
"\xbb\xcc\xdd\xee\xff\xde\xad\xbe\xef\x00";
const char *iter = data;
string strA = pop(iter, 4);
string strB = pop(iter, 8);
string strC = pop(iter, 8);
cout << "strA: '" << strA << "'" << endl;
cout << "strB: '" << strB << "'" << endl;
cout << "strC: '" << strC << "'" << endl;
return 0;
}
The output is identical like above.
Note:
The usage of char[] and char* is much more sensitive for out-of-bound access. Thus, it has to be used carefully.
I'm not quite sure whether the (unsigned char) cast is necessary. As I have often seen "funny" effects concerning char, int and sign extension, I guess it cannot hurt. (I feel better with it.)
I can propose you a very simple alternative using string::substr
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string _data="00010001001000100011001101000100\
0101010101100110011101111000100010011001101010101011101111001100\
1101110111101110111111111101111010101101101111101110111100000000";
int lenA = (4*8); //First 4 Bytes
int lenB = (8*8); //Second 8 Bytes
int lenC = (16*8); //Last 16 Bytes
string strA = _data.substr(0, lenA - 1);
string strB = _data.substr(lenA, lenB - 1);
string strC = _data.substr(lenB, lenC - 1);
std::cout << "strA: " << strA << endl;
std::cout << "strB: " << strB << endl;
std::cout << "strC: " << strC << endl;
return 0;
}
This is neat and simple but gets your job done!
Demo here
Output:-
strA: 0001000100100010001100110100010
strB: 010101010110011001110111100010001001100110101010101110111100110
strC: 100110011010101010111011110011001101110111101110111111111101111010101101101111101110111100000000

How to output float to cout without scientific notation or trailing zeros?

What is the most elegant way to output a floating point number in C++ with no scientific notation or trailing zeros?
float a = 0.000001f;
float b = 0.1f;
cout << "a: " << a << endl; // 1e-006 terrible, don't want sci notation.
cout << "b: " << b << endl; // 0.1 ok.
cout << fixed << setprecision(6);
cout << "a: " << a << endl; // 0.000001 ok.
cout << "b: " << b << endl; // 0.100000 terrible, don't want trailing zeros.
I am not sure about the "most elegant way" but here's one way.
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std ;
string fix( float x, int p )
{
ostringstream strout ;
strout << fixed << setprecision(p) << x ;
string str = strout.str() ;
size_t end = str.find_last_not_of( '0' ) + 1 ;
return str.erase( end ) ;
}
int main()
{
float a = 0.000001f ;
float b = 0.1f ;
cout << "a: " << fix( a, 6 ) << endl; // 0.000001 ok.
cout << "b: " << fix( b, 6 ) << endl; // 0.1 ok.
return 0;
}
You could perhaps create your own I/O manipulator if you need to to a lot of this kind of output. That is arguably more elegant, but the implementation could be similar.
If string manipulating doesn't hurt your eyes:
std::string fixedfloat(float x)
{
std::ostringstream ss;
ss << std::fixed << std::setprecision(std::cout.precision()) << x;
std::string str = ss.str();
return str.substr(0, str.find_last_not_of('0') + 1);
}
int main()
{
float b = 0.1f;
std::cout << std::setprecision(6) << fixedfloat(b);
}
or
class fixedfloat
{
public:
fixedfloat(float x) : x(x) {}
float value() const { return x; }
private:
float x;
};
ostream &operator<<(ostream &out, const fixedfloat &f)
{
ostringstream ss;
ss << fixed << setprecision(out.precision()) << f.value();
string str = ss.str();
out << str.substr(0, str.find_last_not_of('0') + 1);
return out;
}
int main()
{
float b = 0.1f;
cout << setprecision(6) << fixedfloat(b);
}
the other example like mine actually output "200." or did "200" >> "2".
this should work for everything (as I took it from a string to val function I use).
string fix(float in) {
string s = to_string(in);
size_t dot = s.find_first_of('.'), last = s.find_last_not_of(".0");
if (dot!=string::npos) return s.substr(0, max(dot,last+1));
else return s;
}

std::ostream tellp() giving wrong output in VS2010

Below is the code i am running and corresponding output.
#include<iostream>
#include <sstream>
#include <strstream>
#include <streambuf>
template <typename char_type>
struct ostreambuf : public std::basic_streambuf<char_type,std::char_traits<char_type> >
{
ostreambuf(char_type* buffer, std::streamsize bufferLength)
{
// set the "put" pointer the start of the buffer and record it's length.
setp(buffer, buffer + bufferLength);
}
};
int main()
{
char strArr[] = "Before-1";
char stringArr[] = "Before-2";
std::strstream strStream(strArr,sizeof(strArr));
ostreambuf<char> ostreamBuffer(stringArr, sizeof(stringArr));
std::ostream stringStream(&ostreamBuffer);
const std::streampos posStringBefore = stringStream.tellp();
std::cout << "Before: "
<< "strArr = "
<< strArr
<< " & "
<< "stringArr = "
<< stringArr
<< std::endl;
std::cout << "Before: " << "posStringBefore = "
<< posStringBefore
<< std::endl;
// -------------------------
strStream << "After-1";
stringStream << "After-2";
const std::streampos posStringAfter = stringStream.tellp();
std::cout << "After : "
<< "strArr = "
<< strArr
<< " & "
<< "stringArr = "
<< stringArr
<< std::endl;
std::cout << "After : " << "posStringAfter = "
<< posStringAfter
<< std::endl;
return 0;
}
This is the o/p on VS2010 :
Before: strArr = Before-1 & stringArr = Before-2
Before: posStringBefore = -1
After : strArr = After-11 & stringArr = After-22
After : posStringAfter = -1
In reference to link
Setting the internal buffer used by a standard stream (pubsetbuf)
How to get the size of std::ostream object created?
It doesn't give you a "wrong" output/value. tellp uses rdbuf()->pubseekoff which relays the call to virtual seekoff. The basic_streambuf implementation simply returns -1 as defined in the C++ standard. You need to provide an own implementation for this method in your ostreambuf class.
See cppreference: basic_streambuf::pubseekof