Langage C
Langage C
Langage C
programmation en langage C
1
Qu'est-ce qu'un bon programme?
Un Bon Programme ? ? :
Efficacité Rapidité?
- Lisible
- Structuré
2
Objectifs
Être capable de bien programmer
3
Qualités attendues d'un
programme
Clarté
Simplicité
Efficacité
Modularité
Extensibilité
4
Types de base
4 types de base, les autres types seront dérivés de ceux-ci.
5
TYPE de la valeur de retour
int main(void)
{
void main(void): La fonction main ne prend
/* corps du programme*/
begin aucun paramètre et ne retourne pas de valeur.
declaration des Cstes et Var ;
instruction1 ; int main(void): La fonction main retourne une
valeur entière à l'aide de l'instruction return (0
instruction2 ; si pas d’erreur).
….
int main(int argc, char *argv[]): On obtient
} alors des programmes auxquels on peut
end adresser des arguments au moment où on lance
le programme.
Entre accolades "{" et "}" on
mettra la succession d'actions à
réaliser.(Bloc)
6
Structure d'un programme C
#include <stdio.h>
#define DEBUT -10 Directives du préprocesseur :
#define FIN 10 accès avant la compilation
#define MSG "Programme de démonstration\n"
int fonc1(int x);
int fonc2(int x); Déclaration des fonctions
void main()
{ /* début du bloc de la fonction main*/
int i; /* définition des variables locales */
Programme
i=0; principal
fonc1(i) ;
fonc2(i) ;
} /* fin du bloc de la fonction main */
int fonc1(int x) {
return x; Définitions des
}
fonctions
int fonc2(int x) {
return (x * x);
}
7
Indenter = lisibilté #include <Lib1.h>
#include <Lib2.h>
Prenez l'habitude de respecter (au moins au début) les #define X 0;
règles :
int fonc1(int x);
- une accolade est seule sur sa ligne, float fonc2(char a);
- { est alignée sur le caractère de gauche de la ligne
précédente, int main(void)
Inclusion de fichiers
#include <nom-de-fichier> /* répertoire standard */
#include "nom-de-fichier" /* répertoire courant */
9
1er Programme
#include <stdio.h>
#include <conio.h>
int main(void)
{
10
La fonction printf() :
Librairie : stdio.h. #include <stdio.h>
Exemple :
printf("Qu'il est agreable d’utiliser printf "
"en\t C,\nlorsqu'on l'utilise \"proprement\".\n");
12
La fonction scanf() :
Librairie : stdio.h. #include <stdio.h>
Variables : initialisations
Les variables doivent être déclarées avant leur utilisation dans un début de bloc (juste après{),
zone des déclarations:
char c;
int i;
float x;
16
Affichages et saisies
Librairie : stdio.h
Fonction Syntaxe Description
17
LES DECLARATIONS DE CONSTANTES
2eme méthode: déclaration d'une variable, dont la valeur sera constante pour tout le programme.
Exemple:
void main() Le compilateur réserve de la
{ place en mémoire (ici 4 octets).
const float PI = 3.14159;
const int JOURS = 5;
float perimetre,rayon = 8.7;
perimetre = 2*rayon*PI;
.... /*ERREUR !*/ On ne peut
JOURS = 3;
....
! changer la valeur d’une const.
19
Identificateurs
Les identificateurs nomment les objets C (fonctions, variables ... )
Identificateurs valides :
xx y1 somme_5 _position
Noms surface fin_de_fichier VECTEUR
Identificateurs invalides :
3eme commence par un chiffre
x#y caractère non autorisé (#)
no-commande caractère non autorisé (-)
taux change caractère non autorisé (espace)
20
Un identificateur ne peut pas être un mot réservé du langage :
21
Les opérateurs arithmétiques
Le C propose les opérateurs suivants :
+ addition
- soustraction
* multiplication
/ division
% modulo (reste de la division entière )
7/2 3
7.0/2
7/2.0
7.0/2.0
3.5
22
Utiliser des opérateurs arithmétiques
k = i / j;
h = f / g;
h = 5/4 = 1.0000 h = i / j;
}
23
Les opérateurs de comparaison
< plus petit
Le type booléen
<= plus petit ou égal n'existe pas. Le
> plus grand résultat d'une
expression logique
>= plus grand ou égal
vaut 1 si elle est
== égal
! vraie et 0 sinon.
!= différent
Réciproquement,
Les opérateurs logiques toute valeur non
!
nulle est considérée
&& et comme vraie et la
|| ou (non exclusif) valeur nulle
comme fausse.
! non
24
int i;
Exemple
float f;
char c;
i = 7; f = 5.5; c = 'w';
aa+=
+=32;
32; ff/=
/=9.2;
9.2; ii*=
*=jj++5;5;
aa==aa++32;
32; ff==ff//9.2;
9.2; ii==ii**(j(j++5);
5);
26
Incrément et décrement
int main(void)
{
équivalent à:
int i, j = 5;
1. j++;
i = ++j;
2. i = j; !
printf("i=%d, j=%d\n", i, j);
j = 5; équivalent à:
i = j++; 1. i = j;
printf("i=%d, j=%d\n", i, j); 2. j++; !
return 0;
} i=6,
i=6,j=6
j=6
i=5,
i=5,j=6
j=6
28
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" ().
#include <stdio.h>
#include <conio.h>
void main() Conversion float -> int: 89.67 -> 89
{
Conversion int -> float: 4660 -> 4660.00
int i=0x1234, j;
char d,e; Conversion int -> char: 1234 -> 34
float r=89.67,s; Conversion float -> char: 89.67 -> 89
j = (int)r;
Pour sortir frapper une touche
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(); // pas getchar
}
29
Les structures de contrôle en C
Alternative: if-else
Choix Multiple: switch-case
Itérations: for, while, do-while
Rupture de Contrôle: break, continue, return … goto
30
Les structures de contrôle en C
Les décisions - if then else
if (expression booléenne vraie) if (a<b)
{ {
Pas de then en C BLOC 1 D'INSTRUCTIONS min=a;
} }
else else
Le bloc " else " { {
est optionnel. BLOC 2 D'INSTRUCTIONS min=b;
} }
* Tout ce qui est 0 ( ‘\0’ 0 0.0000 NULL ) est faux
* Tout ce qui est != de 0 ( 1 ‘0’ 0.0001 1.34 ) est vrai
if(32)
printf("ceci sera toujours affiche\n");
if(0)
printf("ceci ne sera jamais affiche\n");
31
Exemples :
if (i < 10) i++;
La variable i ne sera incrémentée que si elle a une valeur inférieure à 10.
}
printf(" la valeur de i =%d et moy=%f\n", i,moy) ;
if(delta == 0) = if(!delta)
else {
printf ("erreur \n");
}
i = i +2; // i +=2 ; !
32
! Attention!
Ne pas confondre = = (opérateur logique d’égalité)
et = (opérateur d’affectation)
#include <stdio.h>
int main(void)
{
int i = 0;
return 0;
}
Quand
Quandii!=
!=de
dezero
zero
33
if emboîtés
else est associé avec le if le plus proche
int i = 100;
if(i > 0)
if(i > 1000)
printf("i > 1000\n");
else
printf("i is reasonable\n"); i is reasonable
i is reasonable
int i = 100;
if(i > 0) {
if(i > 1000)
printf(" i > 1000 \n");
} else
printf("i is negative\n");
34
l es )
o u c Les itérations – for
( B
int i,j;
for( init ; test; increment) i i==00
{ for (i = 0; i <3; i++) { i i==11
/* corps de for */ printf ( "i = %d\n", i); i i==22
} j j==55
} j j==44
for(j = 5; j > 0; j- -)
printf("j = %d\n", j); j j==33
double angle; j j==22
j j==11
for(angle = 0.0; angle < 3.14159; angle += 0.2)
printf("sine of %.1lf is %.2lf\n",angle, sin(angle));
int i, j, k;
for( ; ; )
{ for(i = 0, j = 2, k = -1; (i < 20) &&(j==2); i++, k--)
............; /* bloc d'instructions */
............;
............;
}
36
Exemple
i=1; Intérieur
Intérieur 11
while(i<5) Intérieur
Intérieur 22
{ Intérieur
Intérieur 33
printf(“Intérieur %d\n",i); Intérieur
Intérieur 44
itération i++; Extérieur
Extérieur 55
}
printf("Extérieur %d\n",i);
int
intj j==5;5;
start
start
tant que, pas jusqu’à ce que! printf("start\n");
printf("start\n"); end
end
while(j == 0)
while(j == 0)
printf("j
printf("j==%d\n",
%d\n",j--);
j--);
printf("end\n");
printf("end\n");
i=1;
while(i<5);
{ "tant que l'expression est vraie
printf(“Intérieur %d\n",i); attendre".
i++;
}
37
l es )
c
( Bo u
do while = REPETER … tant que
(guarantit l’exécution au moins une fois)
bloc d' do
{
instructions ............; /* bloc d'instructions */
............;
}
while (expression);
non
condition
oui vraie
39
Cette instruction est commode pour les "menus":
default; printf("\nCE CHOIX N'EST PAS PREVU "); /* pas de break ici */
}
40
Instructions d'échappement
Pour rompre le déroulement séquentiel d'une suite d'instructions
Break;
Continue;
int i, j=1; for (i = -10; i <= 10; i++)
char a; {
for (i = -10; i <= 10; i++){ if (i == 0)
continue;
while(j!=0) /* boucle infinie */ // pour éviter la division par zéro
printf(“ %f”, 1 / i);
{ }
a=getchar();
if(a= ='x')
break; return (expression);
} permet de sortir de la fonction qui la contient
}
exit (expression); La fonction est interrompu.
Si x est tapée au clavier expression : un entier indiquant le code de terminaison
du processus
41
goto étiquette
#include <stdio.h>
void main()
{
int i, j;
for (i=0; i < 10; i++)
for (j=0; j < 4; j++) {
if ( (i*j) == 10)
goto trouve;
printf("i*j != 10.\n");
}
trouve:
printf("i*j =%d * %d = %d== 10.\n",i,j,i*j);
}
42
Tableaux : Introduction
Déclaration de tableaux
Un tableau (array) est une collection de variables de même type, appelées éléments
On les déclare par un type, un nom et une dimension (CONSTANTE) placée entre [ ]
Le C alloue toujours un tableau dans une zone contigüe de la mémoire
Une fois déclaré, on ne peut redimensionner un tableau
Exemples
int tab[4]; déclare un tableau de 4 valeurs entières tab[0] tab[1] tab[2] tab[3] !
#define
#define SIZE
SIZE 10
10
int
int a[SIZE];
a[SIZE]; /*/*aaest
estun
unvecteur
vecteurde
de10
10entiers
entiers*/*/
le compilateur réserve SIZE places en mémoire pour ranger les éléments du tableau.
float
float A[5]
A[5] =={{10.1,
10.1,20.3,
20.3,30.5,
30.5,40.0,
40.0,50.4
50.4};};
43
Accès aux éléments d’un tableau
Les éléments sont numérotés de 0 à dim-1 !
Il n’y a pas de vérification de bornes
a
void
voidmain(void)
main(void) void
void main(void)
main(void)
{{ 59 0
{{
int
int a[6];
a[6]; ? 1
int
int i i==7;7; int
inti;i;
? 2
int
intA[6]
A[6]=={{1,1,2,3,
2,3,5,5,7,7,11
11};};
a[0]
a[0]==59;
59; 2 3
a[5]
a[5]==-10;
-10; for
for(i=0;i<6;i++)
(i=0;i<6;i++)
a[i/2] ? 4
a[i/2]==2;2; printf("%d
-10 printf("%d",",A[i]);
A[i]);
5
a[6]
a[6]==0;0; }}
a[-1]
a[-1]==5;5;
}}
45
Fonctions en C
Encapsule un traitement particulier formant un tout
Peut implémenter la notion de module en logique
Notion de librairie
Augmente la lisibilité d’un programme
Réalise un objectif précis
Améliore le débogage et la maintenance d’un programme
Son utilisation se décompose en trois phases :
Définition de la fonction
Déclaration de la fonction
Appel de la fonction Déclarer une fonction
Appeler une fonction
Règles de visibilité des variables
Passage des paramètres par valeur
Fonction renvoyant une valeur au programme
Passage des paramètres par valeur et par adresse
Passage des tableaux aux fonctions
46
Fonctions en C
Les principes
En C, tout est fonction (Définition, Déclaration et Appel).
Une fonction peut avoir autant de paramètres que l’on veut, même
aucun
(comme void main(void))
Une fonction renvoie une valeur ou aucune.
Les variables déclarées dans une fonction sont locales à cette fonction
Une fonction possède un et un seul point d'entrée, mais
éventuellement plusieurs points de sortie (à l'aide du mot return).
L'imbrication de fonctions n'est pas autorisée:
une fonction ne peut pas être déclarée à l'intérieur d'une autre fonction. Par contre, une fonction
peut appeler une autre fonction. Cette dernière doit être déclarée avant celle qui l'appelle.
47
Déclarer une fonction
printf("Celsius\tFarenheit\n");
for(d = start; d <= end; d += step, lines++)
printf("%.1lf\t%.1lf\n", d, d * 1.8 + 32);
return lines;
}
Valeur renvoyée
48
Appeler une fonction
IMPORTANT: cette instruction spécifie comment la fonction est définie
#include <stdio.h>
void main(void)
{
int combien; Le compilateur attend des
double end = 100.0; doubles; les conversions sont
automatiques
combien = print_table(1.0,end,3);
print_table(end, 200, 15);
}
Ici, on ne tient pas compte de la valeur de retour
49
float calculeFloat(float, float);
int addition();
void main(void)
{
int Val ;
Val = addition();
printf(“val = %d”, Val);
}
int addition()
{
float tmp;
tmp = calcule(2.5,3) + calcule(5,7.2);
return (int)tmp;
}
51
Passage des paramètres par valeur
52
Passage des paramètres par valeur
#include <stdio.h>
void main(void)
{
int var = 5;
change(var); change:
change:vv==500
500
main:
main:var
var==55
printf("main: var = %d\n", var);
}
void change(int v)
{
v *= 100;
printf("change: v = %d\n", v);
}
53
FONCTION RENVOYANT UNE VALEUR AU
PROGRAMME
#include <stdio.h>
void main(void){
int var = 5;
int valeur;
valeur = change(var);
change:
change:vv==
printf("main: var = %d\n", var); main:
printf("main: valeur = %d\n", valeur);
main:var
var==
main:
main:valeur
valeur==
}
int change(int v)
{
v *= 100;
printf("change: v = %d\n", v);
return (v+1);
}
54
Une fonction se termine et « rend la main » au code appelant lorsque son
exécution rencontre l’instruction : return expression; ou return;
#include <stdio.h>
void main(void){
int var = 5;
int valeur;
valeur = return_Val(var);
return_Val
return_Val::rien
rien
printf("main: var = %d\n", var); main:
printf("main: valeur = %d\n", valeur);
main:var
var==
main:
main:valeur
valeur==
}
int return_Val(int v)
{
if (v == 10) return (2*v);
else return (3*v);
}
55
int max (int a, int b) {
if (a > b) return a ;
else return b ;
}
int min (int a, int b) {
if (a < b) return a ;
else return b ;
}
int difference (int a, int b, int c) {
return (max (a, max(b,c)) - min (a, min (b, c))) ;
}
void main ()
{
printf ("%d", difference (10, 4, 7)) ;
}
56
Une fonction est dite récursive, dès lors ou elle se fait appel pour
calculer une sous partie de la valeur finale qu'elle retournera.
#include <stdio.h>
int fact(int n);
int return_Val(int v);
void main(void){
int var = 5, int valeur;
valeur = return_Val(var);
printf("main: var = %d\n", var);
printf("main: valeur = %d\n", valeur); return_Val
return_Val::rien
rien
} main:
main:var
var==
main:
main:valeur
valeur==
int fact(int n) {
return (n<2?1:((int)n*fact(n-1));
}
(0)=0*fact(-1)
int return_Val(int v)
{ int temp=1;
if (v == 10) return (2*v); while(n>1) temp*=n--;
else return fact(v);
}
57
L’opérateur ternaire “?:”
return(n<2?1:((int)n*fact(n-1));
if (n<2 ) {
return 1;
} return(n<2?1:((int)n*fact(n-1));
else {
return ((int)n*fact(n-1));
}
58
int fact( int n) {
if (n < 1) return 1;
ti é
else return ( n * fact(n-1) );
}
u
int c ;
é c …
if (n == 1) move(a,b);
a R else {
hanoi(n-1, a, c);
59
Passer des tableaux aux fonctions
Les tableaux peuvent être passés comme paramètres d'une fonction.
Ils ne peuvent pas être retournés comme résultat d'une fonction. !
La longueur du tableau ne doit pas être définie à la déclaration de la fonction.
Un tableau peut être modifié dans une fonction. Il est passé par référence
(adresse) et non par valeur.
#include
#include<stdio.h>
<stdio.h>
void
void somme(int
somme(intx[], x[],int
intn);
n); p avant somme p après somme
void
void main(void){
main(void){
int
inti;i; 1 1
int
intp[6]
p[6]=={{1,1,2,3,
2,3,5,5,7,7,11
11};};
somme(p, 2 3
somme(p,6); 6);
for
for(i=0;i<6;i++)
(i=0;i<6;i++) 3 5
printf("%d
printf("%d",",p[i]);p[i]);
}} 5 8
7 12
void
void somme(int
somme(inta[],a[],int
intn){
n){ 11 18
int
int i;i;
for(i
for(i==n-1;
n-1;i i>0
>0;;i--)
i--)
a[i]
a[i]+=
+=a[i-1];
a[i-1];
}}
60
Exemple: transposition d'une matrice
void transpose ( float a[][20], int m, int n);
void main(void)
{float matrice [100][20]; /* matrice (100,20) */
/*…*/
transpose (matrice, 3, 2);
}
A- Saisie et affichage
B- Moyenne
C- Suppression du Max et affichage
D- Suppression du Min et affichage
E- Ajout d’un entier à une position donnée
Q- Quitter
62
Le point A sera traité par deux fonctions :
Saisie : la saisie au clavier des entiers et leur rangement dans le tableau.
Dans cette fonction on demandera le nombre d’éléments (NE<= Nmax)à
saisire.
Affichage : affichage des données.
char
char last_name[6]
last_name[6] ="Minor";
="Minor"; 'M' 'i' 'n' 'o' 'r' 0
char
char other[]
other[] =="Tony
"TonyBloot";
Bloot";
'T' 'o' 'n' 'y' 32 'B' 'l' ‘o' ‘o' 't' 0
char
char characters[7]
characters[7]=="No
"Nonull";
null"; 'N' 'o' 32 'n' 'u' 'l' 'l'
Pas de ‘\0’
64
Entrées/Sorties Standards
• getchar() : lire un caractère sur entrée standard (valeur -1 = EOF = fin)
• putchar() : écrire un caractère sur sortie standard
main(){
char c; main(){
c = getchar(); char c;
while (c != EOF) { while ( (c=getchar())!= EOF)
putchar(c); putchar(c);
c = getchar(); }
}
}
• Fichiers stdin et stdout: Tout programme lit ou écrit sur ces fichiers (défaut clavier et écran).
65
Affichage à l'écran des strings
Soit caractère par caractère, avec le format “%c” ou putchar,
ou, plus simplement, avec le format “%s” ou puts .
int i = 0;
last_name[3] = ‘\0’; Min
}
while(last_name[i] != '\0') printf("%s\n", last_name);
printf("%c", last_name[i++]); puts(last_name);
printf("\n");
66
Saisie des strings
char texte[30];
printf("ENTRER UN TEXTE: ");
scanf("%s", texte); //est équivalent à gets(texte);
67
RQ:
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.
Pour saisir une chaîne de type "il fait beau", il faut utiliser gets.
#include <stdio.h>
#include <string.h>
Affectation de strings :
Les strings peuvent être void main(void) {
initialisés avec “=”,
char who[] = "Tony Bloot";
mais pas affectés avec “=”
(ce sont des tableaux!) who = "John Minor";
strcpy(who, "John Minor");
}
68
Fonctions permettant la manipulation des chaînes
string.h ou stdlib.h
void main(void)
{
int L,i=0;
char s[9] = "midi", u[11] = "avant", v[10] = "soir";
char text[80]; text[i] = getchar();
while ( text[i] != EOL ) {
While ( (text[i] = getchar() ) != EOL ) i++; i++;
text[i] = getchar();
puts(text);
}
L = strlen(s); /* L = 4 */
for (i=0;i<L;i++) {
putchar(toupper(s[i])); /* M, I, D,I */
}
71
Les Pointeurs en C
La déclaration de pointeurs
Valeurs pointées et adresses
Passage de paramètres de fonction par référence
Pointeurs et tableaux
72
Les pointeurs, c'est quoi?
Un pointeur est une variable particulière, dont la
valeur est l'adresse d'une autre variable.
Pointeur p: valeur 5A0F3 (adresse hexadécimale)
Adresse 5A0F3: valeur 17 (correspondant à la
valeur d'un entier i)
En accédant à cette adresse, on peut accéder indirectement à la variable et donc la modifier.
i=17
5A0F3 17
p=5A0F3 p i
Un pointeur est une adresse mémoire. On dit que le
pointeur p pointe vers i, puisque p pointe vers
l’emplacement mémoire où est enregistrée i.
73
Les pointeurs: pourquoi ?
Les pointeurs sont nécessaires pour:
74
Déclaration de Pointeurs
Le symbole * est utilisé entre le type et le nom du pointeur
Déclaration d’un entier: int i;i;
int
Déclaration d’un pointeur vers un entier: int
int *p;
*p;
Exemples de déclarations de pointeurs
int
int*pi;
*pi; /*/* pipiest
estun
unpointeur
pointeurvers
versun
unint
int
*pi
*pidésigne
désignelelecontenu
contenude
del'adresse
l'adresse*/*/
float
float*pf;
*pf; /*/*pfpfest
estun
unpointeur
pointeurvers
versun
unfloat
float*/*/
char
charc,c,d,d,*pc;
*pc; /*/*ccetetddsont
sontdes
deschar*/
char*/
/*/*pc
pcest
estununpointeur
pointeurvers
versun
unchar
char*/*/
double
double*pd,
*pd,e,e,f;f; /*/*pd
pdest
estununpointeur
pointeurvers
versun
undouble*/
double*/
/*/*eeetetffsont
sontdes
desdoubles
doubles*/*/
double
double**tab;
**tab; /*/*tab tabest
estununpointeur
pointeurpointant
pointantsur
surun
unpointeur
pointeurqui
qui
pointe
pointesur
surununflottant
flottantdouble
double*/*/
75
Opérateurs unaires pour manipuler les pointeurs,
& (adresse de) et * (contenu)
Exemple: int i = 8;
printf("VOICI i: %d\n",i);
printf("VOICI SON ADRESSE EN HEXADECIMAL: %p\n",&i);
nom_de_Pointeur = &nom_de_variable
void main(void) cp.
s u r c
{ inte
c p o 0x1132 'a'
char c = 'a', d = 'z'; d on
e c ; 0x1132
char *p; d
r es se p
it l 'ad d
r eço 0x91A2 'z'
*p = c; 0x91A2
p = &c;
printf("%c\n", *p);
p = &d; L’opérateur * (“valeur pointée par”)
printf("%c\n", *p);
} aa
zz
76
#include <stdio.h>
void main() {
int *p, x, y;
p = &x; /* p pointe sur x */
x = 10; /* x vaut 10 */
y = *p - 1; printf(" y= *p - 1 =? = %d\n" , y); y vaut ?
*p += 1; printf(" *p += 1 =? *p = x= ? = %d %d\n" , *p, x); x vaut ?
(*p)++; printf(" (*p)++ =? *p = x= ? = %d %d alors y=%d \n" , *p, x,
y);
incrémente aussi de 1 la variable pointée par p, donc x vaut ??.
y vaut 9
78
* et ++
*p++ signifie:
*p++ trouver la valeur pointée
*p++ passer à l’adresse suivante !
(*p)++ signifie:
(*p)++ trouver la valeur pointée
(*p)++ incrémenter cette valeur (sans
changer le pointeur)
*++p signifie:
*++p incrémenter d’abord le pointeur
*++p trouver la valeur pointée
79
Passage des paramètres par valeur et par adresse
Syntaxe qui conduit à une erreur: Syntaxe correcte:
a et b:
#include <stdio.h> variables #include <stdio.h>
locales à
void ech(int x,int y) void ech(int *x,int *y)
{ main(). La {
int tampon; fonction ech int tampon;
tampon = x; ne peut donc tampon = *x;
x = y; pas modifier *x = *y;
y = tampon; leur valeur. *y = tampon;
} On le fait }
donc en
void main() void main()
{
passant par {
int a = 5 , b = 8; l'adresse de int a = 5 , b = 8 ;
ech(a,b); ces variables. ech(&a,&b);
printf(“ a=%d\n ”, a) ; a = ? printf(“ a=%d\n ”, a) ; a=?
printf(“ b=%d\n ”, b) ;
b=?
printf(“ b=%d\n ”, b) ; b=?
} }
PASSAGE DES PARAMETRES PASSAGE DES PARAMETRES
PAR VALEUR PAR ADRESSE
80
Passage de paramètres de fonction
par référence ou adresse
Quand on veut modifier la valeur d'un paramètre dans une
fonction, il faut passer ce paramètre par référence ou adresse
81
Appel des fonctions par référence
#include
#include<stdio.h>
<stdio.h>
void
void change(int*
change(int*p);p);
void
void main(void)
main(void)
{{
int
intvar
var==5;5;
change(&var);
change(&var);
printf("main:
printf("main:varvar==%d\n",var);
}}
%d\n",var); !
void
void change(int*
change(int*p)
p)
{{
*p
*p*=
*=100;
100;
printf("change:
printf("change:*p
*p==%d\n",*p);
%d\n",*p);
}}
change:
change:*p
*p==500
500
main:
main:var
var==500
500
82
#include <stdio.h>
void somme(int , int , int *);
int modif(int , int *, int *);
void main(){
int a, b, c;
a = 2; b = 8;
somme(a, b, &c);
Somme de a=? et b=? : ?
printf("Somme de a=%d et b=%d : %d\n",a, b, c);
a = modif(a, &b, &c);
printf(" Modif : a=%d , b=%d et c= %d\n",a, b, c);
}
Modif : a=?, b=? et c= ?
void somme(int x, int y, int *z){
*z = x + y;
}
int modif(int x, int *y, int *z){
x *= 2; *y= x+ *y; *z= 5;
return x;
} 83
Identification des tableaux et pointeurs
En C, le nom d’un tableau représente l’adresse de sa
composante 0, donc a == &a[0]
C'est pour cela que les tableaux passés comme paramètres
dans une fonction sont modifiables
85
Utiliser des pointeurs - exemple
#include <stdio.h>
long sum(long*, int);
Tab Tab
int main(void)
1 1000 1
{
long Tab[6] = { 1, 2, 2 1004 2
3, 5, 7, 11 };
3 1008 3
printf("%ld\n", sum(Tab, 6));
5 1012 5
return 0;
} 7 1016 7
long sum(long *p, int sz) 11 1020 11
{
long *end = p + sz; 1024
long total = 0;
p
while(p < end) 1000
total += *p++; end 1024
return total;
}
86
Quelle notation?
A[0] est équivalent à *A
A[i] est équivalent à *(A + i)
&A[0] est équivalent à A
short
short a[8]
a[8]=={{10,
10,20,
20,30,
30,40,
40,50,
50,60,
60,70,
70,80
80};};
short
short *p
*p==a;
a;
printf("%d\n",
printf("%d\n",a[3]);
a[3]); 40
40
printf("%d\n",
printf("%d\n",*(a
*(a++3));
3)); 40
40
printf("%d\n",
printf("%d\n",*(p
*(p++3));
3)); 40
40
printf("%d\n",
printf("%d\n",p[3]);
p[3]); 40
40
p a
1000 10 20 30 40 50 60 70 80
1000 1004 1008 1012
1002 1006 1010 1014
87
SCANF
Pour saisir un caractère ou un nombre
char c;
float Tab[10], X[5][7]; // *Tab,(*X)[7]
printf("TAPER UNE LETTRE: ");
scanf("%c",&c);
scanf("%f",&Tab[5]);
pointeur
char *adr;
printf("TAPER UNE LETTRE: ");
scanf("%c",adr);
adr1 = (float*)malloc(4*sizeof(float));
La réservation d'espace est à la adr2 = (float*)malloc(10*sizeof(float));
charge du programmeur qui doit texte = (char*)malloc(10);
le faire de façon explicite, en
utilisant les fonctions standard *adr1 = -37.28;
*adr2 = 123.67;
malloc(), … qui sont
printf("adr1 = %p adr2 = %p r1 = %f
prototypées dans <stdlib.h> et r2 = %f\
<alloc.h> n",adr1,adr2,*adr1,*adr2);
free(adr1); // Libération de la mémoire
free(adr2);
free(texte);
} 89
sizeof
void main()
{
int i;
char c;
caractère : 1
float f;
entier : 2 ou 4
double d;
réel : 4
printf (‘’caractère : %d \n ‘’, sizeof c);
double : 8
printf (‘’entier : %d \n ‘’, sizeof i);
printf (‘’réel : %d \n ‘’, sizeof f);
printf (‘’double : %d \n ‘’, sizeof d);
}
90
EXP : Création d’un tableau de taille quelconque
void main(){
int i , dim; // compteur et taille du tableau
long* tableau; // pointeur pour stocker l’adresse du tableau
91
La mémoire dynamique varie en cours d'exécution, et peut n'être pas
suffisante pour allouer les variables, provoquant le plantage du programme.
Il faut donc tester le retour des fonctions d'allocation et traiter les erreurs.
Exemple:
Valable pour réserver de l'espace pour les autres types de données int, float, …
Elles retournent le pointeur NULL (0) si l'espace disponible est insuffisant.
93
Structures en C
Concepts
Créer un type de structure
Créer une instance de structure
Initialiser une instance
Accéder aux membres d’une instance
Passer les structures comme paramètres
Listes chaînées
94
Concepts
Une structure est une collection de plusieurs variables (champs) groupées
ensemble pour un traitement commode
Les variables d’une structure sont appelées membres et peuvent être de
n’importe quel type, par exemple des tableaux, des pointeurs ou d’autres
structures
struct
structMembre
Membre
{{
char
char nom[80];
nom[80];
char
char adresse[200];
adresse[200];
int
int *numero;
*numero;
float
float amende[10];
amende[10];
Les étapes sont: };};
déclarer le type de la structure
utiliser ce type pour créer autant d’instances que
désirées
Accéder les membres des instances
95
Déclarer les structures
Les structures sont définies en utilisant
le mot-clé struct struct Membre
struct Membre
struct
structDate
Date {{
char nom[80];
{{ char
char
nom[80];
adresse[200];
char adresse[200];
int
int jour;
jour; int
int numero;
numero;
int
int mois;
mois; float
float amende[10];
amende[10];
! int struct
struct Date emprunt;
int an;
an; struct
Date
struct Date
Date
emprunt;
creation;
creation;
};}; };};
struct
structLivre
Livre
{{ struct
structPret
Pret
char
char titre[80];
titre[80];
{{
struct Livre
struct Livre b;b;
char
char auteur[80];
auteur[80]; struct
struct Date
Date due;
due;
struct
struct Membre
Membre *who;
*who;
float
float prix;
prix; };};
};};
96
Déclarer des instances
Une fois la structure définie, les
instances peuvent être déclarées
Par abus de langage, on appellera
structure une instance de structure
struct
structDate
Date
{{
int
int jour;
jour;
int
int mois;
mois;
int
int an;
an;
}}hier, Déclaration
hier,demain;
demain; avant ‘;’ .
struct
structDate
Datepaques;
paques;
struct
structDate semaine[7]
Datesemaine [7];;
Initialisation .
struct
structDate
Datenouvel_an
nouvel_an=={{1,1,1,1,2001
2001};};
97
Des structures dans des structures
struct
structDate
Date
{{
int
int jour;
jour;
int
int mois;
mois; struct
structMembre
Membre
int
int an;an; {{
};};
char
char nom[80];
nom[80];
char
char adresse[200];
adresse[200];
int
int numero;
numero;
float
float amende[10];
amende[10];
struct
struct Date
Date emprunt;
emprunt;
struct
struct Date
Date creation;
creation;
};};
struct
structMembre
Membre mm=={{
"Arthur
"ArthurDupont",
Dupont",
”rue
”rue de Houdain,9,9,7000
de Houdain, 7000Mons",
Mons",
42,
42,
{{0.0
0.0},},
{{0,0,0,0,00},},
{{5,5, 2,2,2001
2001}}
};};
98
Accéder aux membres d’une
structure
Les membres sont accédés par le nom de l’instance,
suivi de . , suivi du nom du membre
struct
structMembre
Membre m;
m;
printf("nom = %s\n", m.nom);
printf(”numéro de membre = %d\n", m.numero);
printf(”amendes: ");
for(i = 0; (i < 10) && (m.amende[i] > 0.0); i++)
printf("%.2f Euros", m.amende[i]);
99
Différence entre tableaux et
structures
. Arrays Structures
Nom pointeur La structure
élément 0
100
Assignation des structures
struct
structMembre
Membretemp;
temp;
temp
temp==m;
m;
101
Passer des structures comme
paramètres de fonction
Une structure peut être passée, comme une autre
variable, par valeur ou par adresse
Passer par valeur n’est pas toujours efficace
(recopiage à l’entrée)
Passer par adresse ne nécessite pas de recopiage
void
void Par_valeur(struct
Par_valeur(struct Membre
Membre m);
m);
void
void Par_reference(struct
Par_reference(struct Membre
Membre *m);
*m);
Par_valeur(m);
Par_valeur(m);
Par_reference(&m);
Par_reference(&m);
102
Quand la structure est un pointeur !
Utiliser p->name
L’écriture p->name est synonyme de (*p)->name,
! où p est un pointeur vers une structure
void
void affiche_membre
affiche_membre(struct
(structMembre
Membre*p) *p)
{{
printf("nom
printf("nom==%s\n",
%s\n",p->nom);
p->nom);
printf("adresse
printf("adresse==%s\n",
%s\n",p->adresse);
p->adresse);
printf(”numéro
printf(”numérodedemembre
membre==%d\n",
%d\n",p->numero);
p->numero);
printf("\nDate
printf("\nDated’affiliation
d’affiliation%d/%d/%d\n",
%d/%d/%d\n",
p->creation.jour,
p->creation.jour,p->creation.mois,
p->creation.mois,p->creation.an);
p->creation.an);
}}
103
Retour de structures dans une fonction
struct
structComplex
Complex add(struct
add(structComplex
Complexa,a,struct
structComplex
Complexb)
b)
{{
struct
structComplex
Complex result
result==a;a;
result.real_part
result.real_part +=
+=b.real_part;
b.real_part;
result.imag_part += b.imag_part;
result.imag_part += b.imag_part;
return
returnresult;
result;
}}
struct
structComplex
Complex c1
c1=={{1.0,
1.0,1.1
1.1};};
struct
structComplex
Complex c2
c2=={{2.0,
2.0,2.1
2.1};};
struct
structComplex
Complex c3;
c3;
c3
c3==add(c1,
add(c1,c2);
c2); /*/*c3
c3==c1
c1++c2
c2*/*/
104
TP
Enoncé
Ecrire un programme permettant de :
struct {
char nom_pren[40]; // nom+pren
char nom[20];
char pren[20];
int NH[NM_max] ; // NM_max=3 : nbre d’heures pr NM_max matières
}
1- Saisie et affichage
2- Construction et affichage
3- Modifier et affichage
4- Tri et affichage
5- Quitter
105
Tri à bulles
while(???){
for j = 0 to …. {
if tab[j] > tab[j+1] {
<on échange tab[j] et tab[j+1]>
}
} 0 1 2 3 4 5 6 j
tab[j]
} 2 6 4 8 12 13 0
6 2
6 4 2 tab[j] < tab[j+1]
6 4 8 2
6 4 8 12 2 ……
13 12 8 6 4 2 0 6 4 8 12 13 2 0
106
Gestion des fichiers en C
Elle est assurée par la librairie standard <stdio.h> via un
ensemble de fonctions commençant par “f”
Avant de manipuler un fichier, il faut lui associer un
descripteur (pointeur vers la structure fichier)
Il y a 3 descripteurs automatiquement ouvert par tout
programme C, stdin, stdout et stderr
stdin (standard input) est connecté au clavier. On peut y
lire
stdout (standard output) et stderr (standard error) sont
reliés au moniteur. On peut y écrire.
!
FILE *f;
/*déclare un descripteur f de fichier*/
107
Ouvrir et fermer des fichiers
Les fichiers sont ouverts avec la fonction fopen
ils sont fermés avec la fonction fclose
FILE*
FILE*fopen(const
fopen(constchar*
char*name,
name,constconstchar*
char*mode);
mode);
int
intfclose
fclose(FILE
(FILE*f);
*f); #include <stdio.h>
#include <stdio.h>
void
voidmain(void)
main(void)
{{
FILE*
FILE* in;
in;
FILE*
FILE* out;
out;
FILE*
FILE* append;
append;
in
in==fopen("autoexec.bat",
fopen("autoexec.bat","r");
"r");
out
out==fopen("autoexec.bak",
fopen("autoexec.bak","w");
"w");
append
append==fopen("config.sys",
fopen("config.sys","a");
"a");
/*/*…
…*/*/
fclose(in);
fclose(in);
fclose(out);
fclose(out);
fclose(append);
fclose(append);
}}
108
Lecture et écriture sur fichier
Fonctions de lecture
int
int fscanf(FILE*
fscanf(FILE*stream,
stream,const
constchar*
char*format,
format,...);
...);
int
int fgetc(FILE*
fgetc(FILE*stream);
stream);
char*
char* fgets(char*
fgets(char*buffer,
buffer,int
intsize,
size,FILE*
FILE*stream);
stream);
Fonctions d’écriture
int
int fprintf(FILE*
fprintf(FILE*stream,
stream,const
constchar*
char*format,
format,...);
...);
int
int fputc(int
fputc(intch,
ch,FILE*
FILE*stream);
stream);
int
int fputs(const
fputs(constchar*
char*buffer,
buffer,FILE*
FILE*stream);
stream);
int feof(FILE *f); /*renvoie une valeur non nulle si fin de fichier*/
109
Exemple d’écriture (lecture) de fichier
#include <stdio.h> #include <stdio.h>
void sauvegarde( char titre[], int n, void main(void)
float x[], int ind [] ) {
char titre[81];
{
float x[10];
int i=0; int ind[10], i=0;
FILE *f; FILE *f;
f = fopen(“monfichier.dat”,”w”); f = fopen(“monfichier.dat”,”r”);
if (f !=NULL){ if (f!= NULL) {
fprintf(f,”%s\n”,titre); fgets(titre,80,f);
for (i=0; i < n; i++ ) { while(!feof(f)) {
fprintf(f,”%f %d\n”, x[i],ind[i]); fscanf(f,”%f %d”,&x[i],&ind[i]);
i++;
} Mon titre }
} }
3.0 1
fclose(f); fclose(f);
} 4.5 2
}
7.3 3
La constante NULL (définie comme 0 dans stdio.h) réfère à une adresse non définie
110
Compilation Séparée et édition de Lien
Cas I Cas II
111
Structure d'un programme C
#include <stdio.h>
#define DEBUT -10 Directives du préprocesseur :
#define FIN 10 accès avant la compilation
#define MSG "Programme de démonstration\n"
int fonc1(int x);
int fonc2(int x); Déclaration des fonctions
void main()
{ /* début du bloc de la fonction main*/
int i; /* définition des variables locales */
Programme
i=0; principal
fonc1(i) ;
fonc2(i) ;
} /* fin du bloc de la fonction main */
int fonc1(int x) {
return x; Définitions des
}
fonctions
int fonc2(int x) {
return (x * x);
}
112
Structure d'un programme C
#include <stdio.h>
#define DEBUT -10
#define FIN 10
#define MSG "Programme de démonstration\n" Fichier.h
int fonc1(int x);
int fonc2(int x);
#include ‘’Fichier.h’’
void main()
{ /* début du bloc de la fonction main*/
int i; /* définition des variables locales */
Programme
i=0; principal
fonc1(i) ;
fonc2(i) ;
} /* fin du bloc de la fonction main */
int fonc1(int x) {
return x; Définitions des
}
fonctions
int fonc2(int x) {
return (x * x);
}
113
MANIPULATION DES FICHIERS
#include "module.h"
extern int a;
int a = 0;
void fct();
void fct() { a++; }
Fichier "main.c"
#include <stdio.h>
#include "module.h"
void main(void) {
fct();
a++;
printf("%d\n",a); // Résultat affiché : 2
}
115
Directives de compilation
116
Exemple :
#ifndef (BOOL)
#define BOOL char /* type boolean */
#endif
#ifdef (BOOL)
BOOL FALSE = 0; /* type boolean */
BOOL TRUE = 1; /* définis comme des variables */
#else
#define FALSE 0 /* définis comme des macros */
#define TRUE 1
#endif Utile pour les fichiers include.
#ifndef _STDIO_H_
#define _STDIO_H_
texte a compiler une fois
…
#endif
117
Listes chaînées
Une liste est une structure de données constituée de cellules
chaînées les unes aux autres par pointeurs.
Une liste simplement chaînée : une cellule est un
enregistrement qui peut être déclarée comme suit:
struct
structNode
Node{{
int
int data;
data; /*/*les
lesinformations
informations*/*/
struct
structNode
Node *next;
*next; /*/*lelelien
lien*/*/
};};
return
returnp;
p;
}}
119
Nouvelle cellule dans une liste chaînée vide
cellule
cellule*debut;
*debut; Denis\0
debut
debut==(cellule
(cellule*)
*)malloc
malloc(sizeof(cellule));
(sizeof(cellule)); NULL
strcpy
strcpy((debut->name,
debut->name,“Denis”);
“Denis”); debut
debut->next
debut->next==NULL;NULL;
Le début de la liste est indiqué par un pointeur indépendant (debut) et la fin par NULL
debut
prec 120
Nouvelle cellule après la
cellule prec
cellule
cellule*p;
*p;
pp==(cellule
(cellule*)
*)malloc
malloc(sizeof(cellule));
(sizeof(cellule));
strcpy
strcpy((p->name,
p->name,“Alfred”);
“Alfred”);
p->next
p->next==prec->next;
OK?
prec->next;
prec->next
prec->next==p; p;
Alfred
p Denis
Claire
Claire Denis
NULL
debut NULL
prec
debut
121
Parcourir une liste
void
voidparcours
parcours(struct
(structNode
Node*debut)
*debut) debut est un pointeur sur
{{ la cellule qui contient le
struct
structNode
Node*p;*p; premier élément de la
pp==debut;
debut;
while liste
while((pp!=
!=NULL)
NULL){{
printf
printf(“%s\n”,
(“%s\n”,p->name);
p->name); Liste identifier par l'adresse
pp==p->next;
p->next; de sa première cellule
}}
}}
Alfred Denis
Claire
NULL
debut
122
void liberation(liste L){
if (L) {
liste temp = L-
>suivant;
free(L);
liberation(temp);
}
}
123
Exemple
LIFO
Last-In-First-Out
• Le dernier élément ajouté dans la
liste, est le premier à en sortir.
• Opérations:
Créer la pile,
Ajouter un élément (Push),
Effacer un élément (Pop), Eliminer la
pile .
124
PUSH procédure
Push(5) 7 3 9 5
Push(9)
NULL
Push(3)
Top Top Top Top
Push(7)
125
POP procédure
Pop(7) 7 3 9 5
Pop(3)
Underflow risk NULL
Pop(9)
si
Top
la pile
Top
Top
est
Top
Top
vide !!!
Top
Top
Pop(5)
126
Simulation de la factorielle
5! = ??
5! = 5*4!
4! = 4*3!
3! = 3*2!
2! = 2*1!
1! = 1*0! 0
0! = 1 1
2
3
4
5
127
Simulation de la factorielle
5! = ??
5! = 5*4! 0! = 1
4! = 4*3! 1! = 1 *1 = 1
3! = 3*2! 2! = 2 *1 = 2
2! = 2*1! 3! = 3 *2 = 6
1! = 1*0! 4! = 4 *6 = 24 0
0! = 1 5! = 5 *24 = 120 1
2
3
4
5
128
TP3
Créer une liste simplement chaînée dont chaque cellule contient les champs
suivants :
{
int data; /* les informations */
struct Node *next; /* le lien : pointeur sur la cellule suivante */
}
129
1 : Crée une liste en insérant 2n, puis 2n-2, puis 2n-4, … et enfin 0 qui sera
en tête de la liste. (Liste : 0,2,4,6,8,10, …2n.)
Push(6) 0 2 4 6
Push(4)
NULL
Push(2)
debut Top Top Top
Push(0)
2 : Sauvegarde la liste dans le fichier Liste1
3 : Insère dans la liste –1, puis 1, puis 3, … et en fin 2n-1.
(Liste finale : -1,0,1,2,3,4,5,6,7,8,9,…2n)
2’ : Sauvegarde la nouvelle liste dans le fichier Liste2
4 : Libère la mémoire avant de quitter le programme.
130
Listes doublement chaînées
struct
structNode
Node{{
int
int data;
data; /*/*les
lesinformations
informations*/*/
struct data prev next
structNode
Node *prev;
*prev; /*/*lien
lienvers
versleleprécédent
précédent*/*/
struct
structNode
Node *next;
*next; /*/*lien
lienvers
verslelesuivant
suivant*/*/
};};
131
debut->prev = NULL;
data prev next
debut->next = fin;
fin->prev = debut;
fin->next = NULL;
NULL NULL
debut fin
132
Insérer un élément en fin de liste
fin->next = act;
data prev next
act->prev = fin;
act->next = NULL;
fin = act;
NULL NULL
debut fin
NULL NULL
act fin
debut
133
Insérer un élément dans la liste pos=qlq
Cell *tmp;
data prev next
tmp = (Cell *) malloc(dim);
tmp->prev = act->prev ;
act->prev->next = tmp;
tmp->next = act;
act->prev = tmp;
tmp
NULL NULL
act
debut fin
134
tmp
NULL NULL
debut fin
NULL NULL
fin
debut
135
typedef struct noeud {
Arbre binaire int donnee;
struct noeud *gauche;
struct noeud *droite;
}
136