Getting a buffer into a stringstream in hex representation: - c++

If I had a buffer like:
uint8_t buffer[32];
and it was filled up completely with values, how could I get it into a stringstream, in hexadecimal representation, with 0-padding on small values?
I tried:
std::stringstream ss;
for (int i = 0; i < 32; ++i)
{
ss << std::hex << buffer[i];
}
but when I take the string out of the stringstream, I have an issue: bytes with values < 16 only take one character to represent, and I'd like them to be 0 padded.
For example if bytes 1 and 2 in the array were {32} {4} my stringstream would have:
204 instead of 2004
Can I apply formatting to the stringstream to add the 0-padding somehow? I know I can do this with sprintf, but the streams already being used for a lot of information and it would be a great help to achieve this somehow.

#include <sstream>
#include <iomanip>
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (int i = 0; i < 32; ++i)
{
ss << std::setw(2) << static_cast<unsigned>(buffer[i]);
}

Look at the stream modifiers: std::setw and std::setfill. It will help you.

You can do this with C++20 std::format:
std::stringstream ss;
for (int i = 0; i < 32; ++i) {
ss << std::format("{:02}", buffer[i]);
}
Until std::format is widely available you can use the {fmt} library, std::format is based on. {fmt} also provides the join function that makes this even easier (godbolt):
std::string s = fmt::format("{:02}", fmt::join(buffer, ""));
Disclaimer: I'm the author of {fmt} and C++20 std::format.

Related

Control the Precision of float number in a string - C++

I'm trying to control the number of Digits i add in a String , but I couldn't control it since i am printing an Array of Strings .
float loads[n] = { 1,2,3,0.05,1,2,3,0.5,1,2,3,3,1,2 };
string print[nBits] = { "" };
int n=14;
int BB;
.
.
.
void main(){
for (int j = 0; j < nBits; ++j)// 2^n
{
for (int i = 0; i < n; ++i) // n
{
BB = arr[j][i];
R = loads[i];
if (BB == 1) {
print[j]+="" +std::to_string(loads[i])+"//";
}
}
}
But i eventually get an Array of strings that Looks like this :
0.050000//3.000000//...
Is there any way to control the Precision of the floating number before adding it to the String ?
(so i can have a resulting string control a fixed number of Digits instead)
0.05//3.00// ...
Use std::stringstream together with std::fixed and std::setprecision(n).
http://en.cppreference.com/w/cpp/io/manip
You can use the standard streaming mechanic:
streams
You can use ostream to generate the string:
#include <ostream>
#include <sstream>
#include <iomanip>
std::ostringstream stream;
for(...) {
stream << loads[i] << "//";
}
std::string str = stream.str();
The idea is to generate a stream that you can stream strings too. You can then generate a std::string out of it, using stream.str(). Streams have default values for how to convert numbers. You can influence this with std::setprecision and std::fixed as well as other variables (for more info, see the C++ stdlib reference).
Using std::setprecision and std::fixed.
std::ostringstream stream;
// set the precision of the stream to 2 and say we want fixed decimals, not
// scientific or other representations.
stream << std::setprecision(2) << std::fixed;
for(...) {
stream << loads[i] << "//";
}
std::string str = stream.str();
You find another example here.
sprintf
You can always go the C way and use sprintf although it's discouraged as you have to provide a buffer of correct length, e.g.:
char buf[50];
if (snprintf(buf, 50, "%.2f", loads[i]) > 0) {
std::string s(buf);
}

boost::lexical_cast int to string padding with zeros

I need to create files with generated names. I use boost::lexical_cast to transform integers to std::string. Is it a possibility to get string with padding zeros;
I have no c++11 tools, just everything that MSVS 2008 supports.
Example :
int i = 10;
std::string str = boost::lexical_cast<std::string>(i);
// str = "10"
// expect str = "000010"
p.s. don't suggest to use sprintf please.
Why boost::lexical_cast? Use std::stringstream
std::ostringstream ss;
ss << std::setw(6) << std::setfill('0') << i;
const std::string str = ss.str();
You could use std::ostringstream with the normal stream manipulators for formatting.

Equivalent of %05d with std::stringstream for negative numbers?

I'm trying to create a replacement for sprintfs' %05d behavior. Althought, I've found a similar question here on stackoverflow, the proposed solution there doesn't work for me when I'm testing with negative numbers.
Doing a "sprintf(buf, "%05d", -12)", I'm getting "-0012" back which looks nice.
Using stringstream, width and fill, I'm getting "00-12" which seams reasonable when looking at the docs from std::basic_ios::fill
The fill character is the character used by output insertion functions to fill spaces when padding results to the field width.
but doesn't look like something one could wish.
So I'm confused and don't know if I'm doing something obvious wrong or if width/fill from the std streams doesn't easily support this situation.
A compilable testcode can be found on codepad.
Here's an extract of the stream based conversion:
std::string NumberToString(const long iVal, const int iNumDigit)
{
std::stringstream ss;
if (iNumDigit >= 0) ss.fill(' ');
else if (iNumDigit < 0) ss.fill('0');
ss.width(std::abs(iNumDigit));
ss << iVal;
return ss.str();
}
EDIT1: Solution:
To match the std stream approach with printf formatting for %05d, jrok's solution can be used for the case with leading zeros. Here's the new function:
std::string NumberToString(const long iVal, const int iNumDigit)
{
std::stringstream ss;
if (iNumDigit >= 0) ss.fill(' ');
else if (iNumDigit < 0) { ss.fill('0'); ss.setf(std::ios::internal, std::ios::adjustfield); }
ss.width(std::abs(iNumDigit));
ss << iVal;
return ss.str();
}
Use stream manipulator std::internal.
It (along with std::left and std::right) lets you specify where the fill characters go. For example
std::cout << std::setw(5) << std::setfill('0') << std::internal << -1;
will print -0001.

Use stream instead of snprintf

I'm not fairly familiar in C++ stream API and I want to convert a C code using stream in C++,
char sHex[20] = {0};
int numid = 2;
snprintf( sHex, sizeof(sHex) - 1, "%X", numId );
stringstream ss;
ss << uppercase << hex << numId;
string res = ss.str();
Take a look at Understanding C++ Streams and Stream Buffers it may help you, like as helped me.

stringstreams and formatting

I am using C++ and writing a program that is supposed to do a bunch of stuff with primes. However the main issue is that I am having trouble converting in between ints and strings. I believe the following is the relevant code:
for(int j=0;j<size-1;j++){
num=primes[j];
ss<<num;
ss>>temp;
ss.str("");
for (int count=0; count < temp.size(); count++) {
cout<<temp<<endl;
}
I know that I could Google and figure out how to convert from an integer another way. However, I have a feeling that the reason I can't figure out what is going wrong is because I'm lacking some fundamental knowledge about stringstreams which I'm not aware of which I'm hoping can be fixed. num is an int and ss is a stringstream and cout temp is printing out 2 every single time, which is the value of primes[0]. I think the stringstream might be not reading after the first trial because of something to do with a newline character but I don't really know.
The reason for what you are experiencing is that the EOF_BIT will be set in ss after reading the first value into temp, after that no read/writes can be made to the std::stringstream and therefore temp is not updated with a new value.
A more human readable way of explaining the above; the std::stringstream ss will think that it has reached the end (which it has, at one point). You'll need to tell it to "start all over again" (reset all error-flags) for it to be usable in another iteration.
How do I solve this issue?
There are a few methods available, to me the most clear (in code readability) is to use a new std::stringstream for each iterator in your loop (see "Example solution #2).
Check out the snippets below that all will output:
2
3
5
7
11
13
17
Example solution #1
int const PRIMES_SIZE = 7;
int const primes[PRIMES_SIZE] = {2,3,5,7,11,13,17};
std::stringstream ss;
std::string temp;
for (int i =0; i < PRIMES_SIZE; ++i) {
ss << primes[i];
ss >> temp;
std::cout << temp << std::endl;
ss.clear (); // unset error flags
}
Example solution #2
int const PRIMES_SIZE = 7;
int const primes[PRIMES_SIZE] = {2,3,5,7,11,13,17};
for (int i =0; i < PRIMES_SIZE; ++i) {
std::stringstream ss;
ss << primes[i];
std::cout << ss.str () << std::endl;
}
Example solution #3
#include <iterator>
...
int const PRIMES_SIZE = 7;
int const primes[PRIMES_SIZE] = {2,3,5,7,11,13,17};
std::stringstream ss;
std::copy (primes, primes+PRIMES_SIZE, std::ostream_iterator<int> (ss, "\n"));
std::cout << ss.str ();