Home > Software design >  printf - raw string literal with format macro of fixed width integer types
printf - raw string literal with format macro of fixed width integer types

Time:07-09

How do I use raw string literal R with format macro of fixed width integer types?

For example

std::int64_t num = INT64_MAX;
std::printf(R"("name":"%s", "number":"%")" PRId64, "david", num); // wrong syntax

The output should be

"name":"david", "number":"9223372036854775807"

Use of escape sequences instead of R is not permitted

CodePudding user response:

Firstly, you should check your current format string with puts().

#include <cstdio>
#include <cinttypes>

int main(void) {
    std::puts(R"("name":"%s", "number":"%")" PRId64);
    return 0;
}

Result:

"name":"%s", "number":"%"ld

Now you see the errors:

  • You have an extra " between % and ld.
  • " is missing after ld.

Based on this, fix the format string:

#include <cstdio>
#include <cinttypes>

int main(void) {
    std::int64_t num = INT64_MAX;
    std::printf(R"("name":"%s", "number":"%)" PRId64 R"(")", "david", num);
    return 0;
}

Result:

"name":"david", "number":"9223372036854775807"

CodePudding user response:

@MikeCAT's answer shows how to do this with string literal concatenation at compile-time.

Another option would be to create the format string at runtime instead, eg:

char fmt[36] = {};
std::sprintf(fmt, R"("name":"%%s", "number":"%%%s")", PRId64);
std::printf(fmt, "david", num);

Or:

std::string fmt = R"("name":"%s", "number":"%)"   std::string(PRId64)   R"(")";
std::printf(fmt.c_str(), "david", num);

Though, I would not rely on using PRId64 at all, I would let C format the num for me, eg:

std::cout << R"("name":)" << std::quoted("david") << R"(, "number":)" << std::quoted(std::to_string(num));

Or, in C 20 (or using the {fmt} library):

std::cout << std::format(R"("name":"{}", "number":"{}")", "david", num);
  • Related