LANGAGE C
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-1-
CHAPITRE 1
ELEMENTS DE LANGAGE C
Le corrigé des exercices et le listing de ces programmes se trouvent à la fin de chaque
chapitre.
INTRODUCTION
Le langage C est un langage évolué et structuré, assez proche du langage machine destiné à des
applications de contrôle de processus (gestion d’entrées/sorties, applications temps réel ...). Les
compilateurs C possèdent les taux d’expansion les plus faibles de tous les langages évolués (rapport
entre la quantité de codes machine générée par le compilateur et la quantité de codes machine
générée par l’assembleur et ce pour une même application);
Le langage C possède assez peu d’instructions, il fait par contre appel à des bibliothèques, fournies
en plus ou moins grand nombre avec le compilateur.
exemples: math.h : bibliothèque de fonctions mathématiques
stdio.h : bibliothèque d’entrées/sorties standard
On ne saurait développer un programme en C sans se munir de la documentation concernant
ces bibliothèques.
Les compilateurs C sont remplacés petit à petit par des compilateurs C++.
Un programme écrit en C est en principe compris par un compilateur C++.
Le cours qui suit est un cours ce langage C écrit dans un contexte C++.
ETAPES PERMETTANT L'EDITION, LA MISE AU POINT,
L'EXECUTION D'UN PROGRAMME
1- Edition du programme source, à l’aide d’un éditeur (traitement de textes). Le nom du fichier
contient l’extension .CPP, exemple: EXI_1.CPP (menu « edit »).
2- Compilation du programme source, c’est à dire création des codes machine destinés au
microprocesseur utilisé. Le compilateur indique les erreurs de syntaxe mais ignore les fonctionsbiblioth
èque appelées par le programme.
Le compilateur génère un fichier binaire, non listable, appelé fichier objet: EXI_1.OBJ (commande
« compile »).
3- Editions de liens: Le code machine des fonctions-bibliothèque est chargé, création d’un fichier
binaire, non listable, appelé fichier executable: EXI_1.EXE (commande « build all »).
4- Exécution du programme (commande « flèche jaune »).
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-2-
Les compilateurs permettent en général de construire des programmes composés de plusieurs
fichiers sources, d’ajouter à un programme des unités déjà compilées ...
Exercice I-1:
Editer (EXI_1.CPP), compiler et exécuter le programme suivant:
#include <stdio.h> /* bibliotheque d'entrees-sorties standard */
#include <conio.h>
void main()
{
puts("BONJOUR"); /* utilisation d'une fonction-bibliotheque */
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
Le langage C distingue les minuscules, des majuscules. Les mots réservés du langage C doivent être
écrits en minuscules.
On a introduit dans ce programme la notion dinterface homme/machine (IHM).
- Lutilisateur visualise une information sur lécran,
- Lutilisateur, par une action sur le clavier, fournit une information au programme.
Modifier le programme comme ci-dessous, puis le tester :
#include <stdio.h> /* bibliotheque d'entrees-sorties standard */
#include <conio.h>
void main()
{
int a, b, somme ; /* déclaration de 3 variables */
puts("BONJOUR"); /* utilisation d'une fonction-bibliotheque */
a = 10 ; /* affectation* /
b = 50 ; /* affectation */
somme = (a + b)*2 ; /* affectation et opérateurs */
printf(« Voici le resultat : %d\n », somme) ;
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
Dans ce programme, on introduit 3 nouveaux concepts :
- La notion de déclaration de variables : les variables sont les données que manipulera le
programme lors de son exécution. Ces variables sont rangées dans la mémoire vive de
lordinateur. Elle doivent être déclarées au début du programme.
- La notion daffectation, symbolisée par le signe =.
- La notion dopération
LES DIFFERENTS TYPES DE VARIABLES
1- Les entiers
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-3-
Le langage C distingue plusieurs types d’entiers:
___________________________________________________________
TYPE DESCRIPTION TAILLE MEMOIRE
___________________________________________________________
int entier standard signé 4 octets: - 231 ≤ n ≤231-1
unsigned int entier positif 4 octets: 0 ≤ n ≤ 232
short entier court signé 2 octets: - 215 ≤ n ≤ 215-1
unsigned short entier court non signé 2 octets: 0 ≤≤n ≤ 216
char caractère signé 1 octet : - 27 ≤≤n ≤ 27-1
unsigned char caractère non signé 1 octet : 0 ≤n ≤ 28
_____________________________________________________________
Numération: En décimal les nombres s’écrivent tels que, précédés de 0x en hexadécimal.
exemple: 127 en décimal s’écrit 0x7f en hexadécimal.
Remarque: En langage C, le type char est un cas particulier du type entier:
un caractère est un entier de 8 bits
Exemples:
Les caractères alphanumériques s’écrivent entre
Le caractère ’b’ a pour valeur 98 (son code ASCII).
Le caractère 22 a pour valeur 22.
Le caractère 127 a pour valeur 127.
Le caractère 257 a pour valeur 1 (ce nombre s’écrit sur 9 bits, le bit de poids fort est perdu).
Quelques constantes caractères:
________________________________________________________________
CARACTERE VALEUR (code ASCII) NOM ASCII
________________________________________________________________
’\n’ interligne 0x0a LF
’\t’ tabulation horizontale 0x09 HT
’\v’ tabulation verticale 0x0b VT
’\r’ retour charriot 0x0d CR
’\f’ saut de page 0x0c FF
’\\’ backslash 0x5c \
’\’’ cote 0x2c ’
’\"’ guillemets 0x22 "
_______________________________________________________________
Modifier ainsi le programme et le tester :
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-4-
#include <stdio.h> /* bibliotheque d'entrees-sorties standard */
#include <conio.h>
void main()
{
int a, b, calcul ; /* déclaration de 3 variables */
char u, v;
puts("BONJOUR"); /* utilisation d'une fonction-bibliotheque */
a = 10 ; /* affectation* /
b = 50 ; /* affectation */
u = 65 ;
v = ‘A’ ;
calcul = (a + b)*2 ; /* affectation et opérateurs */
printf(« Voici le resultat : %d\n », calcul) ;
printf(« 1er affichage de u : %d\n »,u) ;
printf(« 2ème affichage de v : %c\n »,u) ;
printf(« 1er affichage de u: %d\n »,v) ;
printf(« 2éme affichage de v: %c\n »,v) ;
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
2- Les réels
Un réel est composé - d’un signe - d’une mantisse - d’un exposant
Un nombre de bits est réservé en mémoire pour chaque élément.
Le langage C distingue 2 types de réels:
_________________________________________________________
TYPE DESCRIPTION TAILLE MEMOIRE
_________________________________________________________
float réel standard 4 octets
double réel double précision 8 octets
__________________________________________________________
LES INITIALISATIONS
Le langage C permet l’initialisation des variables dans la zône des déclarations:
char c; est équivalent à char c = ’A’;
c = ’A’;
int i; est équivalent à int i = 50;
i = 50;
Cette règle s’applique à tous les nombres, char, int, float ...
SORTIES DE NOMBRES OU DE TEXTE A L'ECRAN
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-5-
LA FONCTION PRINTF
Ce n’est pas une instruction du langage C, mais une fonction de la bibliothèque stdio.h.
Exemple: affichage d'un texte:
printf("BONJOUR"); /* pas de retour à la ligne du curseur apres l’affichage, */
printf("BONJOUR\n"); /* affichage du texte, puis retour à la ligne du curseur. */
Exercice I-2: Tester le programme suivant et conclure.
#include <stdio.h>
#include <conio.h>
void main()
{
printf("BONJOUR ");
printf("IL FAIT BEAU\n"); /* equivalent à puts("BONJOUR"; */
printf("BONNES VACANCES");
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
La fonction printf exige l'utilisation de formats de sortie, avec la structure suivante:
printf("%format",nom_de_variable);
Exercice I-3: Affichage d’une variable de type char:
Tester le programe suivant et conclure.
Dans un deuxième temps, le modifier ce programme pour améliorer linterface utilisateur.
#include <stdio.h>
#include <conio.h>
void main()
{
char c;
c =66; /* c est le caractere alphanumerique A */
printf("%d\n",c); /* affichage du code ASCII en decimal */
/* et retour … à la ligne */
printf("%o\n",c); /* affichage du code ASCII en base huit
/* et retour … à la ligne */
printf("%x\n",c); /* affichage du code ASCII en hexadecimal
/* et retour … à la ligne */
printf("%c\n",c); /* affichage du caractère */
/* et retour à la ligne */
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-6-
}
Exercice I-4: Affichage multiple de structure:
printf("format1 format2 .... formatn",variable1,variable2, .......,variablen);
Tester le programe suivant et conclure:
#include <stdio.h>
#include <conio.h>
void main()
{
char c;
c ='A';/* c est le caractere alphanumerique A */
printf("decimal = %d ASCII = %c\n",c,c);
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
Formats de sortie pour les entiers:
%d affichage en décimal (entiers de type int),
%x affichage en hexadécimal (entiers de type int),
%u affichage en décimal (entiers de type unsigned int),
D’autres formats existent, consulter une documentation constructeur.
Exercice I-5:
a et b sont des entiers, a = -21430 b = 4782, calculer et afficher a+b, a-b, a*b, a/b, a%b en
format décimal, et en soignant linterface homme/machine.
a/b donne le quotient de la division, a%b donne le reste de la division.
Exercice I-6:
Que va-t-il se produire, à l’affichage, lors de l’exécution du programme suivant ?
#include <stdio.h> /* ex I_6 */
#include <conio.h>
void main()
{
char a = 0x80;
unsigned char b = 0x80;
clrscr();
printf("a en decimal vaut: %d\n",a);
printf("b en decimal vaut: %d\n",b);
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-7-
}
Exercice I-7:
En C standard, la taille des entiers est de 32 bits;
Que va-t-il se passer, à l'affichage, lors de l'exécution du programme suivant ?
#include <stdio.h> /* ex I_7.C */
#include <conio.h>
void main()
{
int a = 12345000, b = 60000000, somme;
somme=a*b;
printf("a*b = %d\n",somme);
printf("a*b (en hexa) = %x\n",somme);
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
Format de sortie pour les réels: %f
Exercice I-8:
a et b sont des réels, a = -21,43 b = 4,782, calculer et afficher a+b, a-b, a*b, a/b, en soignant
linterface homme/machine.
AUTRES FONCTIONS DE SORTIES
Affichage d’un caractère: La fonction putchar permet d’afficher un caractère:
c étant une variable de type char, l’écriture putchar(c); est équivalente à printf("%c\n",c);
Affichage d’un texte: La fonction puts permet d’afficher un texte:
l’écriture puts("bonjour"); est équivalente à printf("bonjour\n");
Il vaut mieux utiliser puts et putchar si cela est possible, ces fonctions, non formatées, sont
d’exécution plus rapide, et nécessitent moins de place en mémoire lors de leur chargement.
LES OPERATEURS
Opérateurs arithmétiques sur les réels: + - * / avec la hiérarchie habituelle.
Opérateurs arithmétiques sur les entiers: + - * / (quotient de la division) % (reste de la division)
avec la hiérarchie habituelle.
Exemple particulier: char c,d;
c = ’G’;
d = c+’a’-’A’;
Les caractères sont des entiers sur 8 bits, on peut donc effectuer des opérations. Sur cet exemple, on
transforme la lettre majuscule G en la lettre minuscule g.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-8-
Opérateurs logiques sur les entiers:
& ET | OU ^ OU EXCLUSIF ~ COMPLEMENT A UN « DECALAGE A GAUCHE
» DECALAGE A DROITE.
Exemples: p = n « 3; /* p est égale à n décalé de 3 bits à gauche */
p = n » 3; /* p est égale à n décalé de 3 bits à droite */
L’opérateur sizeof(type) renvoie le nombre d’octets réservés en mémoire pour chaque type d’objet.
Exemple: n = sizeof(char); /* n vaut 1 */
Exercice I-9: n est un entier (n = 0x1234567a), p est un entier (p = 4). Ecrire un programme qui met
à 0 les p bits de poids faibles de n.
Exercice I-10: Quels nombres va renvoyer le programme suivant ?
#include <stdio.h>
#include <conio.h>
void main()
{
printf("TAILLE D'UN CARACTERE:%d\n",sizeof(char));
printf("TAILLE D'UN ENTIER:%d\n",sizeof(int));
printf("TAILLE D'UN REEL:%d\n",sizeof(float));
printf("TAILLE D'UN DOUBLE:%d\n",sizeof(double));
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
INCREMENTATION - DECREMENTATION
Le langage C autorise des écritures simplifiées pour l’incrémentation et la décrémentation de
variables:
i = i+1; est équivalent à i++;
i = i-1; est équivalent à i--;
OPERATEURS COMBINES
Le langage C autorise des écritures simplifiées lorsqu’une même variable est utilisée de chaque côté
du signe = d’une affectation. Ces écritures sont à éviter lorsque l’on débute l’étude du langage C car
elles nuisent à la lisibilité du programme.
a = a+b; est équivalent à a+= b;
a = a-b; est équivalent à a-= b;
a = a & b; est équivalent à a&= b;
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-9-
LES DECLARATIONS DE CONSTANTES
Le langage C autorise 2 méthodes pour définir des constantes.
1ere méthode: déclaration d’une variable, dont la valeur sera constante pour tout le programme:
Exemple: void main()
{
const float PI = 3.14159;
float perimetre,rayon = 8.7;
perimetre = 2*rayon*PI;
....
}
Dans ce cas, le compilateur réserve de la place en mémoire (ici 4 octets), pour la variable pi, mais
dont on ne peut changer la valeur.
2eme méthode: définition d'un symbole à l’aide de la directive de compilation #define.
Exemple: #define PI = 3.14159;
void main()
{f
loat perimetre,rayon = 8.7;
perimetre = 2*rayon*PI;
....
}
Le compilateur ne réserve pas de place en mémoire. Les constantes déclarées par #define s’écrivent
traditionnellement en majuscules, mais ce n’est pas une obligation.
LES CONVERSIONS DE TYPES
Le langage C permet d’effectuer des opérations de conversion de type: On utilise pour cela
l’opérateur de "cast" ().
Exemple et exercice I-11:
#include <stdio.h>
#include <conio.h>
void main()
{
int i=0x1234,j;
char d,e;
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-10-
float r=89.67,s;
j = (int)r;
s = (float)i;
d = (char)i;
e = (char)r;
printf("Conversion float -> int: %5.2f -> %d\n",r,j);
printf("Conversion int -> float: %d -> %5.2f\n",i,s);
printf("Conversion int -> char: %x -> %x\n",i,d);
printf("Conversion float -> char: %5.2f -> %d\n",r,e);
printf("Pour sortir frapper une touche ");getch();
}
CORRIGE DES EXERCICES
Exercice I-5:
#include <stdio.h>
#include <conio.h>
void main()
{
int a,b;
a= -21430;
b= 4782;
printf("A + B = %d\n",a+b);
printf("A - B = %d\n",a-b);
printf("A x B = %d\n",a*b);
printf("A sur B = %d\n",a/b);
printf("A mod B = %d\n",a%b);
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
Exercice I-6:
a en décimal vaut -128 b en décimal vaut 128
Rques:
En C, le type char désigne un entier codé sur 8 bits.
-128 <= char <=+127 0<= unsigned char <= 255
Exercice I-8:
#include <stdio.h> /* EXI_8*/
#include <conio.h>
void main()
{f
loat a,b;
a= -21.43;
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-11-
b= 4.782;
printf("A + B = %f\n",a+b);
printf("A - B = %f\n",a-b);
printf("A x B = %f\n",a*b);
printf("A sur B = %f\n",a/b);
puts("Pour continuer frapper une touche...");
getch(); /* Attente d'une saisie clavier */
}
Exercice I-9:
#include <stdio.h>
#include <conio.h>
main()
{
int n,p,masque;
clrscr();
n = 45;
p = 4;
printf("valeur de n avant modification:%x\n",n);
masque = ~0; /* que des 1 */
masque = masque « p;
n = n & masque;
printf("n modifié vaut:%x\n",n);
}
Exercice I-10:
En C standard: sizeof(char) vaut 1 sizeof(int) vaut 4 sizeof(float) vaut 4 sizeof(double) vaut 8.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-12-
CHAPITRE 2
SAISIE DE NOMBRES ET DE CARACTERES AU CLAVIER
LA FONCTION GETCH
La fonction getch, appartenant à la bibliothèque conio.h permet la saisie clavier d’ un caractère
alphanumérique, sans écho écran. La saisie s’arrête dès que le caractère a été frappé.
La fonction getch n'est pas définie dans la norme ANSI mais elle peut exister dans la
bibliothèque d’autres compilateurs.
On peut utiliser getch de deux façons:
- sans retour de variable au programme:
Exemple: printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
- avec retour de variable au programme:
Exemple: char alpha;
printf("ENTRER UN CARACTERE (ATTENTION PAS DE RETURN) ");
alpha = getch();
printf("\nVOICI CE CARACTERE: %c",alpha);
Les parenthèses vides de getch() signifient qu'aucun paramètre n'est passé à cette fonction par
le programme.
LA FONCTION SCANF
La fonction scanf, appartenant à la bibliothèque stdio.h, permet la saisie clavier de n’importe quel
type de variable.
Les variables à saisir sont formatées, le nom de la variable est précédé du symbole & désignant
l’adresse de la variable (On reverra ce symbole dans le chapitre sur les pointeurs).
La saisie s’arrête avec "RETURN" (c’est à dire LF), les éléments saisis s’affichent à l’écran (saisie
avec écho écran).
Tous les éléments saisis après un caractère d'espacement (espace, tabulation) sont ignorés.
Exemples: char alpha;
int i;
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-13-
float r;
scanf("%c",&alpha); /* saisie d’un caractère */
scanf("%d",&i); /* saisie d’un nombre entier en décimal */
scanf("%x",&i); /* saisie d’un nombre entier en hexadécimal*/
scanf("%f",&r); /* saisie d’un nombre réel */
Remarque: Si l’utilisateur ne respecte pas le format indiqué dans scanf, la saisie est ignorée. Aucune
erreur n’est générée.
Exemple: char alpha;
scanf("%d",&alpha);
Si l’utilisateur saisie 97 tout va bien, alpha devient le caractère dont le code ASCII vaut 97.
Si l’utilisateur saisie a, sa saisie est ignorée.
Exercice II_1:
Saisir un caractère au clavier, afficher son code ASCII à l’écran. Soigner l’affichage.
Exercice II_2: Saisir un nombre entier en décimal au clavier, l’afficher en hexadécimal à l’écran.
Soigner l’affichage.
Exercice II_3:
Que va-t-il se passer lors de l’exécution du programme suivant, si l’utilisateur saisit 67?
#include <stdio.h>
#include <conio.h>
void main()
{
char c;
printf("ENTRER UN CARACTERE: ");
scanf("%c",&c);
printf("VOICI SON CODE ASCII: %d\n",c);
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
NOTION DE FLUX D'ENTREE
Lorsque l’on saisit au clavier une suite de caractères terminés par "RETURN" ces caractères sont
rangés dans un tampon (ou buffer) de type FIFO (First In/First Out), le dernier caractère rangé dans
le tampon est LF (code ASCII 0x0A).
Cette suite de caractères est appelée flux d'entrée.
La taille du tampon dépend de la machine et du compilateur utilisés. Sur un PC et en TURBOC, la
taille du tampon est de 127 caractères.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-14-
Une compilation du programme vide le tampon.
LA FONCTION SCANF
DEUXIEME APPROCHE
La fonction scanf ne se comporte pas tout à fait comme décrit plus haut. Si le tampon est vide, tout
se passe comme précédemment décrit.
Au contraire, si le tampon n’est pas vide, la fonction scanf en teste le premier élément, s’il
correspond au format de la variable invoquée, le tampon perd cet élément et la variable en prend la
valeur.
Tout caractère ou nombre saisi au clavier et non pris en compte par la fonction scanf est
rangé dans le tampon.
Exemple et Exercice II-4:
#include <stdio.h>
#include <conio.h>
void main()
{
char c1,c2;
printf("ENTRER UN CARACTERE: ");
scanf("%c",&c1);
printf("VOICI SON CODE ASCII EN HEXADECIMAL: %x\n",c1);
printf("ENTRER UN AUTRE CARACTERE: ");
scanf("%c",&c2);
printf("VOICI SON CODE ASCII EN HEXADECIMAL: %x\n",c2);
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Si l’utilisateur saisit K pour c1, le programme donnera l’écran d’exécution suivant:
ENTRER UN CARACTERE: K
VOICI SON CODE ASCII EN HEXADECIMAL: 4b
ENTRER UN AUTRE CARACTERE: VOICI SON CODE ASCII EN HEXADECIMAL: a
Lors de la saisie de K, le caractere LF est rangé dans le tampon. Lors du deuxième appel à scanf, le
tampon n’est pas vide, l’utilisateur ne peut effectuer sa saisie clavier, le code ascii de LF est affiché à
l’écran.
A l’issue de l’exécution, le tampon est vide.
Exercice II_5: Le programme suivant s’exécute-t-il "correctement" ? Que contient le tampon à
l’issue de l’exécution ?
#include <stdio.h>
#include <conio.h>
void main()
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-15-
{
char c;
int i;
printf("ENTRER UN CARACTERE: ");
scanf("%c",&c);
printf("VOICI SON CODE ASCII EN HEXADECIMAL: %x\n",c);
printf("ENTRER UN NOMBRE: ");
scanf("%d",&i);
printf("VOICI CE NOMBRE EN HEXADECIMAL: %x\n",i);
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice II_6: Le programme suivant s’exécute-t-il "correctement" ? Que contient le tampon à
l’issue de l’exécution ?
#include <stdio.h>
#include <conio.h>
void main()
{
char c;
int i;
printf("ENTRER UN NOMBRE: ");
scanf("%d",&i);
printf("VOICI CE NOMBRE EN HEXADECIMAL: %x\n",i);
printf("ENTRER UN CARACTERE: ");
scanf("%c",&c);
printf("VOICI SON CODE ASCII EN HEXADECIMAL: %x\n",c);
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice II_7: Dans l’exercice II_4 que se passe-t-il si, lors de la première saisie, l’utilisateur tape 67
?
Remarque: En TURBOC la fonction flushall() permet de vider le tampon d’entrée. En l’invoquant
après un appel à scanf, on se débarrasse des problèmes de flux d’entrée.
LA FONCTION GETCHAR
La fonction getchar pemet la saisie d’un caractère (char). Elle appartient à la bibliothèque stdio.h.
Les 2 écritures suivantes sont équivalentes:
char c; char c;
printf("ENTRER UN CARACTERE: "); printf("ENTRER UN CARACTERE: ");
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-16-
scanf("%c",&c); c = getchar();
Non formatée, la fonction getchar est moins gourmande en place mémoire que scanf. Il vaut mieux
l’utiliser quand cela est possible; getchar utilise le flux d’entrée exactement comme scanf.
CORRIGE DES EXERCICES
Exercice II_1:
#include <stdio.h>
#include <conio.h>
void main()
{
char c;
printf("ENTRER UN CARACTERE: ");
scanf("%c",&c);
printf("VOICI SON CODE ASCII EN DECIMAL: %d\n",c);
puts("Pour continuer frapper une touche...");
getch();
}
Exercice II_2:
#include <stdio.h>
#include <conio.h>
void main()
{i
nt nombre;
printf("ENTRER UN NOMBRE ENTIER: ");
scanf("%d",&nombre);
printf("VOICI CE NOMBRE EN HEXADECIMAL: %x\n",nombre);
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice II_3: Seul le caractère 6 est pris en compte. L’affichage suivant la saisie donnera 54, c’est
à dire le code ASCII de 6.
Exercice II_5: Oui car lors du deuxième appel à scanf, le programme attend un entier(int), alors que
le tampon ne contient qu’un caractère (char).
A l’issue de l’exécution le tampon contient les deux caractères LF.
Exercice II_6: Non car à l’issue de la première saisie, le tampon contient le caractère LF qui sera lu
lors du deuxième appel à scanf. Apres exécution du programme, le tampon est vide.
Exercice II_7: L’affichage de c1 en hexadécimal donne 36 c’est à dire le code ASCII de 6,
l’utilisateur ne peut saisir c2, l’affichage de c2 en hexadécimal donne 37 c’est à dire le code ASCII
de 7.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-17-
CHAPITRE 3
LES BOUCLES
L'INSTRUCTION SI ... ALORS ... SINON ...
Il s’agit de l’instruction: si (expression conditionnelle vraie)
alors {BLOC 1 D'INSTRUCTIONS}
sinon {BLOC 2 D'INSTRUCTIONS}
Organigramme:
condition
vraie
bloc 1 d’
instructions
bloc 2 d’
instructions
oui non
suite du programme
Syntaxe en C: if (expression)
{
............; /* bloc 1 d'instructions */
............;
............;
}
else
{
............; /* bloc 2 d'instructions */
............;
............;
}
Le bloc "sinon" est optionnel: si (expression vraie)
alors {BLOC D'INSTRUCTIONS}
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-18-
condition
vraie
oui non
bloc d’
instructions
suite du programme
Syntaxe en C: if (expression)
{
............; /* bloc d'instructions */
............;
............;
}
Remarque: les {} ne sont pas nécessaires lorsque les blocs ne comportent qu’une seule instruction.
LES OPERATEURS LOGIQUES
test d’égalité: if (a==b) " si a égal b "
test de non égalité: if (a!=b) " si a différent de b "
tests de relation d’ordre: if (a<b) if (a<=b) if (a>b) if (a>=b)
test de ET LOGIQUE: if ((expression1) && (expression2))
" si l'expression1 ET l'expression2 sont vraies "
test de OU LOGIQUE if ((expression1) || (expression2))
" si l'expression1 OU l'expression2 est vraie "test de NON
LOGIQUE if (!(expression1))
" si l'expression1 est fausse "
Toutes les combinaisons sont possibles entre ces tests.
Exercice III-1: L’utilisateur saisit un caractère, le programme teste s’il s’agit d’une lettre majuscule, si
oui il renvoie cette lettre en minuscule, sinon il renvoie un message d’erreur.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-19-
Le langage C admet des écritures contractées dans les expressions de test:
char reponse; est équivalent à char reponse;
printf("Voulez-vous jouer ?"); printf("Voulez-vous jouer ?");
reponse = getchar();
if(reponse == 'o') if((reponse = getchar()) =='o')
printf("BONJOUR\n"); printf("BONJOUR\n");
else printf("TANT-PIS"\n); else printf("TANT-PIS"\n);
LA BOUCLE TANT QUE ... FAIRE ...
Il s’agit de l’instruction: tant que (expression vraie)
faire{BLOC D'INSTRUCTIONS}
Organigramme:
condition
vraie
oui non
bloc d’
instructions
Syntaxe en C: while (expression)
{
............; /* bloc d'instructions */
............;
............;
}
Le test se fait d'abord, le bloc d’instructions n’est pas forcément exécuté.
Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu’une seule instruction.
Remarque: On peut rencontrer la construction suivante: while (expression); terminée par un ; et
sans la présence du bloc d’instructions. Cette construction signifie: "tant que l'expression est vraie
attendre".
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-20-
L'INSTRUCTION POUR ...
Il s’agit de l’instruction:
pour (initialisation; condition de continuité vraie;modification)
{BLOC D'INSTRUCTIONS}
Organigramme:
bloc d’instructions
oui
suite du programme
initialisation
condition de
continuité vraie non
modification
Syntaxe en C:
for(initialisation ; condition de continuité ; modification)
{
............; /* bloc d'instructions */
............;
............;
}
Remarques:
Les {} ne sont pas nécessaires lorsque le bloc ne comporte qu’une seule instruction.
Les 3 instructions du for ne portent pas forcément sur la même variable.
Une instruction peut être omise, mais pas les ;
Exemples: for(i = 0 ; i<10 ; i++)
{
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-21-
............; /* bloc d'instructions */
............;
............;
}
correspond à l’organigramme suivant:
i = 0
bloc d’instructions
i = i + 1
oui
i < 10
suite du
programme
non
La boucle for(;;)
{
............; /* bloc d'instructions */
............;
............;
}
est une boucle infinie (répétition infinie du bloc d’instructions).
Utilisation de variables différentes:
resultat = 0;
for(i = 0 ; resultat<30 ; i++)
{
............; /* bloc d'instructions */
............;
............;
resultat = resultat + 2*i;
}
Exercice III-2:
Saisir un entier, calculer n!
Utiliser une boucle while puis une boucle for.
Quelle est la plus grande valeur possible de n, si n est déclaré int, puis unsigned ?
L'INSTRUCTION AU CAS OU ... FAIRE ...
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-22-
L’instruction switch permet des choix multiples uniquement sur des entiers (int) ou des
caractères (char).
Syntaxe:
switch(variable de type char ou int) au cas où la variable vaut:
{
case valeur1: ......; - cette valeur1: executer ce bloc d’instructions.
.......;
break;
valeur2:........; - cette valeur2: executer ce bloc d’instructions.
........;
break;
..
etc ...
.
default: .......; - aucune des valeurs précédentes: executer ce bloc
........; d’instructions, pas de "break" ici.
}
le bloc "default" n’est pas obligatoire.
Linstruction switch correspond à une cascade dinstructions if ...else
Exemple:
Cette instruction est commode pour fabriquer des "menus":
char choix;
printf("LISTE PAR GROUPE TAPER 1\n");
printf("LISTE ALPHABETIQUE TAPER 2\n");
printf("POUR SORTIR TAPER S\n");
printf("\nVOTRE CHOIX: ");
choix = getchar();
switch(choix)
{
case '1': .......;
.......;
break;
case '2': ......;
......;
break;
case 'S': printf("\nFIN DU PROGRAMME ....");
break;
default; printf("\nCE CHOIX N'EST PAS PREVU "); /* pas de break ici */
}
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-23-
L'INSTRUCTION REPETER ... TANT QUE ...
Il s’agit de l’instruction: répéter{BLOC D'INSTRUCTIONS}
tant que (expression vraie)
Organigramme:
bloc d’
instructions
condition
vraie
non
suite du programme
oui
Syntaxe en C: do
{
............; /* bloc d'instructions */
............;
............;
}
while (expression);
Le test se faisant après, le bloc est exécuté au moins une fois.
Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu’une seule instruction.
COMPLEMENT SUR LES TESTS
En langage C, une expression nulle de type entier (int) est fausse, une expression non nulle de
type entier (int) est vraie.
Exemples:
int a,b,c,delta; est équivalent à int a,b,c,delta;
delta = b*b-4*a*c; delta = b*b-4*a*c;
if(delta != 0) if(delta)
{ ....... } { ....... }
int a,b,c,delta; est équivalent à int a,b,c,delta;
delta = b*b-4*a*c; delta = b*b-4*a*c;
if(delta == 0) if(!delta)
{ ....... } {.......}
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-24-
EXERCICES RECAPITULATIFS
Exercice III_3: résoudre ax2 + bx +c = 0.
Exercice III_4: Saisir une suite de caractères, compter et afficher le nombre de lettres e et d’espaces.
Utiliser les propriétés du tampon.
Exercice III_5: La fonction kbhit appartient à la bibiothèque conio.h. Une fonction équivalente peut
exister avec d’autres compilateurs. La fonction kbhit teste si un caractère a été frappé au clavier.
Tant que ce n’est pas vrai kbhit renvoie 0 (ceci signifie que la valeur de la fonction kbhit est 0).
Exemple: while(kbhit() == 0) /*tant qu’aucun caractère n’a été frappé exécuter la boucle*/
{ ..... }
Cette écriture est équivalente à:
while(!kbhit()); /* tant que kbhit est faux, exécuter la boucle */
{ ..... }
Ecrire un programme qui affiche le carré des entiers 1, 2, 3 ......, toutes les 500 ms tant qu’aucun
caractère n’a été frappé au clavier. Générer la temporisation à laide dune boucle for et dun
décompteur.
CORRIGE DES EXERCICES
Exercice III-1:
#include <stdio.h>
#include<conio.h>
void main()
{
char c;
printf("ENTRER UNE LETTRE:");
c = getchar();
if((c>='A') && (c<='Z')) printf("CETTE LETTRE EN MINUSCULE: %c\n",c);
else printf("CE N'EST PAS UNE LETTRE MAJUSCULE\n");
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice III-2:
#include <stdio.h>
#include <conio.h>
void main()
{
int n,i,fac= 1;
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-25-
printf("ENTRER UN ENTIER: ");scanf("%d",&n);
for (i=1;i<=n;i++) fac= fac * i;
printf("\nn = %d n! = %d",n,fac);
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE");
getch();
}
Les entiers sont des nombres de 32 bits:
n int: n! maximum= 12!
n unsigned: n! maximum = 12!
Exercice III_3:
#include <stdio.h>
#include <conio.h>
#include <math.h> /* contient la fonction racine */
void main()
{
float a,b,c,delta,x1,x2;
/* saisie de A,B,C */
printf("\t\t\tRESOLUTION DE L'EQUATION DU SECOND DEGRE\n");
printf("\t\t\t 2\n");
printf("\t\t\t AX +BX+C=0\n\n\n");
printf("SAISIR A B C SEPARES PAR RETURN\n");
printf("A = ");scanf("%f",&a);
printf("B = ");scanf("%f",&b);
printf("C = ");scanf("%f",&c);
/* debut du calcul */
/* cas particuliers */
if((a==0)&&(b==0)&&(c==0))printf("INFINITE DE SOLUTIONS\n");
if((a==0)&&(b==0)&&(c!=0))printf("PAS DE SOLUTIONS\n");
if((a==0)&&(b!=0))printf("UNE SOLUTION: X= %f\n",-c/b);
/*cas general */
if(a!=0)
{
delta = b*b-4*a*c;
printf("DELTA= %f\n",delta);
if(delta<0)printf("DELTA NEGATIF PAS DE SOLUTION\n");
else
{
if(delta==0)printf("DELTA NUL, UNE SOLUTION X= %f\n",-b/2/a);
else{
x1= (-b+sqrt(delta))/2/a;
x2= (-b-sqrt(delta))/2/a;
printf("DELTA POSITIF DEUX SOLUTIONS\n");
printf("X1= %f X2= %f\n",x1,x2);
}
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-26-
}
}
/* calculs termines */
printf("\n\nPOUR CONTINUER FRAPPER UNE TOUCHE");
getch();
}
Exercice III_4:
#include <stdio.h>
#include <conio.h>
void main()
{
char c,compt_espace= 0,compt_e= 0;
printf("ENTRER UNE PHRASE:\n");/* l'utilisateur saisit la totalite de sa phrase */
while((c=getchar())!='\n') /* lors du 1er passage, getchar ne prend */
/* en compte que le 1er caractere */
{ /* les autres sont ranges dans le tampon */
if(c=='e')compt_e++; /* et recuperes par getchar lors */
/* des autres passages */
if(c==' ')compt_espace++;
}
printf("NOMBRE DE e: %d\n",compt_e);
printf("NOMBRE D'ESPACE: %d\n",compt_espace);
printf("POUR SORTIR FRAPPER UNE TOUCHE ");
getch();
}
Exercice III_5:
#include <stdio.h>
#include <conio.h>
void main()
{
int i = 0;
float x,tempo=5000000;
printf("POUR SORTIR DE CE PROGRAMME FRAPPER UNE TOUCHE ...\n");
do
{
printf("i = %d i*i = %d\n",i,i*i);
for(x=tempo;x>0;x--);
i++;
}
while(kbhit()==0); /* on peut aussi ‚crire while(!kbhit()); */
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-27-
CHAPITRE 4
UTILISATION D'UNE BIBLIOTHEQUE
Ce petit chapitre vise à expliquer comment se servir d’une bibliothèque de fonctions. On prendra
quelques exemples dans la bibliothèque de BORLAND C++.
NOTION DE PROTOTYPE
Les fichiers de type ".h" (conio.h, dos.h stdio.h etc...), appelés fichiers d'en tête contiennent la
définition des prototypes des fonctions utilisées dans le programme. Le prototype précise la syntaxe
de la fonction: son nom, les paramètres éventuels à passer, la valeur éventuelle retournée au
programme.
Grâce aux lignes "#include", le compilateur lit les fichiers de type ".h" et vérifie que la syntaxe de
l’appel à la fonction est correcte.
FONCTION NE RENVOYANT RIEN AU PROGRAMME
Ce sont les fonctions de type void.
Exemple: clrscr
fonction Efface l’écran de la fenêtre dos.
prototype void clrscr();
prototype dans conio.h et donc bibliothèque à charger.
Une fonction ne renvoyant rien (de type void) s’écrit telle que. Ici pas de passage d’arguments.
ex: clrscr(); /* efface l’écran */
printf("BONJOUR\n");
printf("AU REVOIR\n");
FONCTION RENVOYANT UNE VALEUR AU PROGRAMME
Ce sont les fonctions de type autre que void. Elles renvoient au programme une valeur dont le type
est précisé dans la documentation.
Exemple: kbhit
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-28-
fonction Teste une éventuelle frappe au clavier
prototype int kbhit();
prototype dans conio.h et donc bibliothèque à charger.
La fonction kbhit renvoie un entier au programme. Cet entier vaut 0, tant qu’il n’y a pas eu de frappe
clavier. On ne peut donc pas écrire la fonction telle que. Il faut la traiter comme une variable de type
int.
ex: while(kbhit ()== 0); /* tend que kbhit vaut 0, attendre */
FONCTION AVEC PASSAGE DE PARAMETRE
Exemple: log
fonction Fonction logarithme népérien..
prototype double log(double);
prototype dans math.h et donc bibliothèque à charger.
La fonction log, renvoie au programme un réel. On traite la fonction comme une variable de type
double. Il faut lui passer un paramètre de type double.
ex: double x,y;
printf("SAISIR x: ");
scanf("%f",&x);
y = log(x);
printf("log(x) = %f\n",y);
Exercice IV_1:
En utilisant randomize et random jouer au 421.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
void main()
{
char c;
int n1,n2,n3;
printf("JEU DU 421\n");
randomize();
do
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-29-
{
clrscr() ;
/* LANCEMENT DES DES */
printf("LANCER LES DES EN FRAPPANT UNE TOUCHE: ");
getch();
n1 = random(6) + 1;
n2 = random(6) + 1;
n3 = random(6) + 1;
printf("\n VOICI LES DES: %1d %1d %1d\n",n1,n2,n3);
/* TEST */
if(((n1==4) && (n2==2) && (n3 ==1))||
((n1==4) && (n2==1) && (n3 ==2))||
((n1==2) && (n2==4) && (n3 ==1))||
((n1==2) && (n2==1) && (n3 ==4))||
((n1==1) && (n2==2) && (n3 ==4))||
((n1==1) && (n2==4) && (n3 ==2)))printf("GAGNE !\n");
else printf("PERDU !\n");
printf("\nPOUR REJOUER FRAPPER O SINON UNE TOUCHE
QUELCONQUE\n");
c = getch();
}
while((c=='O')||(c=='o'));
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-30-
CHAPITRE 5
LES POINTEURS
L’étude des pointeurs montre l’adaptation du langage C à la conduite de processus. On verra dans ce
chapitre et les suivants la puissance de cette notion par ailleurs de concept simple pour un
informaticien industriel.
L'OPERATEUR ADRESSE &
L'opérateur adresse & retourne l'adresse d'une variable en mémoire.
Exemple: int i = 8;
printf("VOICI i: %d\n",i);
printf("VOICI SON ADRESSE EN HEXADECIMAL: %p\n",&i);
On remarque que le format d’une adresse est %p (hexadécimal) ou %d (décimal) dans printf.
Exercice V_1: Exécuter lexemple précédent, et indiquer les cases-mémoire occupées par la
variable i.
LES POINTEURS
Définition: Un pointeur est une adresse mémoire. On dit que le pointeur pointe sur cette
adresse.
DECLARATION DES POINTEURS
Une variable de type pointeur se déclare à l’aide de l’objet pointé précédé du symbole * (opérateur
d'indirection).
Exemple: char *pc; pc est un pointeur pointant sur un objet de type char
int *pi; pi est un pointeur pointant sur un objet de type int
float *pr; pr est un pointeur pointant sur un objet de type float
L'opérateur * désigne en fait le contenu de l'adresse.
Exemple: char *pc;
*pc = 34 ;
printf("CONTENU DE LA CASE MEMOIRE: %c\n",*pc);
printf("VALEUR DE L’ADRESSE EN HEXADECIMAL: %p\n",pc);
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-31-
ARITHMETIQUE DES POINTEURS
On peut essentiellemet déplacer un pointeur dans un plan mémoire à l’aide des opérateurs
d’addition, de soustraction, d’incrémentation, de décrémentation. On ne peut le déplacer que d'un
nombre de cases mémoire multiple du nombre de cases réservées en mémoire pour la variable
sur laquelle il pointe.
C STANDARD
PLAN MEMOIRE
00
00
00
00
0a
pi
pc
pi+1
pc+1
int *pi;
char *pc;
*pi = 0;
*pc = 0x0a;
Exemples:
int *pi; /* pi pointe sur un objet de type entier */
float *pr; /* pr pointe sur un objet de type réel */
char *pc; /* pc pointe sur un objet de type caractère */
*pi = 421; /* 421 est le contenu de la case mémoire p et des 3 suivantes */
*(pi+1) = 53; /* on range 53 4 cases mémoire plus loin */
*(pi+2) = 0xabcd; /* on range 0xabcd 8 cases mémoire plus loin */
*pr = 45.7; /* 45,7 est rangé dans la case mémoire r et les 3 suivantes */
pr++; /* incrémente la valeur du pointeur r (de 4 cases mémoire) */
printf("L’ADRESSE r VAUT: %p\n",pr); /* affichage de la valeur de l’adresse r */
*pc = ’j’; /* le contenu de la case mémoire c est le code ASCII de ’j’ */
pc--; /* décrémente la valeur du pointeur c (d’une case mémoire) */
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-32-
ALLOCATION DYNAMIQUE
Lorsque l’on déclare une variable char, int, float .... un nombre de cases mémoire bien défini est
réservé pour cette variable. Il n’en est pas de même avec les pointeurs.
Exemple:
char *pc;
*pc = ’a’; /* le code ASCII de a est rangé dans la case mémoire pointée par c */
*(pc+1) = ’b’; /* le code ASCII de b est rangé une case mémoire plus loin */
*(pc+2) = ’c’; /* le code ASCII de c est rangé une case mémoire plus loin */
*(pc+3) = ’d’; /* le code ASCII de d est rangé une case mémoire plus loin */
Dans cet exemple, le compilateur a attribué une valeur au pointeur c, les adresses suivantes sont
donc bien définies; mais le compilateur n’a pas réservé ces places: il pourra très bien les attribuer un
peu plus tard à d’autres variables. Le contenu des cases mémoires c c+1 c+2 c+3 sera donc perdu.
Ceci peut provoquer un blocage du système sous WINDOWS.
Il existe en langage C, des fonctions permettant d'allouer de la place en mémoire à un pointeur.
Il faut absolument les utiliser dès que l’on travaille avec les pointeurs.
Exemple: la fonction malloc
char *pc;
int *pi,*pj,*pk;
float *pr;
pc = (char*)malloc(10); /* on réserve 10 cases mémoire, soit la place pour 10 caractères */
pi = (int*)malloc(16); /* on réserve 16 cases mémoire, soit la place pour 4 entiers */
pr = (float*)malloc(24); /* on réserve 24 places en mémoire, soit la place pour 6 réels */
pj = (int*)malloc(sizeof(int)); /* on réserve la taille d’un entier en mémoire */
pk = (int*)malloc(3*sizeof(int)); /* on réserve la place en mémoire pour 3 entiers */
Libération de la mémoire: la fonction free
free(pi); /* on libère la place précédemment réservée pour i */
free(pr); /* on libère la place précédemment réservée pour r */
Exercice V_2:
adr1 et adr2 sont des pointeurs pointant sur des réels. Le contenu de adr1 vaut
-45,78; le contenu de adr2 vaut 678,89. Ecrire un programme qui affiche les valeurs de adr1, adr2 et
de leur contenu.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-33-
AFFECTATION D'UNE VALEUR A UN POINTEUR
Dans les exemples précédents, l’utilisateur ne choisit pas la valeur des adresses mémoire attribuées
par le compilateur à chaque variable. L’utilisateur se contente de lire la valeur de ces adresses en
l’ affichant sur l’écran.
On ne peut pas affecter directement une valeur à un pointeur:
l'écriture suivante est interdite: char *pc;
pc = 0xfffe;
On peut cependant être amené à définir par programmation la valeur d’une adresse. On utilise
pour cela l’opérateur de "cast", jeu de deux parenthèses.
- Par exemple pour adresser un périphérique (adressage physique),
- Par exemple pour contrôler la zône DATA dans un plan mémoire.
Exemples:
char *pc;
pc = (char*)0x1000; /* p est l’adresse 0x1000 et pointe sur un caractère */
int *pi;
pi = (int*)0xfffa; /* i est l’adresse 0xfffa et pointe sur un entier */
Lorsqu'on utilise une fonction d'allocation dynamique on ne peut affecter de valeur au
pointeur à l'aide de l'opérateur de cast.
Ces 2 premiers exemples sont à proscrire sous WINDOWS.
Exercice V_3:
pi est un pointeur sur un entier; pi vaut 0x5000 et son contenu vaut 300. Ecrire le programme
correspondant (programme dangereux sous WONDOWS).
L’opérateur de "cast", permet d’autre part, à des pointeurs de types différent de pointer sur la même
adresse.
Exemple: char *pc; /* pc pointe sur un objet de type caractère */
int *pi; /* pi pointe sur un objet de type entier */
pi = (int*)malloc(4) ; /* allocation dynamique pour i */
pc = (char*)i; /* c et i pointent sur la même adresse, c sur un caractère */
Exercice V_4:
adr_i est un pointeur de type entier; son contenu i vaut 0x12345678. A l’aide d’une conversion de
type de pointeur, écrire un programme montrant le rangement des 4 octets en mémoire.
Exercice V_5:
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-34-
Saisir un texte. Ranger les caractères en mémoire. Lire le contenu de la mémoire et y compter le
nombre d’espaces et de lettres e .
Exercice V_6:
Saisir 6 entiers et les ranger à partir de l’adresse adr_deb. Rechercher le maximum, l’afficher ainsi
que son adresse.
PETIT RETOUR A LA FONCTION SCANF
On a vu au chapitre 2 que pour saisir un caractère ou un nombre, on donne en fait l’adresse de ce
caractère:
Exemple: char c;
printf("TAPER UNE LETTRE: ");
scanf("%c",&c);
On saisit ici le contenu de l’adresse &c c’est à dire le caractère c lui-même.
On peut donc aussi procéder ainsi:
char *adr;
printf("TAPER UNE LETTRE: ");
scanf("%c",adr);
On saisit ici le contenu de l’adresse adr.
Cette méthode s’applique aux caractères (char), aux entiers (int), aux réels (float).
CORRIGE DES EXERCICES
Exercice V_2:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{f
loat *adr1,*adr2;
adr1 = (float*)malloc(4);
adr2 = (float*)malloc(4);
*adr1 = -45.78;
*adr2 = 678.89;
printf("adr1 = %p adr2 = %p r1 = %f r2 = %f\n",adr1,adr2,*adr1,*adr2);
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-35-
free(adr1);
free(adr2);
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice V_3:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
int *i;
i = (int*)malloc(4);
*i = 300;
printf(" adresse = %p variable = %d\n",i,*i);
free(i);
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice V_4:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
char *adr_c;
int *adr_i,i=0x12345678;
adr_i = &i;
adr_c = (char*)adr_i;
printf("ADRESSE: %p CONTENU: %x\n",adr_c,*adr_c);
printf("ADRESSE: %p CONTENU: %x\n",adr_c+1,*(adr_c+1));
printf("ADRESSE: %p CONTENU: %x\n",adr_c+2,*(adr_c+2));
printf("ADRESSE: %p CONTENU: %x\n",adr_c+3,*(adr_c+3));
getch();
}
L’analyse de l’exécution en BORLANC C++, montre que les microprocesseurs INTEL rangent en
mémoire d’abord les poids faibles d’une variable.
Exercice V_5:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-36-
{
char *adr_deb,c;
int i,imax,compt_e = 0,compt_sp = 0;
adr_deb = (char*)malloc(30); /* texte d'au plus 30 caracteres */
/* saisie et rangement du texte */
printf("\nADRESSE DU TEXTE: %p (ATTRIBUEE PAR LE COMPILATEUR)",adr_deb);
printf("\nENTRER UN TEXTE: ");
for (i=0;((c=getchar())!='\n');i++) *(adr_deb + i) = c;
imax = i; /* borne superieure */
/* lecture de la memoire et tri */
for (i=0;i<imax;i++)
{
c = *(adr_deb+i);
printf("\nCARACTERE: %c ADRESSE: %p",c,adr_deb+i);
if (c=='e') compt_e++;
if (c==' ') compt_sp++;
}
/* resultats */
printf("\nNOMBRE DE e: %2d NOMBRE d'espaces: %2d\n",compt_e,compt_sp);
free(adr_deb);
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice V_6:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
int *adr_deb,*adr_max,i,imax=6,max;
adr_deb=(int*)malloc(4*6);
printf("\nADRESSE DE BASE: %p (CHOISIE PAR LE PROGRAMMEUR)\n",adr_deb);
/* saisie des nombres */
printf("SAISIE DES NOMBRES: \n");
for(i=0;i<imax;i++)
{
printf("ENTRER UN NOMBRE: ");
scanf("%d",adr_deb+i);
}
/* tri */
max = *adr_deb;
adr_max = (int*)adr_deb;
for(i=0;i<imax;i++)
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-37-
{i
f(*(adr_deb+i)>max)
{
max = *(adr_deb+i);
adr_max = adr_deb+i;
}
}
/* resultats */
printf("LE MAXIMUM:%d SON ADRESSE:%p\n",max,adr_max);
free(adr_deb);
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE");
getch();
}
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-38-
CHAPITRE 6
LES TABLEAUX ET LES CHAINES DE CARACTERES
LES TABLEAUX DE NOMBRES (INT ou FLOAT)
Les tableaux correspondent aux matrices en mathématiques. Un tableau est caractérisé par sa
taille et par ses éléments.
Les tableaux à une dimension:
Déclaration: type nom[dim]; Exemples: int compteur[10];
float nombre[20];
Cette déclaration signifie que le compilateur réserve dim places en mémoire pour ranger les
éléments du tableau.
Exemples:
int compteur[10]; le compilateur réserve des places pour 10 entiers, soit 20 octets en TURBOC et
40 octets en C standard.
float nombre[20]; le compilateur réserve des places pour 20 réels, soit 80 octets.
Remarque: dim est nécessairement une VALEUR NUMERIQUE. Ce ne peut être en aucun cas une
combinaison des variables du programme.
Utilisation: Un élément du tableau est repéré par son indice. En langage C les tableaux commencent
à l’indice 0. L’indice maximum est donc dim-1.
Appel: nom[indice]
Exemples: compteur[2] = 5;
nombre[i] = 6.789;
printf("%d",compteur[i]);
scanf("%f",&nombre[i]);
Tous les éléments d'un tableau (correspondant au dimensionnement maximum) ne sont pas
forcément définis.
D’une façon générale, les tableaux consomment beaucoup de place en mémoire. On a donc intérêt à
les dimensionner au plus juste.
Exercice VI_1: Saisir 10 réels, les ranger dans un tableau. Calculer et afficher la moyenne et l’écarttype.
Les tableaux à plusieurs dimensions:
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-39-
Tableaux à deux dimensions:
Déclaration: type nom[dim1][dim2]; Exemples: int compteur[4][5];
float nombre[2][10];
Utilisation: Un élément du tableau est repéré par ses indices. En langage C les tableaux
commencent aux indices 0. Les indices maximum sont donc dim1-1, dim2-1.
Appel: nom[indice1][indice2]
Exemples: compteur[2][4] = 5;
nombre[i][j] = 6.789;
printf("%d",compteur[i][j]);
scanf("%f",&nombre[i][j]);
Tous les éléments d'un tableau (correspondant au dimensionnement maximum) ne sont pas
forcément définis.
Exercice VI_2: Saisir une matrice d’entiers 2x2, calculer et afficher son déterminant.
Tableaux à plus de deux dimensions:
On procède de la même façon en ajoutant les éléments de dimensionnement ou les indices
nécessaires.
INITIALISATION DES TABLEAUX
On peut initialiser les tableaux au moment de leur déclaration:
Exemples:
int liste[10] = {1,2,4,8,16,32,64,128,256,528};
float nombre[4] = {2.67,5.98,-8,0.09};
int x[2][3] = {{1,5,7},{8,4,3}}; /* 2 lignes et 3 colonnes */
TABLEAUX ET POINTEURS
En déclarant un tableau, on définit automatiquement un pointeur (on définit en fait l’adresse du
premier élément du tableau).
Les tableaux à une dimension:
Les écritures suivantes sont équivalentes:
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-40-
int *tableau; int tableau[10]; déclaration
tableau = (int*)malloc(sizeof(int)*10);
*tableau tableau[0] le 1er élément
*(tableau+i) tableau[i] un autre élément
tableau &tableau[0] adresse du 1er élément
(tableau + i) &(tableau[i]) adresse d'un autre élément
Il en va de même avec un tableau de réels (float).
Remarque: La déclaration d’un tableau entraine automatiquement la réservation de places en
mémoire. Ce n’est pas le cas lorsque l’on déclare un pointeur. Il faut alors utiliser une fonction
d’allocation dynamique comme malloc.
Les tableaux à plusieurs dimensions:
Un tableau à plusieurs dimensions est un pointeur de pointeur.
Exemple: int t[3][4]; t est un pointeur de 3 tableaux de 4 éléments ou bien de 3 lignes à 4 éléments.
Les écritures suivantes sont équivalentes:
t[0] &t[0][0] t adresse du 1er élément
t[1] &t[1][0] adresse du 1er élément de la 2e ligne
t[i] &t[i][0] adresse du 1er élément de la ième ligne
t[i]+1 &(t[i][0])+1 adresse du 1er élément de la ième +1 ligne
REPARTITION DES ELEMENTS EN MEMOIRE
Le tableau a été déclaré ainsi: int t[3][4];
t[0]
t[0][0]
t[0][2]
t[1]
t[2]
t[2][3]
Exercice VI_3:
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-41-
Un programme contient la déclaration suivante:
int tab[10] = {4,12,53,19,11,60,24,12,89,19};
Compléter ce programme de sorte d’afficher les adresses des éléments du tableau.
Exercice VI_4:
Un programme contient la déclaration suivante:
int tab[20] = {4,-2,-23,4,34,-67,8,9,-10,11, 4,12,-53,19,11,-60,24,12,89,19};
Compléter ce programme de sorte d’afficher les éléments du tableau avec la présentation suivante:
4 -2 -23 4 34
-67 8 9 -10 11
4 12 -53 19 11
-60 24 12 89 19
LES CHAINES DE CARACTERES
En langage C, les chaînes de caractères sont des tableaux de caractères. Leur manipulation est
donc analogue à celle d’un tableau à une dimension:
Déclaration: char nom[dim]; ou bien char *nom;
nom = (char*)malloc(dim);
Exemple: char texte[dim]; ou bien char *texte;
texte = (char*)malloc(10);
Le compilateur réserve (dim-1) places en mémoire pour la chaîne de caractères: En effet, il ajoute
toujours le caractère NUL ('\0') à la fin de la chaîne en mémoire.
Affichage à l'écran:
On peut utiliser la fonction printf et le format %s:
char texte[10] = « BONJOUR »;
printf("VOICI LE TEXTE: %s\n",texte);
On utilisera si possible la fonction puts non formatée:
puts(texte); est équivalent à printf("%s\n",texte);
Saisie: On peut utiliser la fonction scanf et le format %s. Une chaîne étant un pointeur, on n’écrit
pas le symbole &. On utilisera de préférence la fonction gets non formatée.
char texte[10];
printf("ENTRER UN TEXTE: ");
scanf("%s",texte); est équivalent à gets(texte);
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-42-
Remarque: scanf ne permet pas la saisie d’une chaîne comportant des espaces: les caractères saisis à
partir de l’espace ne sont pas pris en compte (l’espace est un délimiteur au même titre que LF) mais
rangés dans le tampon d’entrée. Pour saisir une chaîne de type "il fait beau", il faut utiliser gets.
A l’issue de la saisie d’une chaîne de caractères, le compilateur ajoute ’\0’ en mémoire après le
dernier caractère.
Comme expliqué au chapitre 2, gets et scanf utilisent le flux d’entrée.
Exercice VI_5:
Saisir une chaîne de caractères, afficher les éléments de la chaîne et leur adresse (y compris le
dernier caractère ’\0’).
Exercice VI_6:
Saisir une chaîne de caractères. Afficher le nombre de e et d’espaces de cette chaîne.
Fonctions permettant la manipulation des chaînes:
Les bibliothèques fournies avec les compilateurs contiennent de nombreuses fonctions de traitement
des chaînes de caractères. En BORLAND C++, elles appartiennent aux bibliothèques string.h ou
stdlib.h. En voici quelques exemples:
Générales (string.h):
void *strcat(char *chaine1,char *chaine2) concatène les 2 chaînes, résultat dans chaine1,
renvoie l’adresse de chaine1.
int strlen(char *chaine) renvoie la longueur de la chaine (’\0’ non comptabilisé).
void *strrev(char *chaine) inverse la chaîne et, renvoie l’adresse de la chaine inversée.
Comparaison (string.h):
int strcmp(char *chaine1,char *chaine2) renvoie un nombre:
- positif si la chaîne1 est supérieure à la chaine2 (au sens de l’ordre alphabétique)
- négatif si la chaîne1 est inférieure à la chaîne2
- nul si les chaînes sont identiques.
Copie (string.h):
void *strcpy(char *chaine1,char *chaine2)
recopie chaine2 dans chaine1 et renvoie l’adresse de chaîne1.
Recopie (string.h):
Ces fonctions renvoient l’adresse de l’information recherchée en cas de succès, sinon le pointeur
NULL (c’est à dire le pointeur de valeur 0 ou encore le pointeur faux).
void *strchr(chaine,caractère) recherche le caractère dans la chaîne.
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-43-
void *strrchr(chaine,caractère) idem en commençant par la fin.
void *strstr(chaîne,sous-chaîne) recherche la sous-chaine dans la chaîne.
Conversions (stdlib.h):
int atoi(char *chaîne) convertit la chaîne en entier
float atof(char *chaine) convertit la chaîne en réel
exemple: printf("ENTRER UN TEXTE: ");
gets(texte);
n = atoi(texte) ;
printf("%d",n); /* affiche 123 si texte vaut "123" */
/* affiche 0 si texte vaut "bonjour" */
void *itoa(int n,char *chaîne,int base) convertit un entier en chaîne:
base: base dans laquelle est exprimé le nombre,
cette fonction renvoie l’adresse de la chaîne.
exemple: itoa(12,texte,10); texte vaut "12"
Pour tous ces exemples, la notation void* signifie que la fonction renvoie un pointeur (l'adresse de
l'information recherchée), mais que ce pointeur n'est pas typé. On peut ensuite le typer à l'aide de
l'opérateur cast .
Exemple: int *adr;
char texte[10] = "BONJOUR";
adr = (int*)strchr(texte,’O’);
Exercice VI_7:
L’utilisateur saisit le nom d’un fichier. Le programme vérifie que celui-ci possède l’extension .PAS
Exercice VI_8:
Un oscilloscope à mémoire programmable connecté à un PC renvoie l’information suivante sous
forme d’une chaîne de caractères terminée par ’\0’au PC:
"CHANNELA 0 10 20 30 40 30 20 10 0 -10 -20 -30 -40 -30 -20 -10 -0"
Afficher sur l’écran la valeur des points vus comme des entiers. On simulera la présence de
l’oscilloscope en initialisant une chaîne de caractères char mesures[100].
CORRIGE DES EXERCICES
Exercice VI_1:
#include <stdio.h>
#include <math.h>
#include <conio.h>
void main()
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-44-
{f
loat nombre[10],moyenne = 0,ecart_type = 0;
int i;
/* saisie des nombres */
printf("SAISIR 10 NOMBRES SEPARES PAR RETURN: \n");
for(i=0;i<10;i++)
{
printf("nombre[%1d] = ",i);
scanf("%f",&nombre[i]);
}
/* calculs */
for(i=0;i<10;i++)
{
moyenne = moyenne + nombre[i];
ecart_type = ecart_type + nombre[i]*nombre[i];
}
moyenne = moyenne/10;
ecart_type = ecart_type/10;
ecart_type = ecart_type - moyenne*moyenne;
ecart_type = sqrt(ecart_type); /* racine */
printf("MOYENNE = %f ECART_TYPE = %f\n",moyenne,ecart_type);
printf("POUR CONTINUER FRAPPER UNE TOUCHE: ");
getch();
}
Exercice VI_2:
#include <stdio.h>
#include <conio.h>
void main()
{i
nt mat[2][2],det;
/* saisie */
printf("ENTRER SUCCESSIVEMENT LES VALEURS DEMANDEES: \n");
printf("mat[0][0] = ");
scanf("%d",&mat[0][0]);
printf("mat[1][0] = ");
scanf("%d",&mat[1][0]);
printf("mat[0][1] = ");
scanf("%d",&mat[0][1]);
printf("mat[1][1] = ");
scanf("%d",&mat[1][1]);
/* calcul */
det = mat[0][0]*mat[1][1]-mat[1][0]*mat[0][1];
/* affichage */
printf("DETERMINANT = %d\n",det);
Le Centre Culturel Algérien COURS/TP DE LANGAGE C
-45-
printf("POUR CONTINUER FRAPPER UNE TOUCHE: ");
getch();
}
Exercice VI_3:
#include <stdio.h>
#include <conio.h>
void main()
{
int i,tab[10]={4,12,53,19,11,60,24,12,89,19};
printf("VOICI LES ELEMENTS DU TABLEAU ET LEURS ADRESSES:\n");
for(i=0;i<10;i++)
printf("ELEMENT N¯%1d: %2d ADRESSE: %p\n",i,tab[i],tab+i);
printf("POUR SORTIR FRAPPER UNE TOUCHE: ");
getch();
}
Exercice VI_4:
#include <stdio.h>
#include <conio.h>
void main()
{
int i,tab[20] = {4,-2,-23,4,34,-67,8,9,-10,11, 4,12,-53,19,11,-60,24,12,89,19};
printf("VOICI LE TABLEAU:\n\n");
for(i=0;i<20;i++)
if (((i+1)%5)==0) printf("\t%d \n",tab[i]);
else printf("\t%d ",tab[i]);
printf("\nPOUR SORTIR FRAPPER UNE TOUCHE: ");
getch();
}
Exercice VI_5:
#include <stdio.h>
#include <conio