Caractères

Les différents caractères qui servent à composer un texte doivent être choisis parmi une liste. Il existe plusieurs listes possibles, parmi lesquelles on retiendra surtout :

ASCII
La plus ancienne table encore utilisée. Numérotée de 0 à 127, cette liste regroupe les caractères les plus importants mais n'a pas assez de place pour les glyphes non-anglophones, tels que les caractères accentués. Il faut 7 bits pour stocker un encodage ASCII.
latin 1
Officiellement nommée ISO-8859-1, cette liste reprend entièrement la table ASCII, et rajoute de nouveaux caractères pour les numéros allant de 128 à 255. On trouve dans cette extension tous les caractères nécessaires pour écrire en français. Il faut 8 bits pour stocker un encodage latin 1.
Unicode
La liste la plus complète comprend actuellement 110000 caractères, et possède assez de place pour en contenir des milliards au besoin. Il faut entre 8 et 32 bits pour stocker un encodage UTF-8. Les caractères provenant de la table ASCII conservent leur numéro et sont stockés sur 8 bits. Les caractères accentués sont généralement stockés sur 16 bits.

Quand on tape un texte dans un programme (console ou éditeur de texte), ce sont seulement les numéros qui sont stockés, en utilisant l'encodage configuré dans le programme. Quand ce même texte est affiché ensuite, les numéros sont convertis en symboles en utilisant une police de caractères. Si l'encodage correspondant à cette police différe de l'encodage d'origine du texte, l'affichage sera altéré (le plus souvent, les caractères accentués sont mal représentés).

Dans son mode le plus simple, le langage C utilise un seul octet (8 bits) pour stocker le numéro d'un caractère.

Pour un encodage en ASCII ou en latin 1, un octet est suffisant. Pour un encodage en UTF-8, il faut entre 1 et 4 octets pour représenter un symbole, mais pour simplifier nous continuerons à utiliser le terme de «caractère» pour indiquer un octet et non un symbole.

Un caractère est identifié dans un fichier source par des apostrophes :

printf("%c", 'A');
Remarque Le format qui permet de demander à printf d'afficher un caractère est "%c".

Lorsque le caractère n'est pas imprimable ou possède un sens spécial, on utilise l'échappement :

printf("%c", '\t');
printf("%c", '\'');
Et pour tous les autres cas, on peut aussi donner directement le numéro si on le connait, en octal ou en hexadécimal.
printf("%c", '\101');
printf("%c", '\x41');
Enfin, si on souhaite stocker un caractère dans la mémoire, on peut définir une variable de type caractère.
char lettre = 'A';
Remarque Les caractères sont des entiers ! On peut donc leur appliquer tous les opérateurs vus précédemment.

Lorsqu'une console est en train d'exécuter une de vos commandes, tous les caractères que vous tapez sont envoyés au programme correspondant (vous en avez fait l'expérience avec la commande man). Ces caractères sont stockés temporairement dans une zone mémoire nommée tampon, en attendant d'être traités.

Les programmes écrits en langage C ne font pas exception à la règle. Vous pouvez donc piocher dans le tampon pour savoir ce que tape l'utilisateur de votre programme. L'une des fonctions qui vous le permettent se nomme getchar et elle est partiellement définie dans le fichier stdio.h.

int main(void) {
  char lettre;
  lettre = getchar();
  printf("J'ai lu : %c\n", lettre);
  return EXIT_SUCCESS;
}
Lorsque getchar est exécutée, elle extrait du tampon le plus ancien caractère non traité. Celui-ci n'est alors plus dans le tampon, puisqu'il vient d'être traité.

Le symbole = représente ici l'affectation : il prend le résultat de l'exécution de la fonction et le place dans la variable lettre.
Remarque L'affectation ressemble à l'initialisation que l'on peut écrire au moment de définir une variable. Elle utilise d'ailleurs le même symbole. Par contre, elle est radicalement différente de la notion d'égalité en mathématiques (malgré les similitudes dans la notation).

Si le tampon est vide lorsque getchar est exécutée (ce qui est probable), le programme s'interrompt et attend que l'utilisateur le remplisse. Comme lorsqu'il tape une commande, l'utilisateur a tout son temps pour choisir quoi entrer. Il peut éditer son texte, en effacer une partie, et copier-coller. Ce qu'il a composé ne sera envoyé au programme que quand il appuiera sur la touche «entrée».

  1. Salut. Reprenez le programme salut.c et faites-en une version qui produit le même résultat mais en remplaçant la constante littérale texte "Hello World!\n" par des constantes littérales caractères.
  2. Chiffres. Dans l'encodage ASCII, le numéro du chiffre 7 n'est malheureusement pas 7 (ce serait trop simple). Néanmoins, tous les chiffres sont côte à côte dans la table ASCII (par ordre croissant).

    Sachant cela, et sans regarder la table ASCII, écrivez un programme qui affiche le caractère 7 sans employer ce caractère dans le fichier source.

  3. Lettres. Dans l'encodage ASCII, la minuscule et la majuscule d'une lettre ont le même numéro, à un petit détail près : le bit numéro 5 (celui qui correspond à 2⁵) vaut 1 pour une minuscule, et 0 pour une majuscule.

    Sachant cela, et toujours sans regarder la table ASCII, écrivez un programme qui affiche un A majuscule sans employer aucune majuscule dans le fichier source.

  4. Encodages. La console où vos programmes affichent leurs résultats utilise certainement une police de caractères dont l'encodage inclut les caractères accentués. Le problème est que suivant l'encodage employé, le numéro pour un caractère précis n'est pas le même.

    Essayez le programme suivant, qui tente d'afficher un î :

    int main(void) {
      printf("Unicode : %c%c\n", '\xC3', '\xAE');
      printf("Latin 1 : %c\n", '\xEE');
      return EXIT_SUCCESS;
    }
    Que pouvez-vous en déduire ?

    Peut-être que cette solution vous paraît pénible. On peut tenter plus simple :

    int main(void) {
      printf("%c\n", 'î');
      return EXIT_SUCCESS;
    }
    Qu'obtenez-vous ? Qu'en déduisez-vous à propos de votre éditeur de texte ?

    Vous comprenez à présent pourquoi nous éviterons les accents dans nos futurs exercices.

  5. Extraction. Écrivez un programme qui demande à l'utilisateur son numéro de sécurité sociale, puis affiche ses mois et année de naissance au format mm/aa.

retour à la page d'accueil

retour au sommet