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?

4
  • The flags and formatting for TWO messes up the output for THREE. Try commenting out TWO and see how TREE might change. Commented Jul 2, 2020 at 16:45
  • On another note, you don't really need std::left justification. Justification is only important if the output is shorter than the field width. Commented Jul 2, 2020 at 16:47
  • std::cout << std::setw(2) << std::setfill('0') << ... Commented Jul 2, 2020 at 16:47
  • @Someprogrammerdude indeed that's the problem, if you use right justification instead it should be correct. Commented Jul 2, 2020 at 16:48

1 Answer 1

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 ); 
Sign up to request clarification or add additional context in comments.

5 Comments

I don't think std::right is needed here
Oh is that default?
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
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 :(
@cigien thanks. God I love peer review. Totally not because I'm lazy. Nope. Not that at all.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.