1

I want to accept a uint8_t vector into a function, which every element is then converted to a 2-digit (all digits not used are 0) written hexadecimal stored in a string. I think I might be getting confused here...

I figured a way to do it with printf (I think):

std::vector<uint8_t> name1 = { 's', '2', '9', '2', 'a', 'b' };

    for (int i = 0; i < name1.size(); i++) {
        printf("printf: %002X ", name1[i]);
        std::cout << std::endl;
    }

But then the idea is that I create a string such as:

MSGPACK 733239326162

where 73 is s, 32 is 2 obviously etc...

So I want to put the above MSGPACK...162 into a variable which stores it and then later do something like printf(msgpack1).

I tried the following way...

char buffer[40];

std::vector<uint8_t> name1 = { 's', '2', '9', '2', 'a', 'b' };

for (int i = 0; i < name1.size(); i++) {
    snprintf(buffer, sizeof(buffer), "%002X", name1[i]);
}

buffer[name1.size()] = '\0';

so I was hoping that I could print it all out like this:

printf("MSGPACK %s", buffer);

I'm not sure what I'm doing wrong here, but I'm getting MSGPACK 62 as output instead. How to get what I need?

Edit: I see that buffer is overwritten now with the last member of vector, but I can't place just buffer[i] into snprintf, so what would be the way to go about it?

Tryb Ghost
  • 419
  • 1
  • 4
  • 14
  • https://stackoverflow.com/questions/5100718/integer-to-hex-string-in-c – Tzalumen Mar 26 '19 at 14:55
  • @Tzalumen The idea is that I don't use much overhead since I'm working with mbed... vector is already quite alot, which is why I'd rather avoid stringstreams and implement this part only using c libraries... – Tryb Ghost Mar 26 '19 at 14:58
  • you are overwriting `buffer` at each `sprintf` call inside your loop. you need to somehow write to the correct index at `buffer`. If you notice, your last character `b` is hex `62`. – MFisherKDX Mar 26 '19 at 14:58
  • In that case, make sure to bounds-check your `buffer[name1.size()] = '\0';` Not your problem, but the potential cause of a segfault. – Tzalumen Mar 26 '19 at 15:01
  • well ... I had typed up a nice answer and now the questions got closed and I lost everything I typed. Here's the jist. `snprintf` returns the number of characters printed (excluding the null byte). Use the return value of `snprintf` to keep track of which index into `buffer` to write on the next iteration. – MFisherKDX Mar 26 '19 at 15:04
  • 1
    @SergeyA I think the question should be re-opened. This is a "why isn't my code working" question with both input and expected output and the bug is subtle. It's not a duplicate in the sense that the duplicate can't explain why the OP's code isn't working as expected. – MFisherKDX Mar 26 '19 at 15:07
  • *Edit: I see that buffer is overwritten now with the last member of vector, but I can't place just buffer[i] into snprintf, so what would be the way to go about it?* --> I can't post an answer, but you can set `size_t n=0` above the loop, pass `buffer+n` and `sizeof(buffer)-n` to `snprintf` and then add the return value of `snprintf` to `n`. Your loop should exit when you've reached the end of the vector or when `snprintf` has failed to write 2 bytes. – MFisherKDX Mar 26 '19 at 15:22
  • @MFisherKDX While what he needed was not addressed, the question as titled is a duplicate. Tryb Ghost should, as recommended, ask a new question, titling it something like "Why doesn't my string print as expected?", so it gets handled properly. – Tzalumen Mar 26 '19 at 15:26
  • @Tzalumen Is a new question required, wouldn't changing this question's title to your suggestion be sufficient? Edit: Never-mind, that title is not even accepted by the edit and I don't seem to be able to come out with a better title. – Tryb Ghost Mar 26 '19 at 15:28
  • Asking new question would remove all these comments and the one posted answer. I don't believe that is a good solution. This question should re-opened. – MFisherKDX Mar 26 '19 at 15:35
  • In general, stack overflow prefers new questions over refactoring an existing question. – Tzalumen Mar 26 '19 at 15:36
  • @Tzalumen, that is not my impression. See the accepted answer on meta here: https://meta.stackexchange.com/a/217394 – MFisherKDX Mar 26 '19 at 15:38
  • Also, with respect to using stringstream, consider what my mentor told me repeatedly: "Don't pre-optimize at the cost of clarity or simplicity." Until you are done, you won't know for sure if you're butting up against the limits of your system, or even if the stringstream is providing noticable overhead costs. – Tzalumen Mar 26 '19 at 15:39

1 Answers1

1
std::vector<uint8_t> name1 = { 's', '2', '9', '2', 'a', 'b' };
int buffsize = name1.size()*2+1;
char buffer[buffsize];
int retvalue = 0;

for (int i = 0; i < name1.size()*2 && retvalue >= 0 && retvalue < buffsize; i++) {
        retvalue = snprintf(buffer+2*i, sizeof(buffer)-2*i, "%002X", name1[i]);
}

buffer[buffsize-1] = '\0';

printf("MSGPACK %s", buffer);

Output:

MSGPACK 733239326162
glhr
  • 4,439
  • 1
  • 15
  • 26
  • 1
    how on earth were you able to post an answer? when I try the system tells me the question is closed and answers will not be accepted? Anyway, you have some errors. 1) `sizeof(buffer)` as an argument to `snprintf` is wrong and needs to be reduced by the number of characters already written, 2) you should really check the return value of `snprintf` instead of just assuming it will succeed (because it won't when the string is too large), 3) `buffer[name1.size()*2]` is wrong in the sense it doesn't take into account failure modes (when the string is too big for instance). – MFisherKDX Mar 26 '19 at 15:13
  • 1
    The `buffer` should probably be defined after `name1` with `std::unique_ptr buffer(new char[name1.size() * 2 + 1]);` to ensure a good fit and no out-of-bounds when he calls `buffer[name1.size()*2] = '\0';` – Tzalumen Mar 26 '19 at 15:15
  • I guess I managed to submit my answer before the question was closed. Thanks @MFisherKDX and Tzalumen, I tried incorporating your feedback. Would be interested in seeing your take on this. – glhr Mar 26 '19 at 15:40
  • 1
    @glhr `const int buffsize = name1.size()*2+1; char buffer[buffsize];` will not compile, you can't hack around the constexpr requirement of scope array allocation like that. – Tzalumen Mar 26 '19 at 15:42
  • My answer was rejected. A few minutes later your answer was posted. In fact, your answer was posted 9 minutes *after* the question was closed. Must be a bug in the system. Kudos to you! Were you on mobile by any chance? – MFisherKDX Mar 26 '19 at 15:44
  • @Tzalumen https://repl.it/@glhr/55359990 runs fine here. – glhr Mar 26 '19 at 15:47
  • @MFisherKDX I'm on desktop... waiting for my Hogwarts letter. – glhr Mar 26 '19 at 15:48
  • 1
    @glhr that might have been revised post-C++11, or it might be something Clang allows, but MSVC 14 rejects it as `error C2131: expression did not evaluate to a constant` – Tzalumen Mar 26 '19 at 15:50