user3424141
user3424141

Reputation:

Using sprintf with unicode characters

I wanted to print out depictions of playing cards using Unicode.

Code snippet:

void printCard(int card){
    char strCard[10];
    sprintf(strCard, "\U0001F0A%x", (card%13)+1);
    printf("%s\n", cardStr);
}

Since the \U requires 8 hex characters after it I get the following from compiling:

error: incomplete universal character name \U0001F0A

I could create a bunch of if/else statements and print out the card that way but I was hoping for a way that wouldn't make me explicitly write out every card's Unicode encoding.

Upvotes: 1

Views: 9725

Answers (2)

chqrlie
chqrlie

Reputation: 144810

A quick and dirty UTF-8 solution:

void printCard(int card) {
    printf("\xF0\x9F\x82%c\n", 0xA1 + card % 13);
}

The UTF-8 representation of \U0001F0A1 is F0 9F 82 A1. The above code will correctly handle all 13 cards, if your terminal supports UTF-8 and non-BMP code points, like iTerm2 on OS/X.

Alternative solutions involving wide-char conversion to multibyte character sets are complicated to use and would not work on platforms where wchar_t is limited to 16 bits.

Upvotes: 1

rici
rici

Reputation: 241821

Universal character names (like \U0001F0A1) are resolved by the compiler. If you use one in a format string, printf will see the UTF-8 representation of the character; it has no idea how to handle backslash escapes. (The same is true of \n and \x2C; those are single characters resolved by the compiler.) So you certainly cannot compute the UCN at runtime.

The most readable solution would be to use an array of strings to hold the 13 different card symbols.

That will avoid hard-wiring knowledge about Unicode and UTF-8 encoding into the program. If you knew that the active locale was a UTF-8 locale, you could compute the codepoints as a wchar_t and the use wide-character-to-multibyte standard library functions to produce the UTF-8 version. But I'm not at all convinced that it would be worthwhile.

Upvotes: 3

Related Questions