jstechg
jstechg

Reputation: 143

C++ cout does not display a hex byte in the correct format

In a program developed with C ++ on Linux I need to show the content of several arrays that contain bytes.

These arrays are declared as an array of characters.

I am trying to display its content with std::cout but I am not getting the output I need, lthough I have tried in several different ways.

I illustrate this with a simple program example:

#include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <iomanip>


int main()
{
   char data[10] = { 0 };

   for (uint8_t i=0; i<10; i++)
     data[i] = 5 + 2*i;

  printf ("ONE: 0x%02X 0x%02X 0x%02X 0x%02X\n", data[2], data[3], data[4], data[5]);

  std::cout << "TWO: " << std::setw(2) << std::hex << std::uppercase << std::left << std::setfill('0')
            << int(data[2]) << " " << int(data[3]) << " " << int(data[4]) << " " << int(data[5]) << std::endl;


  std::cout << "THREE: "
            << std::setw(2) << std::hex << std::uppercase << std::left << std::setfill('0')
            << int(data[2]) << " "
            << std::setw(2) << std::hex << std::uppercase << std::left << std::setfill('0')
            << int(data[3]) << " "
            << std::setw(2) << std::hex << std::uppercase << std::left << std::setfill('0')
            << int(data[4]) << " "
            << std::setw(2) << std::hex << std::uppercase << std::left << std::setfill('0')
            << int(data[5]) << std::endl;


  std::cout.setf(std::ios::hex | std::ios::left | std::ios::uppercase, std::ios::basefield);
  std::cout.width(2);             
  std::cout.fill('0');
  std::cout << "FOUR: " << int(data[2]) << " " << int(data[3]) << " "
            << int(data[4]) << " " << int(data[5]) << std::endl;

  return 0;
}

The printf output is correct, it corresponds to the format I need:

ONE: 0x09 0x0B 0x0D 0x0F

The output I get in the TWO case is: TWO: 90 B D F The output I want to get is: TWO: 09 0B 0D 0F It presents the following errors:

The TRHEE case ensures that the output of each data is always two characters wide: THREE: 90 B0 D0 F0 The output I want to get is: THREE: 09 0B 0D 0F It presents the following errors:

The FOUR case shows: FOUR: 9 B D F The output I want to get is: FOUR: 09 0B 0D 0F It presents the following errors:

What is the correct way to use cout so that it shows 09 0B 0D 0F?

What should I change in the program?

Upvotes: 1

Views: 1056

Answers (1)

JohnFilleau
JohnFilleau

Reputation: 4288

You want to align your characters to the right (std::right) so that your fill character occupies everything to the left of it. std::setw only applies to the next formatted output that can be modified by std::setw, which means only the first datapoint will have a width of 2.

Note that std::right is the default for a std::ostream such as std::cout, but I'm leaving it in here since the stream could be in an unknown state beforehand.

std::setfill, std::left, std::hex can be set once and apply to the stream until they're reset. The best practice would be to save the current stream state, set it how you want, and then restore it when you're done. This is described in this answer https://stackoverflow.com/a/2273352/2027196

You want

// save stream format
std::ios_base::fmtflags f( cout.flags() );

// set format flags we want
std::cout << std::right << std::hex << std::uppercase << std::setfill('0');

// do actual output

std::cout << "THREE: "
          << std::setw(2) << int(data[2]) << " "
          << std::setw(2) << int(data[3]) << " "
          << std::setw(2) << int(data[4]) << " "
          << std::setw(2) << int(data[5]) << "\n";

// restore prior IO flags
cout.flags( f );

Upvotes: 4

Related Questions