Vous êtes sur la page 1sur 14

INF155 – COURS 08

Les Classes d’Allocation,


L’Allocation Dynamique de Mémoire,
Les Algorithmes de Tri,
Et les Fichiers Textes

Eric Thé

Service des Enseignements Généraux

École de Technologie Supérieure

Hiver 2014
8.1 La Notion de « Storage Class » :
En langage C, une variable a toujours 2 attributs : le type de données et le type d’allocation
de mémoire (ou storage class). Il existe 4 types d’allocation de mémoire différents.

( auto )  c’est le type d’allocation par défaut, donc on utilise jamais ce préfixe. Les
variables auto sont des variables locales aux blocs-fonctions et elles sont
automatiquement détruites à la sortie du bloc de sa déclaration.

extern  ce type d’allocation est utilisé pour indiquer qu’une variable à déjà été
déclarée ailleurs globalement dans le projet actuel. Donc, le préfixe extern
dit au compilateur « va chercher cette déclaration de variable ailleurs ».
Exemple : Voici un petit projet à 2 fichiers-source.
Fich1.cpp Fich2.cpp
#include<....> int fnc(void)
int fnc(void); //prototype { extern int a;
int a=1, b=2; //variables globales! int b;
void main(){ a = b = 4;
printf("%d %d %d", a, b, fnc()); return (a+b);
} }
 Va afficher : 4 2 8

register  indique une allocation mémoire dans un registre de donnée du micro-


processeur (mémoire haute-vitesse). Ce type d’allocation est en fait une
demande au compilateur, il n’est pas garanti que cette demande puisse être
réalisée. Il est utilisé uniquement pour optimiser la performance de code.
Ex. register long i;
for (i=0; i < 2000000000; i++)
. . .
static  va forcer une variable locale à demeurer vivante après la fin de son bloc de
déclaration. L’espace mémoire de cette variable locale demeure réservé pour
la durée entière du programme (contrairement au type d’allocation auto).
L’initialisation, si elle est présente, ne sera faite qu’à la première rencontre de
la variable, sinon la variable statique est initialisée à zéro.
Exemple : int plus1(void) //implémente un compteur cyclique 0, 1, 2, .., 99, 0, 1..
{ static int cnt=0; //initialisation pour la 1ière fois seulement!
++cnt;
if (cnt==100) cnt = 0;
return cnt;
}
 Si on enlève le préfixe static, la fonction renvoie toujours « 1 »!!
 Attention!! Dans cet exemple, « cnt » n’est PAS une variable globale!

1
GET_NOM2.C : Fonction qui saisi un nom dans un tableau de char
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include"WinConsole.h" //pour "clrscr", "clreol" et "gotoxy"

#define BKSPACE 8
#define RETURN 13
#define MAXL 60

char * getnom(int, int); //prototype de la fonction de saisie

int main()
{ char * nom;

clrscr();
gotoxy(10,5);
printf("Entrez une chaîne de caractères : ");

nom = getnom(45, 5);

gotoxy(10,7); printf("chaine = [%s] longueur = %d\n", nom, strlen(nom));


system("pause");
return 0;
}

/* GET_NOM : va saisir un nom a partir de la position-écran (px, py) */


char * getnom(int px, int py)
{ static char buff[MAXL+1]; //variable locale "static" ne sera pas détruite
char ch;
int l = 0, fini = 0;

do {
ch = getch();
switch (ch) { //selon le caractère saisi au clavier..
case BKSPACE : //BKSPACE: on efface une lettre dans la chaine
if (l) {
--l; buff[l] = '\0';
--px; //on recule px de -1 à l'écran
gotoxy(px, py); clreol();
}
break;
case RETURN :
fflush(stdin); fini = 1; //vider le buffer "stdin"
break;
default : //tout autre char: on ajoute une lettre
if (l<MAXL) { //si il reste de la place..
buff[l] = ch;
l++; buff[l] = '\0';
gotoxy(px,py); printf("%c", ch);
px++; //on déplace px de +1 a l'écran
}
}
} while (!fini); //boucler jusqu'a la touche "ENTER"

return buff; //on renvoie l'adresse (char *) du tableau local "buff"


}

2
8.2 L’Allocation Dynamique de Mémoire :
En C, l’espace-mémoire est divisée en deux morceaux: l’espace de la pile (stack size) et
l’espace-tas (heap size). L’espace de la pile est réservé pour entreposer les appels de
fonctions en incluant toutes les variables locales de ces fonctions. Cet espace est assez limité
et avec Visual C++ il est presque impossible de savoir la dimension de l’espace-pile
disponible. Donc, lorsqu’on utilise des tableaux, on risque parfois de “défoncer” la pile!
Pour éviter ces problèmes, le programmeur qui pense utiliser des structures énormes dans ses
programmes fait appel à l’espace disponible dans le tas (heap). Les variables qui permettent
d’accéder à l’espace du tas sont des pointeurs. En fait, ce sont des pointeurs simples qui se
trouvent dans l’espace de la pile et leurs valeurs sont en fait une adresse d’un emplacement
plus gros situé, lui, dans le tas. L’allocation dynamique, c’est la capacité d’obtenir du
système d’exploitation (ou SE) des blocs de mémoire qui viennent du « tas » augmentant
donc la mémoire déjà alloué au programme en compilation.
491
TAS (HEAP)

491 T PILE (STACK)

Le SE possède une réserve d’octets libres (heap size) dans laquelle le programmeur puise
grâce à une demande explicite. Nous verrons comment on peut l’utiliser pour permettre
l’utilisation de “très gros tableaux” dans nos programmes, et aussi comment créer des
structures à dimension dynamique.
En C, les fonctions malloc, calloc et realloc remplissent cet usage et renvoient des
pointeurs génériques de type void * sur le premier octet du bloc offert. Lorsque le
pointeur retourné par le SE est NULL, ceci indique que l’allocation dynamique a échouée.
Les Fonctions malloc et calloc :
Avec les fonctions malloc et calloc de la librairie <stdlib.h>, on peut obtenir de
l’allocation dynamique de mémoire durant l’exécution (contrairement aux tableaux statiques).
Syntaxe générale : pointeur = (type *) calloc(n, sizeof(type));
pointeur = (type *) malloc(n * sizeof(type));

nombre d’éléments désirés


dimension d’un élément du tableau dynamique
Exemple : int *tab, n;
/* Au départ, la variable « tab » n’est PAS un tableau. Elle est une “possibilité” de
tableau. Pour réserver l’espace-mémoire de « n » cellules, il faut utiliser la fonction
« calloc » ou « malloc ». Dans les cas que nous allons voir, nous utiliserons UNE et
UNE SEULE FOIS le « calloc » ou « malloc » sur la variable-pointeur. */

3
printf("Entrez la dimension du tableau : ");
scanf("%d", &n);
Soit a) tab = (int *) calloc(n, sizeof(int));
Ou b) tab = (int *) malloc(n * sizeof(int));
/* Le tableau est maintenant prêt à être utilisé. */
NOTE : La fonction « calloc » va initialiser toutes les cases de l’espace-mémoire
réservé à 0. « malloc » ne nettoiera pas l’espace-mémoire réservé.
Un bloc d’octets obtenu en allocation dynamique n’a pas de « storage class » et la remise en
liberté d’un bloc de mémoire est donc à la charge du programmeur. Quand on n’a plus
besoin d’une variable créée dans le tas avec « calloc » ou « malloc », il faut libérer
l’espace-mémoire avant la fin du bloc de définition du pointeur. Sinon cette partie de
mémoire est irrémédiablement perdue jusqu’à la fin du programme !
La fonction free en C remplie cette tâche. Mais attention, tenter de libérer explicitement,
avec free, une zone de mémoire non précédemment allouée ou déjà “désallouée”, est une
erreur et rendra le comportement du SE imprévisible. Pour plus de sureté, une fois la
mémoire libérée, on assigne explicitement au pointeur la valeur NULL.
free(tab); //libérer la mémoire réservée
tab = NULL;
Remarquez qu’un tableau statique ou dynamique s’utilise de la même façon. La forme
dynamique n’est visible qu’à travers le calloc / malloc et le free. En fait, pointeurs et
tableaux sont intimement reliés. Obtenir, se servir, puis détruire un tableau dynamique est
juste un peu plus technique que de travailler avec un tableau statique.
INVERSE.CPP : Programme qui va remplir et inverser le contenu d'un tableau dynamique.
#include <stdio.h>
#include <stdlib.h>
void main(void)
{ void inverse(int *, int); //prototype local de la fonction
int *tab, i, n;

system("cls");
do {
printf("\n n = "); //demander et valider la dimension désirée du tableau
scanf("%d", &n);
} while (n <= 1);

tab = (int *) malloc(n*sizeof(int)); //allocation dynamique pour le tableau

for (i=0; i<n; ++i) {


printf("tab[ %d ] = ", i);
scanf("%d", &tab[i]); //remplir le tableau
}

printf("\n\n");
for (i=0; i<n; ++i) printf("%d, ", tab[i]);

4
/* inversion du tableau */
inverse(tab, n);

printf("\n\n");
for (i=0; i<n; ++i) printf("%d, ", tab[i]);

free(tab); tab = NULL; //libérer l'espace-mémoire


system("pause");
}

//fonction qui inverse le contenu du tableau « x » de taille « n »


void inverse(int x[], int n)
{ int i, temp;

for (i=0; i<(n/2); ++i) { //on va jusqu'a la moitié du tableau seulement!


temp = x[i];
x[i] = x[n-i-1];
x[n-i-1] = temp;
}
}

TABDYNAM.CPP : Version dynamique du programme TABNOMS.CPP.


#include<stdio.h>
#include<stdlib.h> //nécessaire pour la fonction malloc()
#include<assert.h> //nécessaire pour la fonction assert()
#include<string.h>

#define MAXCH 50 //nombre MAX de lettres dans une chaine


#define MAXELE 10 //nombre de noms dans le tableau

typedef char * Tptrch; //type POINTEUR global pour les chaines dynamiques
typedef Tptrch Ttablo[MAXELE]; //type global pour le tableau de 10 noms

void init_tab(Ttablo); //mets tous les pointeurs du tableau a NULL


void lire_tab(Ttablo); //va saisir les noms du tableau en interactif
void tri_tab(Ttablo); //va trier la liste en ordre alphabétique
void aff_tab(Ttablo); //afficher le contenu du tableau
void main()
{ Ttablo tab; //déclaration de la variable-tableau

system("cls");
init_tab(tab);
lire_tab(tab);
tri_tab(tab);
system("pause");

aff_tab(tab);

for (int i=0; i<MAXELE; i++) //libérer les allocations dynamiques


{ free(tab[i]); tab[i]=NULL; }
system("pause");
}

5
void init_tab(Ttablo tb) //mets tous les noms du tableau = vide
{ for (int i=0; i<MAXELE; i++)
tb[i] = NULL; // = pointeur vide
}

void lire_tab(Ttablo tb) //va remplir le tableau des noms


{ char buff[MAXCH+1]; //la variable-tampon DOIT ETRE DE TYPE "char []"
for (int i=0; i<MAXELE; i++) {
printf("\nEntrez le nom #%d : ", i+1);
gets(buff); //OU avec : fgets(buff, MAXCH, stdin); ...mais
//fgets() ne remplace pas le '\n' de la fin!!!
tb[i] = (char *) malloc(MAXCH+1); //allocation dynamique!!!!!
assert(tb[i]); //validation automatique du pointeur
strcpy(tb[i], buff);
}
}

void aff_tab(Ttablo tb) //affiche le contenu du tableau


{ for (int i=0; i<MAXELE; i++)
printf("\nNom #%d : %s", i+1, tb[i]);
}

void swap(Tptrch s1, Tptrch s2) //échange de deux chaines avec "strcpy()"
{ char tmp[MAXCH+1]; //la variable-tampon DOIT ETRE DE TYPE "char []"
strcpy(tmp, s1); strcpy(s1, s2); strcpy(s2, tmp);
}

void tri_tab(Ttablo tb) //avec méthode de tri par sélection


{ int i, indice, j;
for (i=0; i<MAXELE-1; i++)
{ indice=i;
for (j=i+1; j<MAXELE; j++)
if (strcmp(tb[j], tb[indice]) < 0) indice = j;
swap(tb[indice], tb[i]); //échange de deux noms
}
}

8.3 Les Algorithmes de Tri :


Principe de base : Prendre un tableau de valeurs en désordre et réussir à mettre les valeurs en
ordre en utilisant un minimum de comparaisons et/ou d’échanges.
1. Tri-Bulle (tri par échanges)
Comparer chaque élément avec son voisin de droite et les échanger s’ils ne sont pas
respectivement dans le bon ordre. Répéter ainsi jusqu'à ca que le plus grand élément
se retrouve dans la dernière case. Refaire la même chose avec et les N-1 autres
éléments, ensuite avec les N-2 éléments restants, etc…
/* BULLE.CPP : Exemple de programme qui tri des valeurs (x) dans l'ordre croissant... */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "WinConsole.h" //pour le gotoxy()

6
#define N 15 //dimension du tableau
void BULLE(int *, int); //tri-bulle (sans optimisation)
void BULLE2(int *, int); //tri-bulle avec drapeau

void main(void)
{ int i, x[N];
system("cls");
srand(time(NULL)); //initialiser le "random"
gotoxy( 1, 1); printf("Avant le tri");
gotoxy(31, 1); printf("Apres le tri");
for (i=0; i<N; ++i) {
x[i] = rand()%250; //remplir le tableau
gotoxy( 1, i+3); printf("(%4d)", x[i]); //afficher verticalement
}
BULLE(x, N); //faire le tri des valeurs
for (i=0; i<N; ++i) {
gotoxy(31, i+3); printf("(%4d)", x[i]); //afficher verticalement
}
system("pause");
}
void permute(int *a, int *b) //va échanger deux valeurs du
tableau
{ int temp = *a;
*a = *b;
*b = temp;
}

/* la technique de tri utilisée est celle du tri BULLE */


void BULLE(int x[], int nb)
{ int i, j;
for (i = nb-1; i > 0; i--) {
for (j=0; j < i; j++) {
if (x[j] > x[j+1]) //si un élément est supérieur a son voisin,
permute(&x[j], &x[j+1]); //on les échangent
}
}
}

/* la technique de tri utilisée est celle du tri BULLE avec drapeau!!! */


void BULLE2(int x[], int nb)
{ int i, j,
fini=0; //drapeau qui indiquera si on a besoin de continuer a trier
i = nb-1;
while ((fini != 1) && (i > 0)){ //tant que l'on doit continuer a trier
fini = 1;
for (j=0; j < i; j++) {
if (x[j] > x[j+1]) { //si un élément est supérieur a son voisin,
fini = 0; //il faudra refaire une autre passe..
permute(&x[j], &x[j+1]); //on les échangent
}
}
--i;
}

7
}
2. Tri par Sélection
Chercher la liste au complet pour trouver le plus petit élément et le mettre à sa place.
Chercher ensuite les N-1 autres éléments et mettre le plus petit à la deuxième position
du tableau. Répéter ainsi pour les N-2 autres éléments, les N-3 autres éléments, etc...
(voir exemple TABDYNAM.CPP et aussi SELECT.CPP)

3. Tri par Insertion


Insérer un élément où il devrait être dans la liste. On commence avec de deuxième
élément. On l’insèrera avant le premier si cela est nécessaire. Ensuite, prendre le
troisième élément et l’insérer où il devrait être relativement aux deux premiers
éléments. Ensuite, on va insérer le quatrième élément parmi les trois premiers et ainsi
de suite jusqu’au dernier élément du tableau. Dans le cas d’une « insertion », les
autres éléments doivent être décalés (vers la droite) pour laisser une place libre.
Fonction extraite du programme INSERT.CPP :
/* la technique de tri utilisée est celle du tri par INSERTION */
void INSERTION(int x[], int nb)
{ int i, a_inserer, position;
//On insère les n-1 éléments de x[] dans la zone triée.
for (i = 1; i < nb; i++) {
a_inserer = x[i];
position = i-1;
//Tant que l'élément a insérer est plus petit que ses précédents,
//on les déplacent.
while (position>=0 && (x[position] > a_inserer)) {
x[position + 1] = x[position];
position--;
}
//On insère l'élément x[i] au bon endroit parmi les valeurs déjà
triées.
x[position + 1] = a_inserer;
}
}

8.4 Les Fichiers Texte :


Un fichier texte (*.txt ou *.dat) peut être vu comme une suite de caractères ASCII.
Un programme peut lire des données à partir d’un fichier texte (plutôt qu’à partir du clavier),
ou bien écrire des résultats dans un fichier texte (plutôt qu’à l’écran).
En langage C, le type FILE * (de <stdio.h>) est utilisé pour déclarer un pointeur à un
fichier externe à partir d’un programme. On accède ensuite au fichier à partir de ce pointeur.
Ex. Déclaration de 2 pointeurs de fichiers :
FILE *fentree, *fsortie;
Pour ouvrir un fichier et associer son adresse au pointeur FILE *, on utilise :
pointeur_FILE = fopen("nom", "mode");

8
nom complet avec le chemin
d’accès si nécessaire
Les « modes » d’ouverture de fichier avec « fopen » :
"r"  ouvrir le fichier pour la lecture seulement
"w"  ouvrir le fichier pour écriture à partir du début
"a"  ouvrir le fichier pour écriture à partir de la fin (ajouter au fichier)
"r+"
"w+" ouvrir le fichier pour la lecture + écriture
Ex. fentree = fopen("c:\\donnees.txt", "r");
fsortie = fopen("c:\\bidon\\result.txt", "w");
Ensuite, pour faire la lecture de données à partir du pointeur fentree on utilise :
char fgetc(FILE *ptr);  renvoie le prochain caractère à lire dans le fichier *ptr.

char *fgets(char *str, int n, FILE *ptr);  va lire une chaîne de caractères
de longueur maximale (n-1) dans la
chaîne *str à partir du fichier *ptr
NOTE : la fonction renvoie également un pointeur sur le début de la chaîne lue.

int fscanf( pointeur_FILE, liste d’arguments );

comme avec le scanf()


Pour écrire des données dans le fichier associé à fsortie on utilise :
char fputc(char c, FILE *ptr);  va écrire le caractère c à la fin du fichier *ptr.
NOTE : En cas de réussite, la fonction renvoie le caractère qui à été écrit dans le fichier.

int fputs(const char *str, FILE *ptr);  va écrire la chaîne de caractères *str
à la fin du fichier pointé par *ptr. La
fonction renvoie le nombre de
caractères ajoutés au fichier.

int fprintf( pointeur_FILE, liste d’arguments );

comme avec le printf()


Exemple : Voici le contenu du fichier « donnees.txt » ;
3 8 12 7 9 6 <EOF> //EOF  caractère de fin de fichier
Pour faire la somme des valeurs dans ce fichier :
int val, somme=0;
FILE *fentree, *fsortie;
fentree = fopen("donnees.txt", "r"); //ouverture du fichier

9
while (fscanf(fentree, "%d", &val)==1)
somme += val;

Pour écrire cette somme dans le fichier de sortie :


fsortie = fopen("result.txt", "w"); //créer le fichier-résultat
fprintf(fsortie, "somme = %d\n", somme);
fclose(fentree); IMPORTANT, pour
fclose(fsortie); fermer les deux fichiers
NOTEZ : Quand on utilise le mode "w" ou "a" avec « fopen », si le fichier demandé
n’existe pas à l’emplacement courant, « fopen » va créer ce fichier. Avec le mode "r",
le fichier doit déjà exister. Si le fopen n’a pas fonctionné, il va renvoyer l’adresse NULL.
Validation correcte d’un fopen :
fentree = fopen("donnees.txt", "r"); //ouverture du fichier
if (fentree==NULL) {
printf("Erreur d’ouverture de fichier");
exit(1); //sortie immédiate du programme
}
Autres fonctions de fichiers utiles :
rewind(FILE *);  renvoie le pointeur au début du fichier pour relire/réécrire
feof(FILE *);  fonction qui renvoie 1 si le pointeur est positionné à la fin du
fichier, sinon renvoie 0.

INTEGER.CPP : Exemple de lecture de fichier texte avec des entiers


#include <stdio.h>
#define FIN -1 //valeur spéciale de fin de données
void main(void)
{ FILE *entree; //variable pointeur-fichier
int n;
printf("Entrer des chiffres ... <-1> lorsque vous aurez termine\n\n");
entree = fopen("essai.txt", "w"); //ouverture du fichier, mode écriture
do {
scanf("%d",&n); //on saisie un entier au clavier..
if (n != FIN)
fprintf(entree,"%d ",n); //..et on copie dans le fichier texte
} while (n != FIN); //..jusqu'au caractère de fin de
données
fclose(entree); //fermer le fichier
entree = fopen("essai.txt", "r"); //ré-ouvrir le fichier en mode lecture
printf("\n\nContenu du fichier ESSAI.TXT\n\n");
fscanf(entree,"%d",&n); //lire un entier à partir du fichier
while (!feof(entree)) { //tant que c'est pas la fin du fichier

10
printf("%d ",n); //..écrire l'entier lu a l'écran
fscanf(entree,"%d",&n); //..et lire le prochain entier
}
fclose(entree); //fermer le fichier
}
IOTEST.CPP : Exemple de gestion de fichiers texte avec plusieurs types
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <assert.h> //pour la fonction de validation automatique “assert()”
void copie (FILE *, char *); //pour copier d'un fichier vers un autre
void echoe (char *); //pour afficher contenu d'un fichier a l'écran
char message[] = " TOUT EST OK! ";
/*-----------------------------------------------------------------------*/
int main(void)
{ FILE *stream; //variable pointeur-fichier
int i = 100;
char c = 'C';
float f = 1.234;
int t[3] = { 11, 22, 33 };
stream = fopen("c:\\bidon\\temp1.txt", "w"); /* mode: écrire */
assert(stream); /* validation du fopen */

fprintf(stream, "\n%8d %3c %10.3f\n", i, c, f); //écrire 3 valeurs


for (i=0; i<3; ++i)
fprintf(stream, "%d ", t[i]); //écrire contenu du
tableau
fprintf(stream, "\n%s", message); //écrire la string

fclose(stream);
stream = fopen("c:\\temp\\temp1.txt", "r"); /* mode: lecture */
assert(stream); /* validation du fopen */

copie(stream, "c:\\temp\\temp2.txt"); //faire une copie dans temp2


fclose(stream);

echoe("c:\\temp\\temp2.txt"); //afficher temp2 a l'écran


system("pause");
return 0;
}
/*-----------------------------------------------------------------------*/
void copie (FILE* in, char * nom) //pour copier d'un fichier vers un autre
{ FILE *out = fopen(nom, "w"); /* mode: ecrire */
assert(out);
while (!feof(in)) //tant que c'est pas la fin du
fichier..
{ fputc(fgetc(in), out); } //..copier un caractère de "in" vers "out"
fclose(out);
}
/*-----------------------------------------------------------------------*/
void echoe (char * source)
{ FILE *out = fopen(source, "r"); /* lecture */
assert(out); /* validation du fopen */

11
while (!feof(out)) //tant que c'est pas la fin du
fichier..
{ putchar(fgetc(out)); } //..écrire a l'écran le caractère de "out"
fclose(out);
}
/*-----------------------------------------------------------------------*/

LECTFICH.C : Exemple pour lire une matrice de nombres réels à partir d'un fichier
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<assert.h>

#define MAXDIM 20 //ceci est une taille MAXIMALE, pas la taille actuelle!

typedef double matrice[MAXDIM][MAXDIM];


/*----------------------------------------------------------------------*/
/* Ici l'affichage de la matrice est rectangulaire. */
void affich_mat(const matrice M , int taille)
{ int i,j;

for (i=0; i<taille; i++) {


for (j=0; j<taille; j++)
printf("%7.2lf", M[i][j]);
printf("\n"); //après chaque ligne affichée, on change de ligne
}
}

/*----------------------------------------------------------------------*/
/* Fonction pour lire une matrice d'un fichier texte.
Elle renvoie la taille réelle de la matrice lue.
Le format du fichier est standard : la première ligne nous donne la
taille, et les lectures suivantes sont les éléments de la matrice. */
int flire_mat(char * nom_fichier, matrice M)
{ FILE * fichier;
int i, j, taille;
double x;

fichier = fopen(nom_fichier,"r");
assert(fichier);

fscanf(fichier, "%d", &taille); //lecture du nombre de lignes de données

if (taille <= MAXDIM) {


for(i=0; i<taille; i++)
for(j=0; j<taille; j++){
fscanf(fichier, "%lf", &x);
M[i][j] = x; /* NOTEZ!! on utilise une variable temporaire pour lire
du fichier et ensuite on l'envoi dans la matrice */
}
}
fclose(fichier);
return taille;
}

/*------------------------------------------------------------------------*/
int main()

12
{ matrice valeurs; /* la matrice des valeurs */
int taille;

taille = flire_mat("dat10x10.txt", valeurs); /* on rempli la matrice.. */


affich_mat(valeurs, taille); /* ..et on l'affiche */
return 0;
}

13

Vous aimerez peut-être aussi