Mini-cours de C

Partie III

Maintenant, vous connaissez l'essentiel du C.

Cependant, le C dispose de nombreuses subtilités. La fonction printf(), essentielle à l'affichage, en contient plusieurs.

Afficher des données : printf()

Cette fonction est la plus utilisée car elle permet d'afficher quelque chose dans la console. Pas seulement un résultat, mais aussi les messages invitant les utilisateurs à fournir des données.

Affichage :

Code :

#include <stdio.h>

int main()
{
  printf("Veuillez entrer votre nom : "); // invitation à fournir des données

  int nombrEntier = 17;
  printf("\n"); // \n signifie "new line"
  printf("La variable 'nombrEntier' vaut : %d\n", nombrEntier);

  printf("\nCaractEres spEciaux : (\\) et (%%) \n\n");

  int nombrEntier2 = 13;
  printf("%d + %d = %d\n", nombrEntier, nombrEntier2, nombrEntier+nombrEntier2);

  char lettreA = 'A'; // et non ="A" (si guillemets => string)
  printf("\nLa variable 'lettreA' vaut : %c \n", lettreA);
  printf("La variable 'lettreA' vaut : %d (en dEcimal)\n", lettreA);
  printf("La variable 'lettreA' vaut : %x (en hexadEcimal)\n", lettreA);
  printf("La minuscule de 'A' est : %c\n\n", lettreA+32);

  char prenom[7] = "Thibaut"; // string => dernier caractère = NUL
  printf("La variable 'prenom' vaut : %s\n\n", prenom);

  // C est un langage qui permet de consulter la mémoire.
  printf("Adresse du tableau 'prenom' : %d (en dEcimal)\n", &prenom);
  printf("Adresse de la variable 'nombrEntier' : %d (en dEcimal)\n\n", &nombrEntier);

  char prenom2[8] = "Thibaut"; // 8 = nombre de caractères +1
  printf("La variable 'prenom2' vaut : %s\n", prenom2);

  prenom2[4]='\0'; // placement d'un NUL dans la cinquième case du tableau
  printf("La variable 'prenom2' vaut maintenant : %s\n", prenom2);
  printf("La septiEme case vaut toujours : '%c'\n", prenom2[6]);

  double nombrReel = 12.99; // point décimal
  printf("\nLa variable 'nombrReel' vaut : %f\n", nombrReel);
  printf("La variable 'nombrReel' vaut : %.2f\n\n", nombrReel);

  double const PI = 3.1415926535897932; // constante => en majuscule = tradition
  printf("La constante 'PI' (3.1415926535897932) vaut : %f\n", PI);
  printf("PI * 1 000 vaut : %f\n", PI*1000);
  printf("PI * 1 000 000 vaut : %f\n", PI*1000000);
  printf("PI * 1 000 000 000 vaut : %f\n", PI*1000000000);

  return 0;
}

printf("Veuillez entrer votre nom : ");
Facile ! Il suffit de mettre le message à afficher entre guillemets.

printf("\n");
\n est un code qui signifie, dans une chaîne de caractères, retour à la ligne (new line).

Certains caractères ont une signification spéciale. Pour les afficher seul, il faut les doubler.

Pour afficher le caractère (\), appelé anti-slash, il faut taper : \\
Pour afficher le caractère (%), appelé pourcentage, il faut taper : %%

printf("La variable 'nombrEntier' vaut : %d", nombrEntier);
Ici, la fonction printf() utilise, ici, deux paramètres.
Le premier une chaîne de caractères, le second un nom de variable.
Dans cette chaîne, figure un code : %d.
Ce code dit : placer le contenu de la variable ici, au format digit. (digit, en anglais, signifie chiffre)
Le contenu de la variable nombrEntier vaut 17.
Le nombre 17 est converti en chaîne de caractères et intégré au reste de la chaîne.

Dans la string, on place un (ou plusieurs) code pour indiquer où la valeur de la variable doit être affichée dans la string. Ce n'est pas exceptionnel, c'est une utilisation courante de la fonction printf(). Il est donc important de bien comprendre ce fonctionnement.

printf("%d + %d = %d\n", nombrEntier, nombrEntier2, nombrEntier+nombrEntier2);

Ici, le code %d est utilisé trois fois dans la chaîne de caractères.
Ici, la fonction printf() utilise 4 paramètres. Le premier paramètre (une string), suivi par 3 autres paramètres (deux noms de variable et une expression).

printf("\nLa variable 'lettreA' vaut : %c \n", lettreA);
Dans cette chaîne, figure un code %c
Ce code dit : placer le contenu de la variable ici, au format char.

printf("La variable 'lettreA' vaut : %d (en dEcimal)\n", lettreA);
Ici, on ne demande plus d'afficher le caractère au format char, mais au format digit !
Comme chaque caractère correspond à un code de la table ASCII, c'est ce code qui est affiché, au format digit. Il est important de comprendre qu'un nombre entier compris entre 0 et 255 peut s'afficher différemment : en caractère (%c), en chiffres (%d) et même en hexadécimal (%x)

Bien comprendre que le contenu d'une variable de type char est un octet (8 bits).

Ici, le contenu de la variable 'lettreA' vaut en mémoire : 0100 0001. Cette série de 8 bits peut être représentée, à l'écran, aussi en digits 65, en caractère ASCII A (et aussi en hexadécimal 41, voire même en octal 101)

Dans votre tête (en mémoire), c'est OK (d'accord). Mais comment allez-vous le dire ?
oui == yes == ja == sí == да == 是的 ... tout dépend de la langue utilisée.

Dans votre ordinateur (en mémoire), c'est 0100 0001. Mais comment le programme va l'afficher ?
65 == A == 41 == 101 ... tout dépend de la représentation (à l'écran) utilisée.

En général, pour représenter un octet, le programmeur choisit comme représentation le format décimal (en digits de base 10) ou le format char, soit %d ou %c

Il n'existe pas de %b pour obtenir une représentation binaire (en bits).
Pour afficher une représentation binaire, il faut créer une fonction telle que charToBits()

Bien comprendre ce qu'est un octet. Un octet est une série de 8 bits; et chaque bit peut être positionné à 0 ou 1. Maintenant, la façon de l'afficher à l'écran dépend de la "langue" utilisée par le programmeur.

Bien comprendre ce qu'est un fichier.

Un fichier est une série d'octets auquel on donne un nom. Aucun fichier ne contient de lettres, de chiffres, de notes de musique, de couleurs, d'instructions C, ...

Maintenant, la façon de les utiliser dépend du programme utilisé. Souvent, pour faciliter la reconnaissance d'un type de fichier (texte, image, musique, programme, ...), on ajoute au nom du fichier une extension (txt, .jpg, .mp3, .exe, ...).

Souvent un type de fichier a des sous-types.

Un fichier TEXTE peut avoir comme extension : .txt, .htm, .html, .css, .js, .php, .c (code source des programmes écrits en C), ... Tout fichier texte peut être ouvert par un éditeur de texte.

Un fichier qui n'est pas TEXTE est dit BINAIRE.

Un fichier [binaire] image peut avoir comme extension : .jpg, .gif, .png, ...

Un fichier [binaire] audio peut avoir comme extension : .mp3, .wav, .ogg, ...

Un fichier [binaire] video peut avoir comme extension : .mp4, .avi, .mpg, ...

Un fichier [binaire] exécutable peut avoir comme extension : .exe, .com, .dll, ...

Un fichier [binaire] texte (!) peut avoir comme extension : .pdf, .doc, .odt, ...

Mais quelque soit le type de fichier, binaire ou texte, un fichier est toujours une suite d'octets.. Si vous voulez voir le contenu (incompréhensible) d'un fichier binaire, voire le modifier (!), il faut installer un éditeur hexadécimal.

printf("La variable 'lettreA' vaut : %x (en hexadEcimal)\n", lettreA);
Ici, on demande d'afficher le caractère au hexadécimal !

Un même nombre entier peut être écrit de différentes manières.

Rappel : Chaque nombre entier peut être écrit au format décimal (= en base 10), hexadécimal (= en base 16), binaire (= en base 2), octal (= en base 8), ...

Le numéro de la base correspond au nombre de symboles (appelés aussi "chiffres") utilisés pour représenter un nombre.

Ainsi, en base 10 => dix symboles : 0123456789. Avec ces dix symboles, il est possible de représenter tout nombre entier.

Notez que si nous n'avions eu que 8 doigts, nous aurions malgré tout été capables de faire des additions. Et, seuls les "fous" auraient calculé en base 10 et utilisé les chiffres 8 et 9 ...

Comme nous avons dix doigts, les "fous", ce sont les autres ... Mais, en réalité, on peut représenter un nombre entier dans la base qu'on veut. En base 17, si vous le voulez ... Il suffit de trouver alors 17 symboles.

Si zéro = , un = , deux = ξ, ...
Alors, comment représenter notre 17 ?

En base 10, pour représenter le nombre 10, nous utilisons deux symboles (un suivi de zéro) soit 10. Dans cette base 17, pour représenter notre 17, nous utiliserons aussi deux symboles (un suivi de zéro) soit  ∴ℵ ! Avez-vous compris que notre 18 s'écrira alors ∴∴ ? Attention, à la migraine !

Bon retenez simplement qu'un même nombre peut être écrit de différentes manières, selon la base et les symboles utilisés dans cette base.

Retenez aussi que les ordinateurs n'ont pas dix doigts. Ils comptent en binaire. Ils n'utilisent que 2 positions électriques : OFF et ON, représentées par : (.) et (█). Pas trou et trou (cfr une carte perforée).

Donc, si zéro = (.) et un = (█). Alors, notre 2 s'écrira : (█.), notre 3 (██), notre 4 (█..), notre 5, (█.█), notre 6 (██.), notre 7 (███), notre 8 (█...), notre 9 (█..█), notre 10 (█.█.), ...

Toutefois, en informatique, les deux symboles sont réprésentés par : zéro = 0 et un = 1. Alors, pour lui, notre 2 s'écrira : 10; notre 3 => 11, notre 4 => 100, notre 5 => 101, notre 6 => 110, notre 7 => 111, notre 8 => 1000, notre 9 => 1001, notre 10 => 1010, ...

Et, comme un octet doit avoir 8 bits, on ajoute le nombre suffisant de zéro devant.
0 => 0000 0000, 1 => 0000 0001, 2 => 0000 0010, 3 => 0000 0011, 4 => 0000 0100, 5 => 0000 0101, 6 => 0000 0110, 7 => 0000 0111, 8 => 0000 1000, 9 => 0000 1001, 10 => 0000 1010, ... 255 =>1111 1111.

Un octet ne peut représenter qu'un nombre entier compris entre 0 et 255.

Après ce mini-cours sur le C, vous devez savoir ce qu'est un octet.

printf("La minuscule de 'A' est : %c\n", lettreA+32);
Rappel : Un char est un nombre entier entre 0 et 255. Ici, la variable lettreA vaut 65 (au format décimal).
Si on ajoute 32 à 65, on obtient 97; ce qui correspond au code ASCII de la lettre 'a'.

Puisqu'un char est un nombre (entre 0 et 255), on peut l'additionner.

char prenom[7] = "Thibaut";
Le prénom "Thibaut" contient bien 7 lettres, mais en mettant des guillemets, on dit : ceci est une chaîne de caractères. Or, en C, toute chaîne de caractères doit se terminer par un caractère spécial : NUL (une série de 8 bits à zéro). Le problème apparaît lors de l'affichage. "Thibaut" est bien affiché mais d'autres caractères peuvent suivre ce prénom.

  char prenom2[8] = "Thibaut";
  printf("La variable 'prenom2' vaut : %s\n", prenom2);

Ici, pas de problème à l'affichage, car lors de l'affectation de la variable prenom2 un NUL a été placé après le "t".

  prenom2[4]='\0';
  printf("La variable 'prenom2' vaut maintenant : %s\n", prenom2);
  printf("La septiEme case vaut toujours : '%c'\n", prenom2[6]);

Ici, on place le code ASCII du NUL (= nombre entier 0) dans la cinquième case du tableau prenom2. Puis, on demande d'afficher la string contenue dans ce tableau.

On constate aussi que le 't' est toujours là.

  double nombrReel = 12.99; // point décimal
  printf("\nLa variable 'nombrReel' vaut : %f\n", nombrReel);
  printf("La variable 'nombrReel' vaut : %.2f\n\n", nombrReel);

Dans cette chaîne, figure un code %f. Ce code dit : placer le contenu de la variable ici, au format float. Par défaut, le nombre de décimales est 6. Cependant, il est possible de préciser le nombre de décimales à afficher. Toutefois, le nombre de chiffres significatifs est limité.

Même si l'affichage d'un réel est limité à quelques décimales, en mémoire, la valeur de la variable demeure très précise.

On constate qu'en C, lorsqu'on calcule, les 15 premiers chiffres significatifs sont toujours bons. Ce qui est, en pratique, bien suffisant.

Relativiser l'importance des décimales

Considérons la vitesse de la lumière = 300 000 km/s

Considérons un rayon de 2 milliards d'années lumière
= 3 x 105 x 3600 x 24 x 365,25 x 2 x 109 km
= 3 x 105 x 36 x 102 x 24 x 365,25 x 2 x 109 km
= 3 x 36 x 24 x 365,25 x 2 x 1016 km
= 1 893 456 x 1016 km
= 1,893 456 x 1022 km

La circonférence d'un tel cercle est = 2 π R
= 3,786 912 x 1022 x π km
= 3,786 912 x 1025 x π m
= 3,786 912 x 1028 x π mm
= 3,786 912 x 1030 x π centièmes de millimètre

Une erreur à la 30ème décimale sur le nombre π impliquerait donc une erreur maximale de moins de 4 centièmes de millimètre. Donc, pour un cercle ayant un rayon égal à 2 milliards d'années lumière, l'erreur serait de +/- 2 centièmes de millimètre.

Pour rappel, nous ne sommes qu'à 8 minutes du soleil.
Et, non à 2 milliards d'années du soleil ...

Revenons sur Terre.

Considérons le rayon de la terre = 6 400 km

La circonférence d'un tel cercle est = 2 π R
= 12,8 x 103 x π km
= 12,8 x 106 x π m
= 12,8 x 109 x π mm
= 1,28 x 1010 x π millimètres

Une erreur à la 10ème décimale sur le nombre π impliquerait donc une erreur maximale de moins de 2 millimètres. Donc, pour un cercle ayant un rayon égal à celui de la terre, l'erreur serait de +/- 1 millimètre.

Affichage formaté

Vous connaissez signification des lettres - d, f, c, x, ... - dans une chaîne de caractères à afficher, lorsqu'elles sont préfixées par le caractère %.

Pour info, voici la syntaxe complète :

%signeLargeurPrécisionModificateurLettre

Ainsi, %02X = afficher le nombre entier au format (%), hexadécimal en majuscule (X), avec 2 caractères (02)

Et, %.2f = afficher un nombre réel au format (%), avec 2 chiffres après le point décimal.

Les caractères utilisant le 8ème bit

Plusieurs tables ASCII-étendu (utilisant le 8ème bit) existent.

La fonction printf() affiche correctement les caractères imprimables ASCII (7 bits). Mais, pour l'affichage des caractères utilisant le 8ème bit, catastrophe !

Le problème est que, lors de la compilation, le caractère est traduit en un nombre (entre 0 et 255) correspondant au code de ce caractère dans la table d'IBM (CP852). Mais, lors de l'affichage dans la console, Windows prend ce nombre regarde dans la table ASCII de Windows (CP1252, pour l'Europe occidentale) à quel caractère correspond ce nombre et l'affiche. Comme la position des caractères utilisant le 8ème bit diffère d'une table à l'autre, l'affiche ne correspond pas à ce qui a été écrit dans le code source.

IBM existait lors de l'invention du C, mais pas Microsoft ...

En C, il est possible d'afficher et d'enregistrer du texte français. Si on est persévérant ... En effet, pour afficher le C utilise la table ASCII-étendue CP-850 et pour enregistrer dans le fichier la table ASCII-étendue ANSI.

Les 32 caractères spéciaux de la langue française sont enregistrables (dans un fichier). Mais, seuls 29 peuvent être affichés (à l'écran). Les caractères œ, Ÿ et Œ ne peuvent pas être affichés (à l'écran).

é è ê ë à â î ï ô ù û ü ÿ æ œ ç
Afficher 130 138 136 137 133 131 140 139 147 151 150 129 152 145 --- 135
Enregistrer 233 232 234 235 224 226 238 239 244 249 251 252 255 230 156 231
printf("%c %c %c %c %c %c %c %c %c %c %c %c %c %c ? %c\n",130,138,136,137,133,131,140,139,147,151,150,129,152,145,135);
fprintf(fichier,"%c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n",233,232,234,235,224,226,238,239,244,249,251,252,255,230,156,231);

 

É È Ê Ë À Â Î Ï Ô Ù Û Ü Ÿ Æ Œ Ç
Afficher 144 212 210 211 183 182 215 216 226 235 234 154 --- 146 --- 128
Enregistrer 201 200 202 203 192 194 206 207 212 217 219 220 159 198 140 199
printf("%c %c %c %c %c %c %c %c %c %c %c %c ? %c ? %c\n\n",144,212,210,211,183,182,215,216,226,235,234,154,146,128);
fprintf(fichier,"%c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n\n",201,200,202,203,192,194,206,207,212,217,219,220,159,198,140,199);

 

Détails
___ TABLEAU DECIMAL ___

     0 1 2 3 4 5 6 7 8 9

  0    ☺ ☻ ♥ ♦ ♣ ♠
  1    ♂ ♀   ♫ ☼ ► ◄ ↕ ‼
  2  ¶ § ▬ ↨ ↑ ↓ → ← ∟ ↔
  3  ▲ ▼   ! " # $ % & '
  4  ( ) * + , - . / 0 1
  5  2 3 4 5 6 7 8 9 : ;
  6  < = > ? @ A B C D E
  7  F G H I J K L M N O
  8  P Q R S T U V W X Y
  9  Z [ \ ] ^ _ ` a b c
 10  d e f g h i j k l m
 11  n o p q r s t u v w
 12  x y z { | } ~ ⌂ Ç ü
 13  é â ä à å ç ê ë è ï
 14  î ì Ä Å É æ Æ ô ö ò
 15  û ù ÿ Ö Ü ø £ Ø × ƒ
 16  á í ó ú ñ Ñ ª º ¿ ®
 17  ¬ ½ ¼ ¡ « » ░ ▒ ▓ │
 18  ┤ Á Â À © ╣ ║ ╗ ╝ ¢
 19  ¥ ┐ └ ┴ ┬ ├ ─ ┼ ã Ã
 20  ╚ ╔ ╩ ╦ ╠ ═ ╬ ¤ ð Ð
 21  Ê Ë È ı Í Î Ï ┘ ┌ █
 22  ▄ ¦ Ì ▀ Ó ß Ô Ò õ Õ
 23  µ þ Þ Ú Û Ù ý Ý ¯ ´
 24  ­ ± ‗ ¾ ¶ § ÷ ¸ ° ¨
 25  · ¹ ³ ² ■

Affichage

#include <stdio.h>

int main()
{
  /* Affichage des 32 caractères spéciaux de la langue française, en C */

  // é è ê ë   à â î ï   ô ù û ü   ÿ æ ç ... œ
  printf("En franCais, les 16 minuscules 'spEciales' sont (caractEre = code) :\n");
  printf("%c = 130, %c = 138, %c = 136, %c = 137, ", 130,138,136,137);
  printf("%c = 133, %c = 131, %c = 140, %c = 139\n", 133,131,140,139);
  printf("%c = 147, %c = 151, %c = 150, %c = 129, ", 147,151,150,129);
  printf("%c = 133, %c = 145, %c = 135, ? = ?, \n\n", 152,145,135);

  printf("La ligature minuscule dans les mots : sOEur, vOEu, ... n'est pas affichable en C.\n");

  // À Â Ç É   È Ê Ë Î   Ï Ô Ü Æ   Ù Û ... Ÿ Œ
  printf("En franCais, les 16 majuscules 'spEciales' sont (caractEre = code) :\n");
  printf("%c = 183, %c = 182, %c = 128, %c = 144, ", 183,182,128,144);
  printf("%c = 212, %c = 210, %c = 211, %c = 215\n", 212,210,211,215);
  printf("%c = 216, %c = 226, %c = 154, %c = 146, ", 216,226,154,146);
  printf("%c = 235, %c = 234, ? = ?, ? = ?\n\n",235,234);

  printf("La majuscule des lettres %c et OE ne sont pas affichables en C.\n",133);
  printf("=> 29 lettres spéciales peuvent être affichEes en C");

  printf("Les 32 lettres spEciales sont enregistrables en C.\n\n");

  printf("Les codes sont enregistrEs dans le fichier 'accents.txt'\n");
  printf(" situEs dans le dossier de cet EXE.\n\n");

  FILE *fichier;
  fichier=fopen("accents.txt","w");

  /* Enregistrement des 32 caractères spéciaux de la langue française, en C */

  // é è ê ë   à â î ï   ô ù û ü   ÿ æ ç œ
  fprintf(fichier,"En franCais, les 16 minuscules 'spEciales' sont (caractEre = code) :\n\n");
  fprintf(fichier,"%c = 233, %c = 232, %c = 234, %c = 235, ", 233,232,234,235);
  fprintf(fichier,"%c = 224, %c = 226, %c = 238, %c = 239\n", 224,226,238,239);
  fprintf(fichier,"%c = 244, %c = 249, %c = 251, %c = 252, ", 244,249,251,252);
  fprintf(fichier,"%c = 255, %c = 230, %c = 231, %c = 156\n\n", 255,230,231,156);
  // NB : œ ne peut pas être affiché, mais il peut être enregistré

  // À Â Ç É   È Ê Ë Î   Ï Ô Ü Æ   Ù Û Ÿ Œ
  fprintf(fichier,"En franCais, les 16 majuscules 'spEciales' sont (caractEre = code) :\n\n");
  fprintf(fichier,"%c = 192, %c = 194, %c = 199, %c = 201, ", 192,194,199,201);
  fprintf(fichier,"%c = 200, %c = 202, %c = 203, %c = 206\n", 200,202,203,206);
  fprintf(fichier,"%c = 207, %c = 212, %c = 220, %c = 198, ", 207,212,220,198);
  fprintf(fichier,"%c = 217, %c = 219, %c = 159, %c = 140\n\n",217,219,159,140);

  fclose(fichier);
  printf(">>> accents.txt cr%c%c.\n\n",130,130);

  // Code source ci-dessous :
  // https://openclassrooms.com/forum/sujet/ascii-et-langage-c-46448
  int i, j, k = 0;

  puts("\n _______ TABLEAU HEXADECIMAL ______");
  puts("\n    0 1 2 3 4 5 6 7 8 9 A B C D E F");
  for(i = 0; i < 16; i++) {
    printf("\n %X  ", i);
    for(j = 0; j < 16; j++, k++)
      printf("%c ", k != 7 && k != 8 && k != 9 && k != 10 && k != 13 && k < 256 ? k : ' ');
  }

  puts("\n __________________________________");

  return 0;
}

Enregistrement

#include <stdio.h>

int main()
{
    FILE *fichier;
    fichier=fopen("accents.txt","w");

  /* Enregistrement des 32 caractères spéciaux de la langue française, en C */

  // é è ê ë   à â î ï   ô ù û ü   ÿ æ ç œ
  fprintf(fichier,"En franCais, les 16 minuscules 'spEciales' sont (caractEre = code) :\n\n");
  fprintf(fichier,"%c = 233, %c = 232, %c = 234, %c = 235, ", 233,232,234,235);
  fprintf(fichier,"%c = 224, %c = 226, %c = 238, %c = 239\n", 224,226,238,239);
  fprintf(fichier,"%c = 244, %c = 249, %c = 251, %c = 252, ", 244,249,251,252);
  fprintf(fichier,"%c = 255, %c = 230, %c = 231, %c = 156\n\n", 255,230,231,156);
  // NB : œ ne peut pas être affiché, mais il peut être enregistré

  // À Â Ç É   È Ê Ë Î   Ï Ô Ü Æ   Ù Û Ÿ Œ
  fprintf(fichier,"En franCais, les 16 majuscules 'spEciales' sont (caractEre = code) :\n\n");
  fprintf(fichier,"%c = 192, %c = 194, %c = 199, %c = 201, ", 192,194,199,201);
  fprintf(fichier,"%c = 200, %c = 202, %c = 203, %c = 206\n", 200,202,203,206);
  fprintf(fichier,"%c = 207, %c = 212, %c = 220, %c = 198, ", 207,212,220,198);
  fprintf(fichier,"%c = 217, %c = 219, %c = 159, %c = 140\n\n",217,219,159,140);

  fclose(fichier);
  printf("accents.txt cr%c%c.",130,130);

  return 0;
}

Table ASCII-étendu : ANSI (PDF)

Les 84 caractères de l'alphabet français

Obtenir des données

Ne faites jamais confiance à un utilisateur !

Si vous lui demandez son âge, il peut vous répondre n'importe quoi ! 123456789, bonjour, ... Comment réagira votre programme ?

Toutefois, ici, pour alléger le code, on suppose que votre utilisateur est gentil.

scanf()

La fonction scanf() permet de récolter un entier, un réel, un caractère.

scanf("%d",&nombrEntier);

Le code %d permet de récupérer des digits.
Le code %f permet de récupérer un float.
Le code %c permet de récupérer un char.

Ce qui est récupéré est mis à l'adresse-mémoire indiquée. Cette variable doit être du même type que ce qui est récupéré.

L'adresse d'une variable est obtenu en préfixant le nom de cette variable par (&).

La fonction scanf() permet, aussi, de récolter une string.

Toutefois, une string n'est pas un type. La variable contient l'adresse (en mémoire) du tableau de caractères => pas de & comme préfixe

scanf("%s", phrase);

Notez que scanf() s'arrête dès qu'il rencontre le caractère ayant le code ASCII : 32 (espace), 10 (new line,'\n') ou EOF. En pratique, scanf("%s",mot) n'est utilisé que pour obtenir que des mots (et non une phrase composée de mots et d'espaces).

EOF n'est pas un caractère.

Il est vivement recommandé de vider la mémoire-clavier après chaque frappe sur la touche 'Enter' via l'instruction fflush(stdin);

fgets()

to get = obtenir

Les fonction gets() et fgets() vous permettront de récolter une ligne (mots séparés par des espaces) de la part de l'utilisateur. Cependant, fgets() offre un meilleur contrôle, car elle permet de fixer le nombre de caractères (et, en troisième paramètre, l'origine du flux d'octets).

fgets() retourne également le caractère final NUL.

Toutes deux attendent que l'utilisateur tape sur la touche 'Enter' et envoie ce qui a été tapé (avant la frappe sur la touche 'Enter') dans la variable qui est son premier paramètre.

#include <stdio.h>

#define MAX 10

int main()
{
  char nom[MAX];

  printf("Tapez plus de %d caractEres : ",MAX);
  fgets(nom,MAX,stdin);
  printf("Votre nom est : %s\n", nom);

  printf("Tapez plus de %d caractEres : ",MAX);
  gets(nom);
  printf("Votre nom est : %s\n", nom);
}

Notez qu'ici MAX est une constante qui est DEFINEe juste en dessous des INCLUDE

getchar()

Lorsque le programme est lancé dans son IDE (via la touche F9, avec CodeBlocks), il ajoute :

Ce qui permet au développeur de voir le résultat.

Toutefois, s'il lance l'exécutable en double-cliquant sur son nom dans le dossier monProjet/bin/Debug la console s'ouvre, le programme se lance, puis se ferme ainsi que la console tellement vite qu'on ne voit rien !

Il faut alors taper un code semblable à :

  printf("Pour quitter le programme, appuyez sur la touche 'Enter'.");
  gets(nom);

Ou, à cela :

  printf("\nPour quitter le programme, appuyez sur la touche 'Enter'.");
  char fin = getchar();

La fonction getchar(), comme son nom l'indique, attend que l'utilisateur tape sur la touche 'Enter' et envoie le (premier) caractère tapé (avant la frappe sur la touche 'Enter') dans une variable.

Les entêtes

Un fichier d'entête - appelé header - contient les définitions des fonctions C pré-définies (tout faites).

Liste des headers et de leurs fonctions

stdio.h

L'entête la plus connue est stdio.h. Ce qui est donné au programme - par exemple, via le clavier - s'appelle un input; Ce qui est donné par le programme - par exemple, via un écran - , un output. stdio signifie donc standard for inputs and outputs. Bref, elle permet la communication avec le programme. Elle est donc présente dans tout programme utilisant une console. Parmi les fonctions, citons : printf(), gets(), getchar(), fflush(), ...

string.h

L'entête string.h est aussi très courante. Elle contient la définition de toutes les fonctions C pré-définies relatives aux string (chaînes de caractères) : strlen(), strcat(), strcpy(), strcmp(), ...

if(!strcmp(variable,"abc")){...}
// strcmp() retourne 0 si les deux chaînes sont strictement identiques
// Dans une condition, 0 signifie false => !0 signifie true

ctype.h

L'entête ctype.h est aussi très courante. Elle contient la définition de toutes les fonctions C pré-définies telles que  : isdigit(), isalpha(), isalnum(), tolower(), toupper(), ...

math.h

L'entête math.h est très courante. Elle contient la définition de toutes les fonctions C pré-définies relatives aux fonctions mathématiques : pow(), sqrt(), exp(), log10(), log(), ceil(), floor(), fabs(), sin(), cos(), tan()

stdlib.h

L'entête stdlib.h est très courante. Elle contient la définition de toutes les fonctions C pré-définies tel que  : atoi(), atol(), abs(), system(), ...

Modèles

Modèle sans menu

Code modèle (sans menu) :

#include <stdio.h>
//#include <ctype.h>
//#include <string.h>
//#include <stdlib.h>
//#include <math.h>

int main(){

  char continuer='Y';

  do{ // début de la grande boucle

    system("cls"); // efface l'écran, sous Windows
    //system("clear"); // sous Linux

    //------------------ coeur du programme --------------------






    //--------------- fin du coeur du programme -----------------

    printf("\n****************************\n");
    printf("\nSouhaitez-vous continuer ? (Y/n) : ");
    continuer=getchar();
    fflush(stdin);

  } while(continuer!='n');

  return 0;
}

Exemple :

#include <stdio.h>
//#include <ctype.h>
//#include <string.h>
//#include <stdlib.h>
//#include <math.h>

void charToBits(int value, char bits[9])
{
  int mask = 0x01;
  for(unsigned i = 0; i < 8; ++i)
  {
    bits[7-i] = (value & mask) != 0 ? '1' : '0';
    value>>=1;
  }
  bits[8] = '\0';
}

int main(){

  char continuer='Y';

  do{ // début de la grande boucle

    system("cls"); // efface l'écran, sous Windows
    //system("clear"); // sous Linux

    //------------------ coeur du programme --------------------

    char bits[9];
    int nombrEntier=0;

    printf("Tapez un nombre entier entre 0 et 255,\n");
    printf("pour afficher sa reprEsentation binaire : ");

    scanf("%d",&nombrEntier);
    fflush(stdin);

    charToBits(nombrEntier,bits);

    printf("\n%d => %s\n", nombrEntier,bits);

    //--------------- fin du coeur du programme -----------------
    printf("\n****************************\n");
    printf("\nSouhaitez-vous continuer ? (Y/n) : ");
    continuer=getchar();
    fflush(stdin);

  } while(continuer!='n');

  return 0;
}

Modèle avec menu

Un programme peut avoir plusieurs fonctionnalités. Pour permettre à l'utilisateur de choisir parmi celles-ci, créons un menu.

Modèle général

#include <stdio.h>
//#include <ctype.h>
//#include <string.h>
//#include <stdlib.h>
//#include <math.h>

void ecrire(){
  printf("Bienvenu dans la fonction ecrire()");
}

void ajouter(){
  printf("Bienvenu dans la fonction ajouter()");
}

void lire(){
  printf("Bienvenu dans la fonction lire()");
}

void crypter(){
  printf("Bienvenu dans la fonction crypter()");
}

int main(){ // Point d'entrée du programme

  char continuer='Y';

  do{ // début de la grande boucle

    char choix=0;

    do{ // boucle permettant de choisir dans le menu

      system("cls"); // efface l'écran, sous Windows
      //system("clear"); // sous Linux

      printf("1 = Ecrire un fichier\n");
      printf("2 = Ajouter A la fin du fichier\n");
      printf("3 = Lire un fichier\n");
      printf("4 = Crypter / DEcrypter un fichier\n");
      printf("0 = Quitter ce menu\n");
      printf("----------------------------------\n");
      printf("Votre choix : "); choix=getchar(); fflush(stdin);

    } while(choix<48 || choix>52); // rappel '0' vaut 48

    //------------------ coeur du programme --------------------

    system("cls"); // efface l'écran, sous Windows
    //system("clear"); // sous Linux

    switch(choix){
      case '1': ecrire(); break;
      case '2': ajouter(); break;
      case '3': lire(); break;
      case '4': crypter(); break; // = décrypter aussi
    }

    //--------------- fin du coeur du programme -----------------

    printf("\n****************************\n");
    printf("\nSouhaitez-vous continuer ? (Y/n) : ");
    continuer=getchar();
    fflush(stdin);

  } while(continuer!='n');

  return 0;
}