Nordlöw
Nordlöw

Reputation: 12138

Printing chars as Integers

I want to control whether my ostream outputting of chars and unsigned char's via << writes them as characters or integers. I can't find such an option in the standard library. For now I have reverted to using multiple overloads on a set of alternative print functions

ostream& show(ostream& os, char s) { return os << static_cast<int>(s); }
ostream& show(ostream& os, unsigned char s) { return os << static_cast<int>(s); }

Is there a better way?

Upvotes: 9

Views: 2363

Answers (4)

malat
malat

Reputation: 12506

Just an update to an old post. The actual trick is using '+'. Eg:

template <typename T>
void my_super_function(T x)
{
  // ...
  std::cout << +x << '\n';  // promotes x to a type printable as a number, regardless of type
  // ...
}

In C++11 you could do:

template <typename T>
auto promote_to_printable_integer_type(T i) -> decltype(+i)
{
  return +i;
}

Credit: How can I print a char as a number? How can I print a char* so the output shows the pointer’s numeric value?


Works for both signed/unsigned char:

Upvotes: 1

vitaut
vitaut

Reputation: 55564

In C++20 you'll be able to use std::format to do this:

unsigned char uc = 42;
std::cout << std::format("{:d}", uc); // format uc as integer 42 (the default)
std::cout << std::format("{:c}", uc); // format uc as char '*' (assuming ASCII)

In the meantime you can use the {fmt} library, std::format is based on.

Disclaimer: I'm the author of {fmt} and C++20 std::format.

Upvotes: 0

Michael Kristofik
Michael Kristofik

Reputation: 35188

No, there isn't a better way. A better way would take the form of a custom stream manipulator, like std::hex. Then you could turn your integer printing off and on without having to specify it for each number. But custom manipulators operate on the stream itself, and there aren't any format flags to do what you want. I suppose you could write your own stream, but that's way more work than you're doing now.

Honestly, your best bet is to see if your text editor has functions for making static_cast<int> easier to type. I assume you'd otherwise type it a lot or you wouldn't be asking. That way someone who reads your code knows exactly what you mean (i.e., printing a char as an integer) without having to look up the definition of a custom function.

Upvotes: 1

Andriy
Andriy

Reputation: 8604

I have a suggestion based on the technique used in how do I print an unsigned char as hex in c++ using ostream?.

template <typename Char>
struct Formatter
  {
  Char c;
  Formatter(Char _c) : c(_c) { }

  bool PrintAsNumber() const
    {
    // implement your condition here
    }
  };

template <typename Char> 
std::ostream& operator<<(std::ostream& o, const Formatter<Char>& _fmt)
  {
  if (_fmt.PrintAsNumber())
    return (o << static_cast<int>(_fmt.c));
  else
    return (o << _fmt.c);
  }

template <typename Char> 
Formatter<Char> fmt(Char _c)
  {
  return Formatter<Char>(_c);
  }

void Test()
  {
  char a = 66;
  std::cout << fmt(a) << std::endl;
  }

Upvotes: 0

Related Questions