TP n°1 : familiarisation avec le langage

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.

1  Compiler

1.1  Mise en place

Pour bien travailler, vous aurez besoin de trois fenêtres : une fenêtre pour lire le sujet du TP et deux autres pour programmer. Vous pouvez utiliser un écran virtuel pour lire le TP et un autre pour les deux fenêtres de programmation. Ces deux fenêtres sont d'une part un éditeur de texte et d'autre part un shell (une fenêtre dans laquelle vous pouvez taper des instructions).

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 (dossier) à l'aide de la commande mkdir tp1, dans lequel vous rangerez tout ce qui concerne ce TP. Entrez dans ce répertoire par cd tp1, puis lancez votre éditeur favori : xemacs toto.c & ou vim toto.c ou pico toto.c ou joe toto.c. Vous pouvez donner un autre nom que toto.c à votre fichier, mais il faut terminer le nom du fichier par .c.

Il existe des environnements de programmation plus élaborés que la technique à deux fenêtres décrite ci-dessus, mais celle-ci a l'avantage d'être utilisable en toute circonstance et de bien dissocier la fonction d'édition des autres.

1.2  Le cycle de compilation

Le fichier contenant le texte de votre programme ne peut pas être exécuté directement. Pour cela il faut d'abord compiler votre programme (avec 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.

1.3  Un exemple

Tapez le programme suivant (vous pouvez vous dispenser des commentaires) :

/* Affichage de messages */
#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("Hello world !\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 toto.c -o toto

Puis, pour lancer (exécuter) le programme, tapez ./toto.

2  Structures de données pour les nombres complexes

2.1  Variables de type simple

En C, toutes les variables doivent être déclarées. Cela permet de définir leur type et de leur allouer de la mémoire. L'instruction permettant de déclarer une variable est :

type variable; ou type variable = valeur ;

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.

2.2  Tableaux

Pour déclarer une variable destinée à contenir un tableau, on écrit :

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] n est n'importe quelle expression (nombre, variable,...) ayant une valeur entre 0 et N-1.

2.3  Application

Modifiez le programme précédent pour y déclarer un tableau de taille 2, contenant des flottants, initialisé avec les valeurs de votre choix.

Dans la suite, nous pourrons utiliser de tels tableaux pour représenter les nombres complexes.

2.4  Structures

Pour déclarer une variable "structure" destinée à contenir plusieurs variables, on écrit :

struct { type1 champ1; ... typeN champN; } variable; ou
struct nom { type1 champ1; ... typeN champN; } variable;

ce qui est équivalent à la séquence de déclarations
type1 variable.champ1;
...
typeN variable.champN;

2.5  Application

Modifiez le programme précédent pour y déclarer une structure contenant deux flottants, initialisée avec les valeurs de votre choix.

Dans la suite, nous pourrons utiliser de telles structures pour représenter les nombres complexes.

2.6  Définition de type

Pour définir un nouveau type, on utilise une syntaxe analogue à la déclaration de variable, précédée de typedef. Pour définir un type complexe, on pourra donc faire

typedef float complexe[2]; ou typedef struct { float x; float y; } complexe;

3  Impression d'un complexe

Nous allons écrire une procédure permettant d'imprimer les complexes que nous manipulerons.

3.1  Procédures

Les procédures permettent d'améliorer la lisibilité des programmes en réunissant en un endroit séparé les instructions correspondant à une fonction particulière. Cela permet aussi de n'écrire qu'une seule fois ces instructions qui peuvent être utilisées plusieurs fois.

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 un argument : le complexe. Elle ne rendra aucun résultat, type_resultat sera donc void. L'instruction de fin de procédure sera simplement return;.

3.2  printf

Pour imprimer des résultats, on utilise la fonction 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...

3.3  Application

Écrire la procédure imprimant un complexe, pou les deux types décrits ci-dessus. La tester en l'appelant dans la procédure main avec la matrice que vous avez définie plus haut.

4  Utilisation d'un débuggueur

La commande 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 .

Exécutez les programmes précédents pas à pas, sous gdb.