THEME : Programmation C
Exemples
Int nb_entier;
printf(”l’entier entré est : %d”,nb_entier);
VI- l’entrée – sortie(7)
Syntaxe :
scanf("chaîne de contrôle type1 type2..", &arg1, . . .
, &argn);
VI- l’entrée – sortie(8)
Notation C correspondance
2. 2
1.4 1.4
2.e4 2*104
1.4e-4 1.4*10-4
.3 0.3
2e4 2*104
.3e4 0.3*104
I- Les types de données(4)
I.4- Le type void
On a vu que toute variable C était typée, de même
que toute valeur de retour d’une fonction. Mais il
peut arriver qu’aucune valeur ne soit disponible.
Pour exprimer l’idée de ”aucune valeur”, on utilise
le mot-clé void. Ce type est utilisé dans deux
situations :
principalement dans la déclaration de fonctions
qui n’ont pas de valeur de retour;
le prototype de fonctions sans paramètres : int
rand(void).
II- Variable et Affectation(1)
II.1- notion les variables
Une variable est désignée par un identificateur (il s'agit de
son nom). Une variable correspond à un réceptacle d'une
certaine taille qui permet de stocker un type d'information.
Le réceptacle contient une valeur (la valeur de la variable)
qui est susceptible de changer au cours de l'exécution de
l'algorithme.
Le couple ( identificateur, réceptacle) définit une variable.
Les variables sont identifiées par un nom significatif auquel
on associe un type de donnée.
Syntaxe :
<type_données> <nom_variable> ;
exemple :
char[20] nom ;
II- Variable et Affectation(2)
II.2- notion d’affectation
L’affectation se fait par l’utilisation du signe égal (=).
Syntaxe :
<variable>=<expression_retournant_type_variable> ;
Exemple :
Produit = (diviseur * resultat) + reste ;
III- Les constantes
Une constante est une valeur affectée lors de la
programmation. Elle ne peut changer lors de
l'exécution du programme. Il est préférable de
désigner une constante par un nom
(identificateur) si elle doit être utilisée souvent.
Syntaxe :
1- # define <nom_constant> <valeur>
Exemple : #define Pi 3.14
x y Opération Résultat
14 9 x&y
14 9 x|y
14 9 x ^y
14 ~x
14 2 x << y
14 2 x >> y
III- Les opérateurs et expression (8)
III.5- Opérateurs bit à bit (exemple)
x y Opération Résultat
14 1110 ~x 1 1
14 1110 2 10 x >> y 3 11
IV- Les opérateurs et expression (7)
IV.6- Autres
Op. Traduction Exemple Résultat
Exécute la fonction f
() Appel de fonction f(x,y) avec les argument
la valeur de x avec le
(type) cast (long)x type spécifié
nombre de bits occupé
sizeof taille en bits sizeof(x) par x
Evaluation si x est différent de 0,
?: condionnelle x?y:z alors y sinon z
instructions
expression3
V- Les structures de contrôle (4)
V.2- Instruction for (pour)
exemple :
int i,MAX=14; //compteur
for (i=0; i < MAX ; i++) {
printf("Valeur de i : %d\n",i);
}
non
Expression2! Fin
=0 while
oui
expression3
V- Les structures de contrôle (7)
V.3- Instruction while (tantque)
exemple :
#define MAX 14
int i=0;
while (i < MAX ) {
printf("Valeur de i : %d\n",i);
i++;
}
instruction
non
Expression2! Fin do
=0
oui
V- Les structures de contrôle (10)
V.4- Instruction do … while (répéter)
exemple :
#include <stdio.h>
#define MAX 14
int main() {
int i=0;
do {
printf("Valeur de i : %d\n",i);
i++;
} while (i < MAX);
return 0;
}
Exo : écrire un programme C permettant de calculer
la table de multiplication d’un nombre entier compris
entre 1 à 10.
V- Les structures de contrôle (11)
V.5- Instruction switch (décider entre)
Cette instruction est un if généralisée. Sa syntaxe
est la suivante :
switch (expression) {
case constante1 : liste d′instructions1 break ;
...
case constanten : liste d′instructionsn break ;
default : liste d′instructions
}
V- Les structures de contrôle (12)
V.5- Instruction switch (décider entre)
1. expression est évaluée, puis le résultat est
comparé avec constante1, constante2
etc...
2. A la première constantei dont la valeur est
égale à expression, la (ou les) liste d′instructions
correspondante(s) est exécutée jusqu’à la
rencontre d’une instruction break. La rencontre
d’un break termine l’instruction switch.
V- Les structures de contrôle (12)
V.5- Instruction switch (décider entre)
3. s’il n’existe aucune constantei dont la valeur
soit égale à celle de expression, on exécute la
liste d′instructions de l’alternative default si
celle-ci existe, sinon rien n’est fait.
ATTENTION : expression est nécessairement une
valeur entière.
Exo
Ecrire un programme qui permet de traduire un
nombre entier compris entre 0 à 100 en lettre ie
1=un, …, 100=cent.
IV- Les structures de contrôle (13)
V.6- Instruction goto
Syntaxe :
goto etiquette ;
La directive goto permet de brancher directement
à n’importe quel endroit de la fonction courante
identifiée par une étiquette. Une étiquette est un
identificateur suivi du signe ”:”.
V- Les structures de contrôle (14)
V.6- Instruction goto
Exemple :
for ( ... )
for ( ... )
if ( erreur )
goto TRAITEMENT_ERREUR;
...
TRAITEMENT_ERREUR: // le traitement d’erreur
printf("Erreur: ...."); // est effectué ici
...
V- Les structures de contrôle (15)
V.7- Instruction break
Syntaxe :
break;
On a vu le rôle de l’instruction break au sein de la
directive de branchement multiple switch. On
peut l’utiliser plus généralement au sein de
n’importe quelle boucle (instructions for, while ou
do...while) pour interrompre son déroulement et
passer directement à la première instruction qui
suit la boucle.
V- Les structures de contrôle (16)
V.8- Instruction continue
Syntaxe :
continue;
L’instruction continue ne peut être utilisée que
dans le corps d’une boucle(instruction for, while
ou do). Elle permet de passer directement à
l’itération suivante.
V- Les structures de contrôle (17)
V.8- Instruction continue
exemple :
for (i = -10; i < 10; i++) {
if (i == 0) continue; // passer à 1 sans exécuter 0
… //la suite
...
}
I- Déclaration de fonction(1)
On l’aura compris : comme dans la plupart des
langages, on peut (doit ?) en C découper un
programme en plusieurs fonctions. Il existe
une unique fonction obligatoire : la fonction
principale appelée main.
Syntaxe :
type_resultat nom_fonction (type1 arg1, . . . ,
typen argn) {
<déclaration de variables locales >
<liste d’instructions >
}
I- Déclaration de fonction(2)
Remarques :
1. Une fonction peut fournir comme résultat :
– un type arithmétique,
– void.
Une fonction ne peut pas fournir comme
résultat des tableaux, des chaînes de
caractères ou des fonctions, mais il est
cependant possible de renvoyer un pointeur
sur le premier élément d’un tableau ou d’une
chaîne de caractères.
2. Si une fonction ne fournit pas de résultat, il
faut indiquer void comme type du résultat.
Ex : void print_liste(liste L){...}
I- Déclaration de fonction(4)
Remarques :
3. Si une fonction n’a pas de paramètres, on
peut dèclarer la liste des paramètres comme
(void) ou simplement comme ().
Ex : int main(){...} // equivalent à int
main(void){...}
4. Il est interdit de définir des fonctions à
l’intérieur d’une autre fonction (comme en
Pascal).
5. En principe, l’ordre des définitions de
fonctions dans le texte du programme
ne joue pas de rôle, mais chaque fonction doit
être déclarée ou définie avant d’être appelée.
I- Déclaration de fonction(5)
un = 2un−1 + 1 ∀ n ≥ 1
Exo :
Ecrire une fonction permettant de calculer le factoriel
d’un nombre entier quelconque positif.
I- définition (1)
Les tableaux sont des paquets de données de
même type. Ils sont reconnus par la présence
de crochets ouvrants et fermants lors de la
déclaration ou de la définition de l’objet. La
taille du tableau est donnée entre les crochets
lors de la définition. Pour simplifier le travail du
compilateur, le rang des éléments du tableau
ne peut évoluer qu’entre 0 et la taille du
tableau -1.
I- définition (2)
Syntaxe :
Type_tab nom_tab[dimension];
Exemple :
int tab1[10];
Initialisation d’un tableau :
Int tab1[]={1,3,4,7,2,5,6,9,8,0}
Remarque :
la taille d’un tableau DOIT être connue
statiquement par le compilateur. Impossible
donc d’écrire int t[n] ou n est une variable.
I- définition (3)
Exo :
Écrire un programme c permettant de parcourir le
tableau ci-dessus déclaré.
II- dimension d’un tableau (1)
Les tableaux à deux dimensions sont des
tableaux de tableaux. Les indices de droite
sont les plus internes. Les tableaux à n
dimensions sont des tableaux d’indice variant
de 0 à n-1.
int tab1[10]; // est un tableau à une dimension
Int tab2[10][5]; // est un tableau à 2 dimensions
NB : pour accéder à l’adresse d’un élément on
utilise l’opérateur & : &tab1[5] est 4.
II- dimension d’un tableau (2)
int main()
{
// Create a function pointer and make it point to the Add
function
int (*pFcn)(int, int) = Add;
cout << pFcn(5, 3) << endl; // add 5 + 3
return 0;
}
III- Le s pointeurs et les structures
III.10 –les unions
Les unions permettent l’utilisation d’un même espace
mémoire par des données de types différents à des
moments différents..
Syntaxe :
union nom_de_union {
type1 nom_champ1 ;
type2 nom_champ2 ;
type3 nom_champ3 ;
type4 nom_champ4 ;
...
typeN nom_champ_N ;
} variables ;
III- Le s pointeurs et les structures
III.10 –les unions
exemple
union zone {
int entier;
long entlong;
float flottant;
double flotlong;
} z1,z2;
Les différents “champs” d’une union sont à la même
adresse physique. Ainsi, les égalités suivantes sont vraies :
&z1.entier == (int*)&z1.entlong
&z1.entier == (int*)&z1.flottant
&z1.entier == (int*)&z1.flotlong
III- Le s pointeurs et les structures
III.10 –les unions
Les unions ne sont pas destinées à faire des conversions.
Elles ont étés inventées pour utiliser un même espace
mémoire avec des types de données différents dans des
étapes différentes d’un même programme.
Elles sont, par exemple, utilisées dans les compilateurs.
Comme beaucoup de langages, le C offre la
possibilité de lire et d’écrire des données dans un
fichier. Pour des raisons d’efficacité, les accès à un
fichier se font par l’intermédiaire d’une mémoire-
tamp (on parle de buffer), ce qui permet de réduire
le nombre d’accès aux périphériques (disque...).
Pour pouvoir manipuler un fichier, un programme
a besoin d’un certain nombre d’informations :
l’adresse de l’endroit de la mémoire-tampon où se
trouve le fichier, la position de la tête de lecture, le
mode d’accès au fichier (lecture ou écriture).
#include <cstdlib>
#include <iostream>
}p1;
int n=0 ;
FILE * sortie ;
printf ("nom du fichier a creer : ") ;
scanf ("%20s", nomfich) ;
sortie = fopen (nomfich, "a+") ;
do { printf ("donnez id : ") ;
scanf ("%d", &p1.id) ;
printf ("donnez nom : ") ;
scanf ("%s", p1.nom);
printf ("donnez prenoms : ") ;
scanf ("%s", p1.prenoms) ;
printf ("donnez age : ") ;
scanf ("%d", &p1.age) ;
n++;
fwrite (&p1, sizeof(personne), 1, sortie) ;
}
while (n<=4) ;
fclose (sortie) ;
#include <cstdlib>
#include <iostream>
}p1;
FILE * entree ;
printf ("nom du fichier a lister : ") ;
scanf ("%20s", nomfich) ;
entree = fopen (nomfich, "r") ;
int tot=0;
int i=0;
while ( fread (&p1, sizeof(p1), 1, entree), ! feof(entree) )
{
printf("id : %d | ",p1.id);
printf ("nom : %20s | ", p1.nom) ;
printf ("prenoms : %20s | ", p1.prenoms) ;
printf ("age : %d \n", p1.age) ;
tot+=p1.age;
i++;
}) ;
printf("age total = %d \t",tot);
printf("age moyen = %d \n",tot/i);
fclose (entree) ;
I- Ouverture et fermeture de fichiers
Lorsqu’on désire accéder à un fichier, il est
nécessaire avant tout accès d’ouvrir
le fichier à l’aide de la fonction fopen.
Cette fonction, de type FILE * ouvre un fichier et lui
associe un flot de données.
Sa syntaxe est :
fopen("nom-de-fichier","mode")
La valeur retournée par fopen est
– soit un flot de données ;
– soit NULL si l’exécution de cette fonction ne se
déroule pas normalement.
I- Ouverture et fermeture de fichiers
Les différents modes d’accès
"r" ouverture d’un fichier texte en lecture
"w" ouverture d’un fichier texte en écriture
"a" ouverture d’un fichier texte en écriture à la
fin
"rb" ouverture d’un fichier binaire en lecture
"wb" ouverture d’un fichier binaire en écriture
"ab" ouverture d’un fichier binaire en écriture à
la fin
I- Ouverture et fermeture de fichiers
Les différents modes d’accès
"r+" ouverture d’un fichier texte en
lecture/écriture
"w+" ouverture d’un fichier texte en
lecture/écriture
"a+" ouverture d’un fichier texte en
lecture/écriture à la fin
"r+b" ouverture d’un fichier binaire en
lecture/écriture
"w+b" ouverture d’un fichier binaire en
lecture/écriture
"a+b" ouverture d’un fichier binaire en
lecture/écriture à la fin
I- Ouverture et fermeture de fichiers
Conditions particulières et cas d’erreur
r : le fichier doit exister, sinon c’est une erreur
w : le fichier peut ne pas exister. Dans ce cas, il
sera créée, et si le fichier existait déjà, son ancien
contenu est perdu.
a : le fichier peut ne pas exister. Comme pour le
cas précédent, si le fichier n’existe pas, il est
créée ; si le fichier existe déjà, son ancien
contenu est conservé.
Si un fichier est ouvert en mode ”écriture à la fin”,
toutes les écritures se font à l’endroit où était la
fin du fichier lors de l’exécution de l’ordre
d’écriture.
I- Ouverture et fermeture de fichiers
Les modes de communication standard
Il existe 3 modes de communication standard
lors de l’exécution d’un fichier par le système :
– stdin (standard input) : flot d’entrée (par
défaut, le clavier) ;
– stdout (standard output) : flot de sortie (par
défaut, l’´ecran) ;
– stderr (standard error) : flot d’affichage des
messages d’erreur (par défaut,l’´ecran).
Ces trois constantes se définies dans la
bibliothèque <stdio.h>.
I- Ouverture et fermeture de fichiers
Les modes de communication standard
NB : Il est fortement conseillé d’afficher
systématiquement les messages d’erreur sur stderr
afin que ces messages apparaissent à l’écran
même lorsque la sortie standard est redirigée.
Utilisation typique de fopen
#include <stdio.h>
FILE *fp;
...
if ((fp = fopen("donnees.txt","r")) == NULL) {
fprintf(stderr,"Impossible d’ouvrir le fichier
données en lecture\n");
exit(1);
}
II- Fermeture de fichiers : la fonction fclose
Elle permet de fermer le flot qui a été associé à
un fichier par la fonction fopen.
Sa syntaxe est :
fclose(flot)
où flot est le flot de type FILE* retourné par la
fonction fopen correspondante.
La fonction fclose retourne 0 si l’opération
s’est déroulée normalement et EOF si il y a eu
une erreur.
III- Les entrées-sorties formatées
III.1- La fonction d’écriture en fichier fprintf
La fonction fprintf, analogue à printf permet
d’écrire des données dans un flot. Sa syntaxe
est :
fprintf(flot,"chaîne de contrôle", expression1, .
. . , expressionn);
où flot est le flot de données retourné par la
fonction fopen. Les spécifications de format
utilisées pour la fonction fprintf sont les
mêmes que pour printf puisque :
printf(...) ⇐⇒ fprintf(stdout,...)
III- Les entrées-sorties formatées
III.2- La fonction de saisie en fichier fscanf
La fonction fscanf, analogue à scanf, permet de
lire des données dans un fichier. Sa syntaxe est
semblable `a celle de scanf :
fscanf(flot,"chaîne de contrôle", arg1, . . . ,
argn);
où flot est le flot de données retourné par
fopen. Les spécifications de format sont ici les
mêmes que celles de la fonction scanf.
IV- Impression et lecture de caractères dans un
fichier
IV.1- Lecture et écriture par caractère : fgetc et
fputc
Similaires aux fonctions getchar et putchar les
fonctions fgetc et fputc permettent
respectivement de lire et d’écrire un caractère
dans un fichier.
La fonction fgetc retourne le caractère lu dans
le fichier et la constante EOF.
IV- Impression et lecture de caractères dans un
fichier
IV.1- Lecture et écriture par caractère : fgetc et
fputc
lorsqu’elle détecte la fin du fichier. Son prototype
est :
int fgetc(FILE* flot);
où flot est le flot de type FILE* retourné par la
fonction fopen.
La fonction fputc écrit un caractère dans le flot de
données :
int fputc(int caractere, FILE *flot)
Elle retourne l’entier correspondant au caractère lu
(ou la constante EOF en cas d’erreur).
IV- Impression et lecture de caractères dans un
fichier
IV.2- Lecture et écriture optimisées par caractère :
getc et putc
Il existe également deux versions optimisées des
fonctions fgetc et fputc qui sont implémentées par
des macros. Il s’agit respectivement de getc et
putc.
Leur syntaxe est similaire à celle de fgetc et fputc :
int getc(FILE* flot);
int putc(int caractere, FILE *flot)
Ainsi, le programme suivant lit le contenu du
fichier texte entree.txt, et le
recopie caractère par caractère dans le fichier
sortie.txt:
Exercice
rappel
a & 0x0F permet d'isoler les 4 bits de poids
faible de a (masque des 4 bits LSB : 0x0F).
a & (1<<n) est nul si le nème bit de a vaut 0,
non nul s'il vaut 1.
mise à 0 ou à 1 de certains bits d'une valeur :
a = a | 0x0F met à 1 les 4 bits de poids faible
de a ;
a = a & ~(1<<n) met à 0 le nème bit de a.
return 0;
}
Exercice
Exercice 3.4 : écrire un programme qui affiche
horizontalement un histogramme des
fréquences des caractères d'un fichier texte.
On pourra distinguer les lettres majuscules des
lettres minuscules, les chiffres et les autres
caractères.
Le principe est le suivant :
constitution d'un tableau entier des effectifs,
à partir du caractère saisi,
calcul des fréquences (attention au type),
affichage (attention au type).
Exercice
Exercice 3.4 : histogramme des caractères d'un fichier
#define TAILLE 37
#define NLETTRES 26
#define NCHIFFRES 10
#include <stdio.h>
int main(void)
{/* définitions et initialisations */
int c, i, j ,k , tab[TAILLE] , somme =0;
float total = 0., pour = 0.;
for(i = 0 ; i < TAILLE ; i++) tab[i] = 0;
/* saisie des variables */
while((c = getchar()) !=EOF)
{
/* remplissage du tableau (lettres) */
if( (( c>= 'A') && (c <= 'Z')) ||
(( c>= 'a') && (c <= 'z')) ) tab[(c-'A') %32 ] ++;
else /* chiffres */
if ( (c>= '0') && (c <= '9')) tab[(c -'0')+NLETTRES]++;
else tab[TAILLE-1]++; /* divers */
} /* fin de la saisie */
Exercice
/* calcul de l'effectif total */
for(i = 0; i < TAILLE;i++) somme += tab[i];
printf("somme = %d\n",somme);
/* affichage des résultats */
for(i = 0; i < NLETTRES;i++) /* boucle sur les lettres */
{
printf( " %c ", i+'A');
pour = (float)tab[i] /(float) somme; /* sommation des pourcentages */
total += pour;
k = (int) ( 100 * pour);
for (j = 0; j < k ; j++) printf("x");
printf("\n");
}
for(i = NLETTRES; i < NLETTRES+NCHIFFRES; i++) /* boucle sur les chiffres */
{printf( " %c ", i+'0' - NLETTRES);
pour = (float)tab[i] /(float) somme;
total += pour;
k = (int) ( 100 * pour);
or (j = 0; j < k ; j++) printf("x");
printf("\n");
}
*/
Exercice
printf( " divers %s ");
pour = (float) tab[TAILLE-1] /(float) somme ;
total += pour;
k = (int) (100 * pour) ;
for (j = 0; j < k ; j++) printf("x");
printf("\n");
printf(" pourcentage traité : %6.2f\n", 100 *
total);
return(1);
}
Exercice
Exercice 5.3 : écrire un programme de
suppression d'une occurrence c dans une chaîne
de caractère s. La fonction de suppression est la
fonction squezze.
Exercice 5.4 : écrire un programme d'écriture des
caractères d'une chaîne dans l'ordre inverse.
Exercice 5.5 : écrire une fonction atoi qui assure
la conversion d'une chaîne numérique en un
nombre entier. Cette fonction de la bibliothèque
C retourne zéro si la chaîne est non numérique.
Exercice 5.6 : écrire un programme de recherche
de la ligne la plus longue d'un fichier. On devra
définir les fonctions :
getline saisie d'une ligne de texte,
copy recopie une chaîne de caractères dans
une autre.
Exercice
Exercice 3.5 : écrire un programme qui
dessine un histogramme des fréquences des
longueurs des mots d'un fichier de texte.
L'histogramme est dessiné horizontalement.
Les pourcentages correspondants sont
ensuite calculés. On se limitera à des mots
d'au plus 25 caractères.
Exercice
Exercice 3.2 : écrire un programme de
comptage des chiffres, lettres et autres
caractères spéciaux (blanc, tabulation, fin de
ligne). Les nombres des occurrences des
chiffres, des lettres de l'alphabet, des
caractères spéciaux, seront respectivement
stockées dans les variables chiffre, lettre,
autre.
Exercice
#include <iostream>
#include <stdio.h>
int main(int argc, char** argv) {
int c, nb = 0 , ntab = 0, nl = 0;
while (( c = getchar()) != EOF )
{if (c == ' ' ) ++ nb;
else if (c == '\t') ++ntab;
else if (c == '\n') ++nl;
}
printf("nombre de blancs =");
printf("%d \n",nb);
printf("nombre de tabulations = %d",ntab);
printf("\nnombre de lignes = %d\n",nl);
return 0;
}
Exercice
Exercice 3.1 : écrire un programme de
comptage du nombre de lignes, de mots, de
caractères du fichier d'entrée standard. Utiliser
ce programme sur n'importe quel fichier texte
Exercice
#include <iostream>
#include <stdio.h>
#define YES 1
#define NO 0