Hi!

I've recently converted some C code to a bit more native C++. This included changing printf() statements to std::cout statements. However, some printf()'s are rather lengthy and annoyingly long (and human-error-prone) to write in std::cout. Example (and this one is a short one):

C-style:

printf("ERROR %d: %s: %s\n", event, origin ? origin : "?", fulltext.c_str());

C++-style:

std::cout << "ERROR " << event << ": " << origin ? origin : "?" << ": " << fulltext << "\n";

I personally find the first way much more clear and easier to write. What is the recommended way to do this in C++?

Dani AI

Generated

A concise, modern alternative to long std::cout chains is to use C++20’s std::format (or the portable {fmt} library when the standard library does not provide <format>). That keeps the familiar placeholder style of printf while giving compile-time checks and C++ type-safety. This also lets ’s advice (encapsulate repeated message shapes in a small helper) stay compact and readable, and it complements ’s point that structured error handling (exceptions) can separate formatting from control flow.

#include <format>
#include <iostream>

std::cout << std::format("ERROR {}: {}: {}\n",
    event,
    origin ? origin : "?",
    fulltext);

std::format is the standard C++ facility for this style of formatting; when your toolchain lacks it, use the {fmt} library which exposes fmt::format and fmt::print and is the basis for the standard API. std::format (cppreference) (cppreference.com) fmt library docs (fmt.dev)

Practical notes: centralize formatting in a small logging/report function so call sites stay short (as suggested). When mixing << and the ternary operator, remember to parenthesize the ternary expression — otherwise precedence gives a surprising parse. For quick migration keep printf only where isolated and safe, but prefer std::format/fmt for maintainability and safety. For operator precedence details see the language reference. Operator precedence (cppreference) (cppreference.com)

Recommended Answers

All 4 Replies

Well, considering that this is an error report, you may want to consider try/catch blocks and exceptions:

try {
  //some code
  //some code
  //ERROR
  throw errorType
} catch (const errorType &e) {
  cout << "ERROR: " << e.what() << endl;
}

Well you could just put a bit more "style" into it:

std::cout << "ERROR " << event 
          << ": "     << (origin ? origin : "?") 
          << ": "     << fulltext 
          << std::endl;

It takes more lines of code, but it is worth it in terms of clarity.

If you have code like this that gets repetitive, like an error report that is basically always "event" "origin" "message", then just make a function for that:

inline void report_error(int event, const std::string& origin, const std::string& message) {
  std::cout << "ERROR " << event 
            << ": "     << (origin ? origin : "?") 
            << ": "     << message 
            << std::endl;
};

Or use a MACRO like this:

#define ERROR_REPORT(A,B,C) "ERROR " << A << ": " << (B ? B : "?") << ": " << C

//and use it as:
std::cout << ERROR_REPORT(event,origin,fulltext) << std::endl;

Or use exception messages as Fbody said.

Or, just use printf, if you prefer, there's nothing really wrong with that. You should always consider the C++ options first because they are often better, but wherever the C style works fine, it's ok too (as long as it is within a small piece of code that is well encapsulated).

In this case it was an error report, but I write printf() in general MUCH faster then std::cout. Perhaps it's habit that will go away after a while.

Your eyes will also get used to the C++ version with time. For instance, I find the C++ version you posted more appealing to the eye. And your fingers will also get used to it, believe me.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.