1

How can I convert this code from C into C++ ?

char out[61]; //null terminator
for (i = 0; i < 20; i++) {
    snprintf(out+i*3, 4, "%02x ", obuf[i])
}

I can't find any alternative for snprintf.

Blacktempel
  • 3,935
  • 3
  • 29
  • 53
ar2015
  • 5,558
  • 8
  • 53
  • 110
  • Have you considered `sprintf()`? If you are reasonably sure that no user-supplied data could overflow the buffer, I wouldn't bother with the "safer" version. That said, your string has a fixed layout, all you need is to extract low and high nibble (`x&15`, `x>>4`) and then format them as hex (`"0123456789abcdef"[nibble]`) and store them in the right position. Providing a format string that needs to be parsed in order to format another string is kind-of ugly... – Ulrich Eckhardt Mar 26 '15 at 06:49
  • One more note: If you have tried the obvious and used `stringstream`s, the reason it failed is that it considers every char (even if it's `typedef`d as `byte` or `uint8_t`) a letter, so you have to `static_cast` it. – Ulrich Eckhardt Mar 26 '15 at 06:52
  • Possible duplicate of [What is the C++ idiom to replace snprintf(3)?](http://stackoverflow.com/questions/5847480/what-is-the-c-idiom-to-replace-snprintf3) – jww Nov 28 '15 at 04:38
  • 1
    @UlrichEckhardt, I would suggest always using snprintf instead of sprintf. It can be very dangerous and there no benefit of using sprintf instead so go with the safer snprintf. Some of the hardest bugs I've ever tracked down were from someone using sprintf with a buffer too small. That said, the OP use of snprintf is just as dangerous. If the size of out[] gets changes or his for loop uses another arbitrary length instead of 20 snprintf will not effectively prevent memory beyond out[] from being written too. Thankfully the move to stringstream will result in safer code. – Craig B Dec 20 '17 at 22:58
  • The only reason for not using it would be that it isn't there, but those implementations should be a thing of the past. BTW: 61, 20, 3 are all "magic numbers" that render this code brittle, because you will have to adjust at least two of them together, which then leads to the scenario that Craig describes if you forget one. – Ulrich Eckhardt Jan 07 '18 at 10:40

4 Answers4

8

Use stringstream class from <sstream>.

E.g.:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;

int main()
{
    stringstream ss;
    for (int i = 0; i < 20; i++) {
        ss << setw(3) << i;
    }
    cout << "Resulting string: " << endl;
    cout << ss.str() << endl;
    printf("Resulting char*: \n%s\n", ss.str().c_str() );
    return 0;
}
VolAnd
  • 6,367
  • 3
  • 25
  • 43
  • 5
    Using `stringstream`s and then outputting via `printf()`, seriously? – Ulrich Eckhardt Jan 07 '18 at 10:34
  • `cout << ss.str()` and `printf` for `ss.str().c_str()` are two available options. Of course, using `printf` is not the best option but it is possible – VolAnd Jan 09 '18 at 09:01
  • There's also an `operator<<` for a `streambuf*`. – Ulrich Eckhardt Jan 09 '18 at 23:52
  • @UlrichEckhardt what do you mean? Is there a third alternative? – luizfls Aug 24 '19 at 23:08
  • @VolAnd Note that as written, that is UB since `c_str()` might give a dangling pointer if you don't assign the string to a variable first. [See here](https://stackoverflow.com/questions/21034834/is-there-issue-will-stringstream-str-c-str) – Coder-256 May 07 '23 at 02:34
3

This code is valid C++11, if you have #include <cstdio> and type std::snprintf (or using namespace std;).

No need to "fix" what isn't broken.

M.M
  • 138,810
  • 21
  • 208
  • 365
0

You can use Boost.Format.

#include <boost/format.hpp>
#include <string>

std::string out;
for (size_t i=0; i<20; ++i)
    out += (boost::format("%02x") % int(obuf[i])).str();
jyw
  • 135
  • 1
  • 3
0

You can convert this code from C to C++ easily with standard library's std::stringstream and iomanip I/O stream manipulators:

#include <sstream>
#include <iomanip>
...

std::ostringstream stream;
stream << std::setfill('0') << std::hex;

for (const auto byte : obuf)
  stream << std::setw(2) << byte;

const auto out = stream.str();
mrts
  • 16,697
  • 8
  • 89
  • 72