Ce premier TP ne suppose aucune connaissance en C. Toutes les instructions
dont vous aurez besoin seront décrites. Afin de simplifier la
présentation déjà assez lourde, ces descriptions
ne seront pas toujours complètes. Vous pourrez trouver un
résumé plus complet ou plein de tutorials sur le web.
Pour tout savoir sur une instruction, vous pouvez aussi utiliser
man
.
L'éditeur de texte sert à écrire votre programme.
Le texte de votre programme sera donc enregistré dans un fichier.
Commencez par créer un répertoire (à l'aide de la
commande mkdir
) dans lequel vous rangerez tout ce qui concerne
ce TP. Dans ce répertoire, donc, lancez votre éditeur :
joe matrices.c
ou gvim matrices.c
ou xemacs matrices.c
.
Vous pouvez donner un autre nom que matrices.c
à votre
fichier, mais il est recommandé de terminer le nom du fichier
par .c
.
cc
ou gcc
de préférence).
Cette opération produit un autre fichier
contenant du code qui lui est exécutable. Vous n'avez ensuite plus
qu'à lancer ce fichier (en tapant simplement son nom) pour voir
votre programme s'exécuter.
/* Manipulations de matrices */
#include <stdlib.h> /* bibliothèque contenant les fonctions
de base comme exit */
#include <stdio.h> /* bibliothèque contenant les fonctions
d'entrée/sortie comme printf */
int main() /* La procédure principale, point de départ du
programme */
{
printf("Manipulations de matrices\n");
/* \n signifie passage à la ligne */
exit(0);
/* on sort du programme. La valeur 0 indique par convention que
le programme se termine normalement */
}
Avant de compiler, n'oubliez pas de sauvegarder le fichier contenant le programme. Pour compiler, dans la fenêtre shell tapez :
gcc -g -W -Wall matrices.c -o matrices
Puis, pour lancer le programme, tapez ./matrices
.
type variable;
ou type variable = valeur
;
où type
est le type de la variable. Pour l'instant, le
type d'une variable peut être int
pour un entier, ou
float
pour un flottant (nombre à virgule flottante).
valeur est la valeur initiale de la variable.
type variable[N];
ou
type variable[N] = { val,
... ,val };
N est un nombre entier positif (et pas une expression ou une
variable entière) spécifiant la taille du tableau.
C'est un pointeur vers une zone mémoire réservée
pour N objets de type type
.
La syntaxe
type variable[];
existe,
est est équivalente à
type *variable;
et
variable est juste un pointeur non alloué.
Pour accéder aux valeurs du tableau, utiliser variable[n]
où n
est n'importe quelle expression (nombre,
variable,...) ayant une valeur entre 0 et N-1.
Pour les tableaux à deux dimensions, on rajoute juste une paire de
crochets de plus :
type variable[N][M];
.
Pour bien comprendre les tableaux il faut les comprende comme des pointeurs.
Par exemple, un tableau à deux coordonnées réserve une zone mémoire pour N*M objets de typetype
, qui seront stockés ligne par ligne, mais le tableau pluridimensionnel ne peut être directement utilisé comme pointeur. Une façon portable de le faire est de posertype *p = &(variable[0][0]);
et l'élémentvariable[i][j]
est égal àp[i*M+j]
.
On voit donc quetype variable[][M];
est un pointeur non alloué vers des tableaux à M éléments (de typetype ligne[M];
) et est donc compatible avectype variable[N][M];
. Tandis quetype variable[][];
est un pointeur vers un pointeur vers un élément de typetype
, et n'est donc pas un tableau à deux dimensions.
Dans la suite, nous utiliserons de tels tableaux pour représenter les matrices.
L'écriture d'une procédure se fait de la facon suivante :
type_resultat proc(type1 arg1,...,typen
argn)
{
...
return expr;
}
Dans notre cas, la procédure prendra trois arguments : la matrice,
son nombre de lignes et son nombre de colonnes. Elle ne rendra aucun
résultat, type_resultat
sera donc void
. L'instruction
de fin de procédure sera simplement return;
.
printf
.
Cette fonction prend en premier argument une chaîne (des lettres ou
nombres entre ") qui définit ce qui sera imprimé. Dans cette
chaîne, tous les %d ou %f seront remplacés dans l'ordre par les
arguments suivants de printf
. %d indique que cette valeur sera un
entier, et %f un flottant.
Example : printf("Nous sommes le %d/%d/%d",23,2*4,annee);
imprimera
Nous sommes le 23/8/1996
si la valeur de annee
est 1996.
Exécutez la commande man printf
et regardez à quoi
ressemble une description exhaustive de la syntaxe d'une fonction C...
for
. Il faut définir une variable
entière, i
par exemple, et écrire
for(i=0; i<N; i++)
{
...
}
La valeur de i
est incrémentée de 1 à chaque
passage dans la boucle.
main
avec la matrice que
vous avez définie plus haut.
#define N 10
, par exemple, et qui
aura pour effet de remplacer partout dans le texte du programme N
par 10 avant d'appeler le compilateur.
En réalité, cette limitation est présente dans les vieilles définitions du langage C (K&R ou C89) mais pas dans la dernière version (C99) ni en C++. La norme C99 n'étant pas encore prise en compte par tous les compilateurs, on préfère ici se limiter à C89.
Modifiez votre programme pour n'utiliser que des valeurs définies par macro dans les déclarations de tableaux (y compris dans la procédure).
scanf
fonctionne de manière analogue à
printf
: le premier argument est un format et les autres arguments
les adresses de variables destinées à contenir les valeurs
lues au clavier.
Exemple : scanf("%d %f",&i,&f);
lit au clavier un entier, un
ou plusieurs blancs ou retours à la ligne, puis un flottant. L'entier
est rangé dans la variable i
, et le flottant dans la variable
f
.
Écrire la procédure de lecture et la tester. Avant d'appeler la procédure de lecture, demander dans la procédure principale le nombre de colonnes et de lignes à l'utilisateur.
Pour les utilisateurs plus confirmés, faire la lecture ligne
à ligne, sans demander le nombre de lignes et de colonnes à
l'utilisateur (hint : utiliser fgets
et sscanf
).
=
, la multiplication avec *
et
l'addition avec +
. Par exemple m[i][j]=t[k][j]*2+m[i][j]
affecte à m[i][j]
deux fois la valeur de t[k][j]
plus l'ancienne valeur de m[i][j]
.
Écrire une procédure mettant dans une matrice le résultat du calcul de la somme de deux autres matrices compatibles et une autre fonction faisant de même pour le produit.
malloc(n)
, dans la stdlib, alloue un espace mémoire
de taille n
. La fonction sizeof(type)
donne la taille
du type type
sur la machine sur laquelle on compile.
Réécrire les fonctions précédentes pour
qu'elles n'utilisent que la place mémoire nécéssaire
pour les matrices (et non N*N*sizeof(float)
quelle que soit la
taille réelle de la matrice). On pourra écrire deux
procédures pour lire la valeur de la matrice en [i][j]
ou
changer cette valeur.
gdb
sert à exécuter un programme pas à pas et à
afficher le contenu des variables. Il est nécessaire que la compilation
ait été faite avec l'option -g
.
Quelques tutoriels en français sont disponibles sur le web : ici ou là.