1

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:

  • Only the first data of the array appears with a width of two characters. The others are shown with a width of one character.
  • Value 9 is displayed as 90 when it should be 09 What should I change in this cout statement?

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:

  • Shows "0" on the right, instead of on the left.
  • It is too cumbersome to have to set the exit indicators again before of displaying a new value in the same cout statement.

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:

  • Does not show each data with two characters in width and a "0" on the left.

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

What should I change in the program?

jstechg
  • 123
  • 1
  • 2
  • 10

1 Answers1

4

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 );
JohnFilleau
  • 4,045
  • 1
  • 15
  • 22
  • 1
    I don't think `std::right` is needed [here](https://godbolt.org/z/_RixkH) – cigien Jul 02 '20 at 16:52
  • Oh is that default? – JohnFilleau Jul 02 '20 at 16:54
  • 1
    Yes, I believe so. It's only needed if the stream was previously set to `left`. Also, minor typo, you have an extra `;` after THREE – cigien Jul 02 '20 at 16:55
  • Nice. Going to leave it in but make a note since it's possible the last person didn't clean up the stream correctly. I tried finding out what the ostream flags are set to by default, but couldn't find it :( – JohnFilleau Jul 02 '20 at 16:57
  • 1
    @cigien thanks. God I love peer review. Totally not because I'm lazy. Nope. Not that at all. – JohnFilleau Jul 02 '20 at 16:58