Types de données et représentation
Langage C
B. Rouzeyre, Polytech'ERII
1. Action de base 2. Séquencement
3. Bloc et niveau de détail
Représentation des algorithmes
Organigramme : façon graphique de représenter le déroulement d'un calcul
Action 1
Action 1 Action 2
Action 12 Action 11 Action 1
Action 2
4. Sélection
Organigramme
Non structuré
Action 23 Action 22 Action 21 Action 1
Action 3
Action 23 Action 22
Action 21
Action 1
Action 3 Critère ?
Ev.1
Ev.3 Ev.2
Ev.1 Ev.2 Ev.3
Σ Evi = 1 et Evi.Evj = 0
Structuré
Se lit de haut en bas et de gauche à droite Se lit en suivant les fils
4. Cas particulier : alternative
Organigramme
Non structuré
Action 22 Action 21 Action 1
Action 3
Action 22 Action 21
Action 1
Action 3 Critère ?
Vrai
Faux Vrai Faux
Structuré
4. Cas particulier : alternative sans action
Organigramme
Non structuré
Action 21 Action 1
Action 3
Action 21
Action 1
Action 3 Critère ?
Vrai
Faux Vrai Faux
Structuré
5. Itérations : exprime le fait que l'on répète une action
Organigramme
Action 2 Action 1
Action 3
Action 3 Action 2
Action 1
Critère
5.1 "Tant que"
Vrai Faux
1 – On évalue le critère
2 – s'il est vrai on effectue l'action 2, retour en 1 2 bis – s'il est faux on passe à la suite
Remarque : éventuellement l'action 2 n'est pas exécutée
5. Itérations :
Organigramme
Action 2 Action 1
Action 3
Action 3 Action 2
Action 1
Critère
5.2 "Jusqu'à ce que"
Faux Vrai
1 – On exécute l'action 2 2 – s'il est faux, retour en 1
2 bis – s'il est vrai, on passe à la suite
Remarque : l'action 2 est exécutée au moins une fois
5. Itérations :
Organigramme
Action 2 Action 1
Action 3
5.3 "Pour tout e ε E"
l'action 2 est exécutée autant de fois qu'il y a d'éléments dans E.
Remarque : si E est vide, Action 2 n'est pas exécutée.
Action 3 Action 2
Action 1
e ε E ?
Vrai Faux
e <- valeur suivante de E
-utiliser que les primitives précédentes -intérêt : traduction (presque) directe en C -ne pas faire de spaghetti :
- traduction difficile - debug impossible - résultat incompréhensible - => 0 à l'examen
Organigramme : conseil
Action 3 Action 2
Action 1
e ε E ?
Vrai Faux
e <- valeur suivante de E
Organigramme : exemple
Imprimer S S=0
x pair ?
x=
suivant(x)
x = premier
x dernier ?
S=0 x = premier
Imprimer S S = S+ x
Vrai Faux
fin = v
x= suivant(x) fin = faux
S = S+ x
KO OK
• Les actions ou "instructions" en langage C ne sont en fait que des opérations élémentaires (+,-, * etc…) sur des données unitaires.
• Chaque instruction est suivie d'un ;
• Le début d'un bloc est signalé par un { , la fin d'un bloc par }. Un bloc devient l'équivalent syntaxique d'une instruction.
• Ex :
Codage d'un algorithme en C
Calcul
x = 1 y = 2
imprimer z z = x+y
{
x=1;
y=2;
z=x+y;
printf("%d",z);
} ;
optionnel
Alternative
if (expression) action1 ; else action2 ;
Codage d'un algorithme en C
"problème"
calcul
Imprimer z
Vrai
Faux
"calcul juste"
z = z+10
…
if (z == 3) {
printf("calcul juste");
z=z+10;
} ;
else printf ("problème");
printf ("%d",z);
…
fin de l'instruction if
Cas particuliers de alternative
Codage d'un algorithme en C
…
if (z == 3) ;
else printf("problème);
printf ("%d",z);
…
"problème"
calcul
Imprimer z
Vrai
Faux
Cas particuliers de alternative
Codage d'un algorithme en C
calcul
Imprimer z
Vrai
Faux
"calcul juste"
z = z+10
…
if (z == 3) {
printf("calcul juste");
z=z+10;
} ; else;
printf ("%d",z);
…
ou bien
…
if (z == 3) {
printf("calcul juste");
z=z+10;
};
printf ("%d",z);
…
Sélection multiple : en C, la sélection ne peut être qu'une comparaison à des valeurs de constante entière ou caractère (si besoin passer à plusieurs if imbriqués)
Codage d'un algorithme en C
…
switch (z) {
case 3 : printf("ok"); break;
case 4 : printf("PB1"); break;
default : "printf ("PB2");
};
…
"PB2"
"PB1"
"ok"
Action 1
Action 3
z=3
autres z=4
Structures itératives. Exemple, on veut imprimer tous les nombres de 1 à 10 TANT QUE : while (condition) action;
Codage d'un algorithme en C
x=1;
while (x <=10) {
printf("%d\n",x);
x=x+1;
};
…
x=1
imprimer x x=x+1
x=1
imprimer x x=x+1
x=1;
do {
printf("%d\n",x);
x=x+1;
}
while (x <= 11);
…
JUSQU'À CE QUE : do action while (condition);
POUR
Codage d'un algorithme en C
for(x=1; x≤10; x=x+1) printf("%d\n",x);
imprimer x
équivalent TANT QUE
x=1;
while (x <=10) {
printf("%d\n",x);
x=x+1;
};
…
x=1
imprimer x x=x+1
Compilateurs
• Sur le web
– ideone.com (pour le début)
• En TP
– Visual C++
Types de données
• 3 types de base
caractères
ex : 'a', '1', '\n'
entier relatifs
ex : 0 , -12, 328
réel
3.14, 2.3 e+4
• Remarques :
Pas de booléen (vrai, faux)
Pas de type chaînes de caractères prédéfini
Type caractère
• Caractère : Symboles alphanumériques (a,z,!,1,9) + caractères spéciaux (retour à la ligne, beep, etc..)
• Un caractère est représenté sur un octet (8 bits) suivant la table ASCII (American Standard Code for Information Interchange)
• ex : 'a' = 9710 = 6116 = 0110 00012
• Table ASCII
ex : code ASCII du 'A' = 65 'A'<'B'<……..< 'Z'
'0'<'1'<'2'<…..<'9' 'a'<'b'<……….<'z'
• Déclaration de variable de type caractère
char c;
c = 'a';
• Constante de type caractère
#define caractère_a 'a'
Table ASCII
• Remarques :
les chiffres sont codés suivant un ordre croissant (48 à 57) idem pour les lettres (65 à 90, 97 à 122)
code des majuscules est inférieur au code des majuscules (différence constante = 32)
les codes supérieurs à 128 dépendent de la langue : é, ö , ä, æ, œ etc…
• Déclaration d'une variable caractère :
char c;
c='a';
…..
Type caractère
• Caractères spéciaux (retour à la ligne, tabulation etc..)
• Exemple :
retour à la ligne = CR = code ASCII 13 char retour;
retour = 13; ou bien retour = '\n';
• Conventions
\n : retour à la ligne
\t : tabulation
\f : nouvelle page
\' : apostrophe
\0 : caractère nul (indique la fin d'une chaîne de caractères)
Les entiers : entiers naturels
• Codage sur 2 ou 4 octets suivant le calculateur
• Sur deux octets on peut coder les nombres de 0 à 216-1 (0 à 65535)
• Nombre représenté en base 2, les bits sont rangés dans des cellules correspondant à leur poids, on complète à gauche par des 0
• Exemple :
13 = 8 + 4 +1 = 1*23+1*22+0*21+1*20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1
• Déclaration d'une variable entier naturel x
unsigned int x;
short unsigned int x; (on force sur 16 bits) long unsigned int x; (on force sur 32 bits)
0 , 1 , n 16 ou 32
, 2
1 0
i
n i i
i
x
x
x
Type entier relatif
• Implantation sur 2 ou 4 octets suivant le compilateur
• Représentation sur n bits : codage complément à 2
• Déclarations
int a,b;
….
a = 1;
….
b= 3;
0 , 1
, 2
2
20 1
1
i
n i i
i n
n
x x
x
x
Type entier relatif
• Codage complément à 2
• Si xn-1 = 0 : nombre positif, xn-1 = 1 : nombre négatif
• Exemple sur 16 bits
+5 = 1 * 22 + 0 * 21 + 1 * 20 = 0000 0000 0000 0101 -3 = -32768 + 32765
= -215+ 214 + 213 + 212 + 211 + 210 + 29 + 28 + 27 + 26 + 25 + 24 + 23 + 1.22 + 0.
21 + 1.20
= 1111 1111 1111 1101
• Sur 16 bits (2 octets)
-32768 x 32767
• Sur 32 bits
-2147483648 x 2147483647
0 , 1
, 2
2
20 1
1
i
n i i
i n
n
x x
x
x
Complément à 2
• Représentation non symétrique : le plus petit nombre n'a pas d'opposé : sur n bits
• le plus grand entier positif est 2
n-1-1
• le plus petit entier négatif est -2
n-1• exemple sur 3 bits :
000
100 110 010
001
011 101
111 0
1
2 3 -3 -4
-2 -1
Codage complément à 2
• Remarques
1/ Complément à 2 de x = Complément à 1 de x + 1 représentation de –3 ?
3 = 0000 0000 0000 0011 c1(3) = 1111 1111 1111 1100 +1 = 0000 0000 0000 0001 c1(3) +1= 1111 1111 1111 1101 2/ Représentation 16 bits = > 32 bits
x >0 = 0000 0000 0000 0011 => x = 0000 0000 0000 0000 0000 0000 0000 0011 x <0 = 1111 1111 1111 1101 => x = 1111 1111 1111 1111 1111 1111 1111 1101
• Extensions
int 2 ou 4 octets ? problème de portabilité short int x; 2 octets
long int x ; 4 octets
unsigned int x ; bit de signe utilisé pour la valeur unsigned short int x ;
unsigned long int x ;
Type réel
• Déclaration
float x,y;
x = 3.14;
y = 2.0 e+3;
• Implantation sur 4 octets
• Représentation suivant le compilateur
en général mantisse exposant (norme IEEE)
• 10
-38< x < 10
38• Extension :
double x; x est codé sur 8 octets
Nombre réels
• Codage des réels : virgule flottante, Norme IEEE
• flottant stocké sous la forme M * B
EM : Mantisse ; B : Base ; E : Exposant
• exemple : 123 . 10
3= 123 000
• Représentation IEEE 754 (signe 1 bit, mantisse et exposant sur 32 ou 64 bits pour simple et double précision)
• SM : signe de la mantisse : 1 bit
• Eb : exposant biaisé : 8 ou 11 bits
• M : Mantisse : 23 ou 52 bits
SM Eb M
Mantisse et exposant
• Signe : bit de poids fort (0 = + ; 1 = -)
• Exposant
placé avant la mantisse pour simplifier les comparaisons (pour ceci il ne doit pas être représenté en complément à deux : -1 > 2)
sur 8 bits : 0..256
sans signe mais biaisé de 127 (simple précision) : Eb = 1 E = 1 – 127 = -126⇒
Eb = 254 E = 254 – 127 = 127⇒
les exposants 255 (erreur) et 0 (nb dénormalisé) sont interdits
• Mantisse
normalisée : bit de poids fort n’est pas 0 et un seul chiffre avant la virgule
• ex : 3,25
10= 11,01
2= 1,101 * 2
1Virgule Flottante
• Comme le bit de poids fort de la mantisse est nécessairement 1 : on ne l’indique pas (gaspillage de place), il est implicite
• Mantisse
partie fractionnaire = f1f2 …fn m = 1,f1f2…fn⇒ nombre x = (-1)SM * 1,M * 2Eb-127
• Exemple
x = (-2,5)10 = -1,01*212 SM = 1 ;
E= 1 => Eb= 128 = 1000 0000 ; m=1,01 => M =010…….0
• Déclaration de variables réelles :
float x;
double y;
SM Eb M
f1,f2,……fn
Variables
• Variable : élément de mémorisation élémentaire
• Toutes les variables doivent être déclarées suivant un type
int a, b; ou bien int a;
int b;
float x;
char caractere;
• Identificateur de variables (noms)
Le premier caractères doit être une lettre
Les autres caractères sont les lettres (majuscules et minuscules), les chiffres et le caractère _
Majuscule / minuscule significatifs
• Exemples :
Pi, pi3_14, a2B3 : corrects 2x, i-E : incorrects A1 a1
Variables
• Exemple :
char a;
int un;
a = 'a';
un =1;
a = '1';
• Initialisation des variables
à l'exécution : int i;
….
i = 0;
à la compilation int i = 0;
Conversion de type
• Conversion explicite : ( type ) expression
Exemple :
int a; float x; char c;
a= 2;
x= (float) a;
x= 2.3;
a= (int) (x+1);
a = 98;
c = (char) a; -> c='b'
• Conversion implicite
Exemple :
int a; float x; char c;
a= 2;
x= a;
x= 2.3;
a= x+1;
a = 98;
c = a; -> c='b'
Conversion de types
• Exemples :
char c; int i; float f;
// conversion entier vers char.
c= 98; // implicite : c prend le code ASCII 98 c-à-d ’b' c = (char) 98; // explicite plus propre
// char vers entier
i= 'a' ; // i prend la valeur 97 i= (int) 'a' ; //plus propre
// entier vers réel
f= 3; // f prend la valeur 3.0;
f=(float) 3; //+ propre
//réel vers entier, attention : troncature i = 3.4; // i prend la valeur 3
i= -3.7; // i prend la valeur -3 i = (int) 3.4; // + propre
Conversion de types : application
• Passer au caractère suivant
char c;
c ='a';
c = c+1; // calcul fait en entier puis résultat converti en char c = (char) ((int) c+1) ; //+ propre
• Conversions majuscule<-> minuscule
char c;
c='t';
// conversion en Majuscule c=c-32; // c contient 'T' ou mieux
c=c-('a'-'A');
c=c+1; // c contient 'U' // conversion en minuscule c=c+32;
ou c=c+('a'-'A')
// conversion en Majuscule
if ((c >= 'a') && (c <= 'z')) c = c-('a'-'A');
Tableaux
• Lorsque on veut mémoriser plusieurs données de même type, on peut utiliser un tableau c-à-d on regroupe sous un même nom plusieurs informations
• Exemple de déclaration d'un tableau d'entiers
int tab[100];
int : type des éléments du tableau tab : identificateur (nom du tableau)
100 : nombre d'éléments du tableau (dimension)
tab peut recevoir 100 entiers indicés de 0 à 99 (attention !) le premier est tab[0]
le second tab[1]
..
le dernier tab [99]
Tableaux
• Utilisation
chaque élément du tableau est accessible par un indice qui doit être de type entier, quelque soit le type des éléments du tableau
exemples : int i ;
tab[2] 3eme élément du tableau tab[2+3] 6eme élément du tableau tab[i] i+1eme élément du tableau
• Exemples :
stocker les 100 premiers nombres pairs : 0,2,4,...,196,198 int i, t[100];
for (i=0; i < 100; i=i+1) t[i]= 2*i;
Tableaux
• Remarques:
1/ chaque élément du tableau s'utilise comme une variable tab[3] = 2;
2/ le nombre maximum d'éléments du tableau (dimension) 1/ doit être fixé à la compilation
2/ ne peut être modifié pendant l'exécution
3/ Pas d'opérations sur les tableaux en tant que tels
Parcours des éléments d’un tableau
Parcours du premier au dernier
int i; /* l’indice de balayage doit être un entier */
float t[100]; /* le type du tableau est quelconque, ici réel */
for (i=0; i < 100; i=i+1) // ou bien for (i=0; i <= 99; i=i+1) t[i]= …….;
Parcours du dernier au premier int i;
float t[100];
for (i=99; i >= 0; i=i-1) t[i]= …….;
La dimension
Bonne pratique de programmation int i;
int t[100];
for (i=0; i < 100; i=i+1) t[i]= 100;
Pb : modification du pgm, changement de la taille du tableau malaisée
#define TAILLE 100 int i;
int t[TAILLE];
for (i=0; i < TAILLE; i=i+1) t[i]= 100;
Il suffit de changer TAILLE
Exemples
Point de l'espace
1ere solution : float x,y,z;
2eme solution float pt[3];
pt[0] pour x, pt[1] pour y, pt[2] pour z
Mémorisation des 100 premiers nombres pairs et impairs:
int pairs[100], impairs[100];
int i;
for (i=0; i<100;i=i+1) { pairs[i]=2*i;
impairs[i]=2*i+1;
}
• En c, pas de type prédéfini chaîne de caractères. En pratique on utilise des tableaux de caractères.
• Convention : le dernier caractère utile est suivi du caractère
\0 (de code ascii 0)
• Exemples :
char t[10]; (9 caractères max, puisque une case réservée pour \0;
strcpy(t,"abcdefghi")
chaque lettre est accessible par l'indice char t[12];
strcpy(t,"abcdefghi");
• Initialisation
char t[10]= "abcdefghi"; ou char t[]= "abcdefghi";• Constante chaîne de caractères
#define ceciestuntexte "azssddqsdqsd"
Chaînes de caractères
'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 0
'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 0 ? ?
Définitions de type utilisateur
typedef int entier; (entier est maintenant un type) entier i;
typedef int tableaude20[20];
tableaude20 t; int t[20];
Les expressions en langage C
Expressions : introduction
• Remarque : expression instruction
• une instruction indique à l'ordinateur de mener une action
• expression = élément syntaxique
• Expressions :
variable ou constante, ex : x, 3
constituées à l'aide d'opérateurs : x+ y
conversion de type, opérateurs arithmétiques, de taille, relationnels et logiques, affectation, bit-à-bit, conditionnels, adresse
Expressions
• Une expression représente une donnée élémentaire :
constante, variable, un élément de tableau, la référence à une fonction ou à une valeur, le résultat d'un calcul etc ….
• Exemples
3 a+b x=y
c = a+b x <= y x == y i++
sin(3.14)
• Toute expression a une valeur
Opérateurs arithmétiques
• Opérateurs bi-opérandes
+ , -
* , / , % (modulo)
Les opérandes doivent être des valeurs numériques.
entier opérateur entier -> résultat entier réel opérateur réel -> résultat réel entier opérateur réel -> résultat réel
• Exemples
int a,b;
a=10; b= 3
a+b 13
a-b 7
a*b 30
a/b 3 (division euclidienne)
a%b 1
float a,b;
a=12.6; b= 3.0
a+b 13.6
a-b 9.6
a*b 37.8
a/b 4.2 (division réelle) a%b erreur de syntaxe
Opérateurs arithmétiques
• Opérateur % :
- int a; flloat x;
(a+x) % 4 incorrect. ((int) (a+x))%4 correct
- si l'un des opérandes est négatif, le résultat est négatif.
• Si l'un des opérandes est de type caractère, c'est la valeur du code ASCII qui est prise (conversion implicite char vers int ou float)
• Conversion majuscule minuscule
Exemple : char c = 'a';
c = c+1; => c = 'b' mécanisme :
c+1 = 98 + 1 =99
c = code ascii 99 = 'c'
Exemple : char c ;
if (c >= 'a' && c <='z') c = c-32 (ou bien c = c + 'A' –'a') if (c >= 'A' && c <='Z') c = c+32 (ou bien c = c - 'A' +'a')
Opérateurs arithmétiques
• Opérateurs unaires (un opérande)
a/ signe : + , - exemple : a = -a;
b/ incrémentation, décrémentation : ++ (+1) , -- (-1) exemple :
int i =1;
++i;
printf("%d",i) ; -> 2;
Syntaxes : ++i ou i++
++i : la valeur de i est d'abord incrémenté, la valeur résultat est utilisée dans l'expression courante
i++ : la valeur courante de i est utilisée dans l'expression courante, puis i est incrémenté
++ et --
• Exemples
i=1; i=1;
printf("i= %d\n",i); -> i=1 printf("i= %d\n",i); -> i=1 printf("i= %d\n",++i); -> i=2 printf("i= %d\n",i++); -> i=1 printf("i= %d\n",i); -> i=2 printf("i= %d\n",i); -> i=2
• Conclusions :
1/ appendre la règle (pour comprendre des programmes) 2/ à n'utiliser que lorsque il n'y a pas d'ambiguïté :
x=y+z++; // à éviter x++; // pas de risque
Opérateurs d'affectation
• Affectation simple
syntaxe : variable = expression
la valeur de l'expression est stockée dans la mémoire à l'endroit réservé pour la variable
Exemples :
a = 2; b=1; c=0;
a = b+c;
a = b && c;
la valeur de l'expression vaut la valeur affectée Attention : affectation et test d'égalité
if (a =1) instruction1; else instruction2;
L'instruction1 est toujours déclenchée.
a = b = 3; (évaluation de droite à gauche)
Opérateurs d'affectation
• Affectation et opération : +=, -=, *=, /=, %=,<<= , >>=, &=,
|=, ^=
Syntaxe : variable opérateur expression
équivalent à : variable = variable opérateur expression Exemple :
int i;
i= 3;
i+=2; // même chose que i=i+2;
printf("%d\n",i); -> 5
Opérateurs relationnels et logiques
• Valeur logique :
0 : faux
0 : vrai
exemple : if (3) traitement1 ; else traitement 2;
équivalent à : traitement1;
• Relationnels : >= , > , == , <, <= , !=
• La valeur de l'expression est 1 si l'expression est vraie , 0 si elle est fausse
Exemple : 2 < 3 vaut 1 , 2 > 3 vaut 0
• Attention à la confusion : test d'égalité == et l'affectation =
ex : if (x=0) traitement 1; // au lieu de x==0 else traitement 2;
Conséquence: En cas d'erreur, non seulement le traitement 1 ne sera jamais exécuté mais en plus x vaudra 0 quelle que soit sa valeur initiale
• Logiques : && "et" logique , || "ou" logique, ! "non" logique
Dans l'évaluation de l'expression, 0 est considéré comme la valeur logique "faux", toute valeur 0 comme la valeur logique "vraie"
La valeur de l'expression est 1 ou 0 Exemples:
2 && 0 vaut 0 et donc est faux 2 || 0 vaut 1 et donc est vrai !0 vaut 1 !4 vaut 0
Opérateurs bit à bit
• Opèrent sur les représentations des valeurs
• & et , | ou, ^ ou-exclusif, ~ complément à 1 ,
• << décalage à gauche, >> décalage à droite,
• Attention : & &&
• Exemples
5 0000 0000 0000 0101
20 0000 0000 0001 0100
5 & 20 0000 0000 0000 0100 => 5 & 20 => 4 5 | 20 0000 0000 0001 0101 => 5 | 20 => 21 5 ^ 20 0000 0000 0001 0001 => 5 ^ 20 => 17
~5 1111 1111 1111 1010 => -6
• Affectation/bit-à-bit : &=, |=, ^=, ~=
Décalages
• Décalages
• à gauche a << b : a est décalé à gauche de b bits (les bits ajoutés valent 0)
5 << 2 0000 0000 0001 0100 20
un décalage d'une position à gauche correspond à une multiplication par 2
• à droite a >>b : a est décalé à droite de b bits (les bits insérés valent le bit de poids fort)
14 0000 0000 0000 1110
14 >> 2 0000 0000 0000 0011 3
-6 1111 1111 1111 1010
-6 >> 1 1111 1111 1111 1101 -3
un décalage d'une position à droite correspond à une division par 2 (en respectant le signe)
Opérateur conditionnel
• Syntaxe
expression1 ? expression2 : expression3 à peu près équivalent à :
if (expression1) expression2; else expression3;
• Exemple :
maximum = (x>y) ? x : y;
if (x>y) maximum =x ; else maximum = y;
• Conseil : ne pas utiliser (peu clair)
Opérateurs d'adressage
• Adresse de : &
Syntaxe : &variable , donne l'adresse mémoire de la variable Exemple :
int i,adr;
adr = &i;
ne pas confondre avec le "et" bit à bit
• Dont l'adresse est : *
Syntaxe *expression : donne le mot mémoire dont l'adresse est donnée par l'expression
Exemple : int i,adr;
i=1;
adr = &i;
printf("%d", *adr); -> 1
Opérateur de taille : sizeof
• Donne la taille de l'implantation
• 2 syntaxes
1/ sizeof expression exemple :
int i,j ;
j= sizeof i; -> 2 ou 4 (octets) 2/ sizeof (type)
exmples :
typedef char tab[100];
tab t;
int n;
n = sizeof(int), -> 2 ou 4 (octets) n = sizeof(tab) -> 100 (char)
Opérateurs divers
• ( ) : force l'ordre des calculs
ex : 1 + 2 * 3 -> 7 (1+2) * 3 -> 9
• [ ] pour les tableaux
t[2] équivalent à *(t+2)
• -> et . (opérateurs sur structures, + tard)
Priorité des opérateurs
Priorité Opérateurs Description Associativité
15 () [ ] -> . opérateurs d'adressage ->
14
++ -- incrément/décrément
<-
~ complément à un (bit à bit)
! non unaire
& * adresse et valeur (pointeurs)
(type) conversion de type (cast)
+- plus/moins unaire (signe)
13 * / % opérations arithmétiques ->
12 + - "" ->
11 << >> décalage bit à bit ->
10 < <= > >= opérateur relationnels ->
9 == != "" ->
8 & et bit à bit ->
7 ^ ou exclusif bit à bit ->
6 | ou bit à bit ->
5 && et logique ->
4 || ou logique ->
3 ?: conditionnel <-
2 = += -= *= /= %=
>>= <<= &= ^= |= assignations <-
1 , séparateur ->
Priorité des opérateurs
a – b /c *d (a-b) / (c-d) i = j = k = 0;
a=1; b=4;
! --a == ++ !b
!0 == ++0 1 == 1 1
Priorité des opérateurs (exercices)
main(){
int x, y , z;
x = 2;
x += 3 + 2; printf("%d\n",x);
x -= y = z = 4; printf("%d%d%d\n",x,y,z);
x = y == z; printf("%d%d%d\n",x,y,z);
x == (y = z); printf("%d%d%d\n",x,y,z);
x = 3; y =2 ; z = 1;
x = x && y || z ; printf("%d\n", x);
printf ("%d\n", x || ! y && z);
x = y = 0;
z = x ++ -1; printf ("%d, %d\n", x, z);
z += -x ++ + ++ y; printf ("%d, %d\n", x, z);
x =1 ; y =1;
printf("%d\n", ! x | x);
printf("%d\n", ~ x | x);
printf("%d\n", x ^ x);
x <<= 3 ; printf("%d\n", x);
y <<= 3 ; printf("%d\n", y);
y >>= 3 ; printf("%d\n", y);
Priorité des opérateurs (exercices)
x =0 ; y =0; z=0;
x+=y+=z;
printf("%d\n", x < y ? y : x) ;
printf("%d\n", x < y ? x++ : y++) ; printf("%d, %d\n", x , y);
printf("%d\n", z += x < y ? x++ : y++) ; printf("%d, %d\n", y , z);
x = 3; y = z = 4;
printf("%d\n",( z >= y >= x) ? 1 : 0) ; printf("%d\n", z >= y && y >= x ) ; x = y = z = 0;
}
ENTREES / SORTIES
Les entrées/sorties (lecture/écriture)
• Lecture clavier
2 fonctions de base : getchar () et scanf()
Elles peuvent être appelées soit indépendamment soit au sein d'expressions
Exemples getchar();
while (c==getchar()) {…..};
getchar()
• getchar() : sert à la lecture de caractères isolés
• la valeur de getchar() est le code ascii du caractère lu
• utilisation char c;
c = getchar();
• Exemple : on veut lire et mémoriser 2 caractères donnés sur 2 lignes différentes
char c1,c2;
c1 = getchar() // acquiert le 1er caractère
getchar (); // filtre le <cr>, on ne mémorise pas la valeur lue c2 = getchar () // acquiert le 2ème caractère
scanf ()
• Sert à la lecture de données et convertit la succession de caractères donnés en entiers, flottants, caractères, chaîne de caractères
• Syntaxe :
scanf (format,arg1,arg2,……,argn)
le nombre d'arguments est quelconque
arg1, arg2,……, argn sont les adresses des variables dans lesquelles on stocke les valeurs lues
variable simple (entier, caractère, flottant) : &v
chaîne de caractères = tableau : v
le format est une chaîne de caractères précisant le type des arguments afin de convertir la suite de caractères lus dans les arguments
Scanf : format
• Format
chaîne de caractères composée de caractères % suivis d'une lettre et éventuellement séparés par des blancs
la lettre indique le type de conversion à effectuer exemple :
int i; float x;
scanf("%d %f", &i,&x);
le %d indique que le premier argument est un entier le %f indique que le second est un réel
réponse : 23☐12.6
23 est converti en entier et stocké dans i 12.6 est stocké en flottant et stocké dans x
Scanf : format
• caractères de conversion
c : donnée de type caractère simple d : donnée de type entier relatif
f : donnée de type flottant
e : donnée de type flottant en notation exponentielle x : donnée de type entier hexadécimal
s : donnée de type chaîne de caractères (tabl. de char terminé par \0)
• Exemple
char t[20];
int i ; float x;
scanf ("%s %d %f", t,&i,&x);
réponses :
1/ abcde 123 0.05
2/ abcde 123 0.05
3/ abcde
123 0.05
Scanf : rôle des caractères ☐, , tabulation, dans les réponses
• Dans les réponses
☐, , tabulation servent de délimiteurs pour les valeurs numériques et les chaînes de caractères (pas pour les caractères)
• Exemples
scanf ("%d%f",&i,&x);
rep1 : 123 ☐☐☐☐456 i = 123 , x = 456.0
rep2 : 123456 i = 123456 , x : pas encore lu (en attente) scanf("%s%d",ch,&i);
rep : abc 12 ch = "abc" , i=12 scanf ("%c%c",&c1,&c2);
rep1 : ab c1= 'a' , c2 = 'b'
rep2 : a☐b c1= 'a' , c2 = ☐
scanf ("%c%c%c",&c1,&c2,&c3);
rep1 : ab c1= 'a' , c2 = 'b', c3=
rep2 : ab c1= 'a' , c2 = 'b'
c c3 =
Scanf : rôle des caractères ☐ et tabulation, dans la chaîne de format
• Lecture de valeurs numériques : aucun rôle
scanf ("%d%f",&i,&x) scanf ("%d☐%f",&i,&x)
• Lecture de caractères : indique de sauter les ☐, tab et
• Exemples
scanf ("%c%c%c",&c1,&c2,&c3);
rep1 : abc c1= 'a' , c2 = 'b', c3= 'c' rep2 : a☐b☐c c1= 'a' , c2 = '☐', c3= 'b' scanf ("%c☐%c☐%c",&c1,&c2,&c3);
rep1 : abc c1= 'a' , c2 = 'b', c3= 'c' rep2 : a☐b☐c c1= 'a' , c2 = 'b', c3= 'c' rep2 : a☐b
c c1= 'a' , c2 = 'b', c3= 'c'
Scanf : compléments
• Nombre de caractères lus
faire précéder le caractère de format du nombre de caractères (max) désiré
Exemples int i,j,k;
scanf("%3d %3d %3d",&i,&j,&k);
rep1 : 1☐2☐3 i=1 j=2 k=3
rep2 : 123☐456☐789 i=123 j=456 k=789 rep3 : 123456789 i=123 j=456 k=789 rep4 :1234☐5678☐9 i=123 j=4 k=567 int i; float x;char c;
scanf("%3d☐%5f☐%c,&i,&x,&c);
rep : 10☐234.567☐t i=10 x=234.5 c='6'
Scanf : compléments
• Lecture d'une chaîne de caractères
char ch[50];
scanf("%s",ch) // pas de &
rep : abcdefghi
Le caractère 0 de fin de chaîne est ajouté automatiquement
Exercice : faire l'équivalent de scanf("%s",ch) à l'aide de getchar()
• Saut conditionnel de caractères : %*d, %*f
permet de sauter des données correspondantes dans la réponse exemple :
int i,j; char c;
scanf("%d ☐ %*d ☐ %c",&i,&c);
rep1 : 12☐34x i=12 c='x' rep2 : 12☐x i=12 c='x'
'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 0 ? ?
scanf : compléments
• Filtre sur chaînes de caractères
[ caractères admissibles] ou [^caractères non admissibles]
exemples
char ch[100];
scanf("%[0123456789]",ch);
rep : 32ab48 ch="32"
scanf("%[^0123456789]",ch);
rep : 32ab48 ch="ab"
raccourcis : [0123456789] ou [0-9]
[abcdefg] ou [a-g]
Ecriture
• 2 fonctions de base : putchar() et printf()
• putchar(caractère)
• Exemple
char c;
c='a';
putchar ( c );
putchar ('\n');
putchar('b');
Affichage : a
b
Printf()
• Format
printf(format,arg1,arg2,…..,argn);
les arguments sont des valeurs d'expression à imprimer
le format donne le texte mort et le mode de décodage des arguments le format est une chaîne de caractères
• Exemples :
printf("bon"); printf("jour");printf("\n") bonjour i=j=1;
printf("i=%d\n",i) i=1
printf("%d%d%d\n",i,j,i+j); 112
printf("%d☐%d☐%d☐%d\n",i,j,i+j,sqrt(i)); 1☐1☐2☐1 x=3.0;
printf("%f☐%d\n",x,i); 3.000000☐1
printf("%d\n%d\n",i,i+j); 1
2
Printf
• Caractères spéciaux de format
%d : imprime les entiers sur le nombre de caractères nécessaires
%f : imprime les réels avec 6 chiffres de partie décimale
%e : imprime les réels en notation exponentielle
%c : imprime un caractère
%s : imprime une chaîne de caractères jusqu'à rencontrer le caractère de fin de chaine 0 (erreur si absent)
…..
\n : saut à la ligne
\t : tabulation
\p : saut à la page
….
Printf : mises en forme
• Forçage du nombre de caractères
entiers :
%5d l'entier est imprimé sur 5 caractères au moins (blancs) avec cadrage à droite
%-5d l'entier est imprimé sur 5 caractères au moins (blancs) avec cadrage à gauche
réels :
%10f le réel est imprimé sur 10 caractères (en tout) avec 6 chiffres en partie décimale (cadrage à droite)
%-10f idem + cadrage à gauche limitation de la partie décimale
%20.3f le réel est imprimé sur 20 caractères (en tout) avec 3 chiffres en partie décimale
Printf : format variable
• ("%*d",n,i)
n donne le nombre de caractères pour i
• ("%*.3f,n,x)
n donne le nombre total de caractères pour x
• ("%*.*f,n,m,x)
n donne le nombre de total caractères
m donne le nombre de caractères pour la partie décimale
• Exemples
Printf
• La valeur de retour du printf est le nombre de caractères écrits et une valeur négative si il y a eu un pb.
• Exemple :
int a,x;
a=32;
x = printf ("%d\n",a);
printf ("%d\n",x); -> 3
Autres fonctions d'E/S
• Beaucoup d'autre fonctions d'E/S
voir "stdio.h"
gets, puts permettent de lire et d'écrire des chaînes de caractères
contenant des espaces (rappel : scanf ("%s",….) les espaces sont des délimiteurs)
exemple :
#include "stdioh"
main() {
char ligne[80];
gets(ligne);
puts(ligne);
}
Lecture/Ecriture dans fichiers
• Principe : identique aux lecture/écriture sur clavier/écran
En fait, le clavier et l'écran sont des fichiers particuliers
• Il faut simplement en plus "ouvrir" le fichier c-à-d
- l'associer à un fichier physique (sur disque) - l'associer à un variable interne du pgm
• Un fichier peut être
- soit lu (read)
- soit (ré-)écrit (write) bande magnétique - soit écrit à la fin (append)
• Déclaration :
FILE * variable-interne
ex : FILE * f; // f est une variable spéciale de type "fichier"
Ouverture de fichier : fopen
• variable = fopen("nom du fichier sur disque",mode d'ouverture)
mode d'ouverture :
syntaxe : chaîne de caractères 1er caractère :
'r' = read = lecture 'w' = write = écriture
'a' = append = écriture à la fin
fopen renvoie la valeur NULL (=0) si le pb sur le fichier physique
• Exemple
FILE * f;
f = fopen ("c:\texte.txt","r1234");
if (f==NULL) printf ("le fichier est absent\n");
else printf ("ok\n");
variable interne
fichier physique
Fermeture du fichier : fclose
• Supprime l'association fichier physique-variable interne
• La variable interne peut être associée à un autre fichier physique
• Syntaxe
fclose (variable interne)
• Exemple :
FILE * f;
f= fopen (fichier1, "r");
….
fclose (f);
…
f= fopen (fichier2,"w");
…
Lecture dans fichier
• Lecture :
fgetc() et getc() ↔ getchar() exemple
c=fgetc(f);
fscanf() ↔ scanf() exemple
fscanf(f,"%d",i) le 1er argument est le variable interne fichier
• Le caractère EOF indique la fin de fichier
• Ecriture
fputc () ↔ putchar() // c= fgetc (f)
fprintf() ↔ printf() // fprintf(f,"……",…..);
Exercice
• Afficher à l'écran le contenu d'un fichier (idem commande unix ou MSDOS type)
main() {
FILE * monfichier;
char sur_disque[100]; char c;
/* acquisition du nom */
scanf("%s",sur_disque);
/*ouverture*/
monfichier=fopen(sur_disque,"r");
if (monfichier==NULL) printf("erreur\n");
else { // lecture affichage
while ((c=getc(monfichier))!=EOF) printf("%c",c);
fclose (monfichier);
} }
Lecture/ecriture dans chaines de caractères
• sprintf (char * s, format, paramètres) = écriture dans la chaine s
• sscanf (char * s, format, paramètres) = lecture dans la chaine s exemple
char tokenstring[] = "15 12 14... " ; char s[81]; char c; int i; float fp;
/*lecture de différentes valeurs: */
sscanf( tokenstring, "%s", s );
sscanf( tokenstring, "%c", &c );
sscanf( tokenstring, "%d", &i );
sscanf( tokenstring, "%f", &fp );
/* Sortie*/
printf( "String = %s\n", s );
printf( "Character = %c\n", c );
printf( "Integer: = %d\n", i );
printf( "Real: = %f\n", fp ); }
• Sortie : String = 15 Character = 1 Integer: = 15 Real: = 15.000000
Lecture/écriture dans chaines de caractères
• Exercice :
Convertir un entier en une chaîne de caractères : exemple :
int i = 135,;
char s[1000];
/* à faire */
……..
printf("%s",s); 135;
Compléments sur les instructions de contrôle
• Instruction if : imbrication
ex1 : if(e1) if(e2) s1;
else s2;
else if (e3) s3;
else s4;
e1
s1 s1 s2 s3 s4 e2
e3
ex2 : if(e1) s1;
else if (e2) s2;
ex3 : if(e1) s1;
else if (e2) s2;
else s3;
ex4 : if(e1) if(e2) s1;
else s2;
e1
s1
s2 e2
e1
s1
s2 s3 e2
e1
s1 s1 s2 e2
e1
s1 s1
s2 e2
Compléments sur les instructions de contrôle
• Règle : le else se rapporte au if le + imbriqué
e1
s1 s1
s2 e2
if(e1) {if(e2) s1;}
else s2;
if(e1)
if(e2) s1;
else ; else s2;
ou bien
Compléments sur les instructions de contrôle : continue
• Dans une structure itérative : l'instruction continue permet d'arrêter l'itération courante sans sortie de la boucle
• Exemple: Calculer la moyenne des valeurs positives d'un tableau d'entiers relatifs.
nb_valeurs=0;
somme = 0;
for (i=0;i<dim;i++) {
if (T[i]<0) continue;
somme = somme + T[i];
nb_valeurs ++;
}
moyenne = somme / nb_valeurs
Instruction break
L'instruction break fait sortir de la structure de contrôle dans laquelle elle est imbriquée
Utilisation dans les boucles : permet de faire une boucle avec une condition de type "et" logique
ex: while (c1 && c2) {traitement;}
while (c1)
if (!c2) break;
else {traitement;}
Application typique : gestion d'exception
différence entre continue et break
for (i = 0 ; i < 10 ; i++) { if (i == 5) break ; printf("%d,",i) ; }
0,1,2,3,4,
for (i = 0 ; i < 10 ; i++) {
if (i == 5) continue ; printf("%d,",i) ;
}
0,1,2,3,4,6,7,8,9
break
On veut afficher tous les éléments d'un tableau d'entiers jusqu'à rencontrer un nombre <0 (si il y en a un)
for (i=0;t[i]>=0 && i<dim;i++) ou bien i=0;
printf("%d", t[i]); while(t[i]>=0 && i<dim) {printf("%d", t[i]);i++};
Pb : lorsque i=dim, il y a évaluation de t[dim] qui n'existe pas => erreur Solution 1 : avec un "drapeau »
positif=1;
// positif indique que l’on a eu que des valeurs positives jusqu'à maintenant for (i=0; (positif==1) && (i<dim) ; i++) {
if(t[i]<0) positif=0;
else printf("%d", t[i]);
} Solution 2 :
for (i=0; i<dim;i++) { if(t[i]<0) break;
else printf("%d", t[i]);
}
Instruction switch
• syntaxe : switch (expression) instructions où expression a une valeur entière ou caractère
• L'instruction est une expression composée d'alternatives.
Chaque alternative commence par une énumération de cas
• switch (expression) {
case valeur 1 : instruction1; instruction 2; ….;
case valeur 2 : instruction1; instruction 2; ….;
…
case valeur n : instruction1; instruction 2; ….;
default : instruction1; instruction 2; ….; // optionnel };
switch
Exemple : char c;
printf("donner un e couleur\n");
c=getchar();if (c>='a' && c<='z') c=c+'A'-'a' switch (c) {
case 'R' : printf("Rouge \n");
case 'V' : printf("Vert\n");
case 'B' : printf("Bleu\n");
default : printf ("Autre");
}
R
Rouge Bleu Vert Autre
V
Bleu Vert Autre
B
Bleu Autre Autre
switch + break
Exemple : char c;
printf("donner un e couleur\n");
c=getchar();if (c>='a' && c<='z') c=c+'A'-'a' switch (c) {
case 'R' : printf("Rouge \n");break;
case 'V' : printf("Vert\n");break;
case 'B' : printf("Bleu\n");break;
default : printf ("Autre");
}
R
Rouge
V
Vert
B
Bleu Autre
b ou B
switch + break
Exemple : char c;
printf("donner une couleur\n");
c=getchar();
switch (c) {
case 'r','R' : printf("rouge \n");break;
case 'v', 'V' : printf("Vert\n");break;
case 'b','B' : printf("Bleu\n");break;
default : printf ("Autre");
}
r ou R
Rouge
v ou V
Vert
Bleu Autre
Les tableaux
Rappel : tableau =regroupement de données de même type sous un même nom, accessibles par un indice (0,..,dim-1)
Déclaration et implantation mémoire :
int t[50]; => réservation dans la mémoire de 50 cases contiguës d'entiers.
L'adresse de la première case est t
&t[0] t
*t t[0]
t[0]t[1]
t[2]
t[48]
t[49]
t
• Initialisation à la compilation int t[10] = {1,2,3,4,5,6,7,8,9,10};
float x[4] = {0.,0.25,3.14,2.57};
char couleur[4]= {'r','v','b','j'};
char texte[10]="abcd";
int t1[10] = {1,2,3};
• Dimension par défaut:
int t[ ]={0,0,0} => dimension =3
char t [ ]={'r','v','b','j'}; => dimension=4 char t[ ]="abcd" => dimension=5
par contre int t[ ] sans initialisation est incorrect
a b
Tableaux
1 2 3 4 5 6 7 8 9 10
c d \0 ? ? ? ? ? 1 2 3 ? ? ? ? ? ? ? 0. 0.25 3.14 2.57
r v b j
Tableaux
• Accès aux éléments d'un tableau
int t[50];
syntaxe 1
// accès à la (i+1)ème case avec i compris entre 0 et 49 t[i];
syntaxe 2
puisque t est l'adresse de la première case :
t[0] *t // mot d'adresse t, * : opérateur mot dont l'adresse est) t[1] *(t+1) // rem : priorité des opérateurs)
…
t[i] *(t+i) // *t+i t[0]+i
Tableaux à plusieurs dimensions
• Tableau dont chaque case est elle-même un tableau ex : typedef int t[100] // t est un type
t matrice [20];
matrice est un tableau de 20 cases, chacune est un tableau de 100 entiers =>
matrice est un tableau de 20*100 entiers autre déclaration :
int matrice [20][100]; // tableau de 20 "lignes" et 100 "colonnes"
• Accès aux éléments
par un 1er indice allant de 0 à 19 et par un 2eme indice allant de 0 à 99 matrice[3] est la 4eme case de tableau. C'est un tableau de 100 cases
(entiers)
matrice[3][48] est un entier.
matrice [i][j] avec i de 0 à 19 et j de 0 à 99 matrice est un tableau à 2 dimensions