web-dev-qa-db-fra.com

imprimer un caractère unicode avec printf

J'essaie d'imprimer un Ș en transmettant la valeur décimale correspondante à printf. La sortie n'est rien du tout. Pourquoi mon code ne fonctionne pas?

#include <stdio.h>
int main()
{
    printf("%lc",536);
    return 0;
}
6
Mike

Sur macOS Sierra 10.12.2 avec GCC 6.3.0, si je lance ce programme (compilé à partir de mb37.c dans mb37):

#include <locale.h>
#include <stdio.h>
#include <wchar.h>      /* wint_t */

int main(void)
{
    setlocale(LC_ALL, "");
    printf("%lc\n", (wint_t)536);
    return 0;
}

la sortie est:

$ ./mb37
Ș
$

Je pense que c'est le résultat souhaité. Si la ligne setlocale() est supprimée, aucune sortie n'est générée, pas même une nouvelle ligne. Les paramètres régionaux utilisés sont en_US.UTF-8; mon terminal gère également UTF-8. Le nom de l'environnement local est trouvé en capturant et en imprimant la valeur de retour de setlocale() - une chaîne normale.

La distribution wint_t est semi-facultative; il se trouve qu'une compilation 64 bits sans la conversion ni l'en-tête <wchar.h> produit également le même résultat, mais il existe une légère coïncidence si wint_t est identique à int. Cela prend un peu de suivi; wint_t est défini en tant que __darwin_wint_t qui est défini en tant que __darwin_ct_rune_t qui est défini en tant que int. Pour être correctement portable, le casting est nécessaire. Sur certains systèmes, cela peut ne pas être nécessaire (et macOS Sierra en est un exemple).

La nouvelle ligne dans printf() n'est pas nécessaire à 100%, mais si elle est omise, l'invite suivante suit immédiatement la LETTRE MAJUSCULE LATINE U + 0218 AVEC COMMA CI-DESSOUS. Il est préférable de s’assurer que la sortie se termine par une nouvelle ligne.

4
Jonathan Leffler

Le spécificateur de longueur l appliqué à un descripteur de champ c indique que l'argument correspondant est de type wint_t (déclaré dans wchar.h). Dans votre code, l'argument est du type int, qui peut être identique ou non. Si ce n'est pas le cas, le comportement est indéfini. Vous pouvez obtenir un wint_t en convertissant ...

    printf("%lc", (wint_t) 536);

; c'est le moyen le plus sûr et le plus portable d'exprimer une constante wint_t.

De plus, il y a une question potentielle de jeux de caractères ici. C'est une question d'environnement dans lequel votre programme fonctionne, pas tellement le programme lui-même. Il est concevable que votre programme génère effectivement le caractère en question, dans un certain encodage, mais le terminal dans lequel vous exécutez ne sait pas le manipuler, ou peut-être n'a tout simplement pas de glyphe. Vous devriez pouvoir le tester en redirigeant la sortie vers un fichier, puis en examinant le contenu du fichier (éventuellement sous forme de fichier binaire).

4
John Bollinger

C n’exige pas qu’une ligne sans fin de ligne soit imprimée. Essayez "% lc\n". 

0
gnasher729