Date de première publication : 2014/12/8
Ce dernier TP vise à expérimenter les dernières notions vues en cours...
Fonctions à nombre d'arguments variable
Voici le code donné en cours :
double moyenne(int nombre, ...) {
double result = 0;
int nb = 0;
va_list liste;
va_start(liste, nombre);
while (nombre>0) {
result += nombre;
nb += 1;
nombre = va_arg(liste, int);
}
va_end(liste);
if (nb>0) result /= nb;
return result;
}
Compilez-le et exécutez-le, par exemple avec :
printf("%lf", moyenne(-1));
printf("%lf", moyenne(2, 2, 5, -1));
À votre avis, que fait le programme suivant :
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main()
{
struct dirent * lecture;
DIR *rep;
rep = opendir("." );
while ((lecture = readdir(rep))) {
printf("%s\n", lecture->d_name);
}
closedir(rep);
}
Créer une fonction à nombre d'arguments variable qui affiche le contenu des répertoires passés en paramètre,
soit en spécifiant le nombre de répertoires ou alors en terminant la liste avec une valeur comme NULL.
fonction1(2, "tp1", "tp2");
fonction2("tp1", "tp2", NULL);
Développer un code de tri générique
Compilez le code suivant et exécutez le code suivant :
void print(int t[], int n) {
for(int i = 0; i< n; ++i)
printf("%d ", t[i]);
printf("\n");
}
void tri(int t[], int n) {
for (int i = 1; i < n; i++) {
double cle = t[i];
int j = i - 1;
while (j >= 0 && t[j] > cle) {
t[j + 1] = t[j];
--j;
}
t[j + 1] = cle;
}
}
int main(){
int t [] = { 3, 1, 5, 2, 10, 7};
print(t, 6);
tri(t, 6);
print(t, 6);
return 0;
}
Si vous compilez avec l'option -S, vous allez obtenir un fichier qui contient l'assembleur de votre programme (vous pouvez aussi utiliser https://godbolt.org/)
On "voit" alors la définition des fonctions print, tri et main et les appels des fonctions print et tri.
Il faut écrire une fonction inferieur et modifier tri pour appeler cette fonction de comparaison.
int inferieur(int a, int b) {
return a < b;
}
La compilation avec "-S" montre alors la nouvelle fonctioninferieuret que la fonction tri appelle bien la fonction
inferieur.
Si l'on compile avec l'option -O2 (moins eau deux), le compilateur optimise notre code et élimine l'appel de la fonction inferieur
en remplaçant par le code de la fonction elle-même.
Paramétrer la fonction de comparaison
En ayant explicité la fonction de comparaison, il est maintenant possible de paramétrer l'algorithme de tri. Il faut alors écrire, par exemple, la fonction "inverse" à la fonction inferieur.
Vous avez deux possibilités :
- écrire une macro
TRI - écrire une fonction
tri2
Les trois paramètres sont les mêmes : le nom du tableau, la taille et la fonction de comparaison.
TRI(t, 6, inferieur);
tri2(t, 6, superieur);
Quand la macro est "compliquée", elle peut ressembler à cela :
#define MACRO(A, B, C) \
do { \
// code de la macro \
// chaque ligne se termine par un slash sauf la derniere \
} while (0)
Pour tri2, le dernier paramètre est un pointeur de fonction.
Faire abstraction du type à trier
Pour faire abstraction du type à trier, le plus simple est d'écrire une macro dont un des paramètres est le nom du type à trier :
TRI(int, t, 6, inferieur);
TRI(double, t, 12, superieur_double);
Si vous voulez plutôt utiliser une fonction, il faut manipuler des pointeurs void * dès que possible à l'image de la fonction de comparaison :
int inferieur(void * p1, void * p2) {
int * i1 = (int *)p1;
int * i2 = (int *)p2;
return *i1 < *i2;
}
Dans l'exemple qui est donné, le tableau est du type int [], on peut le voir comme int * puis finalement comme void *
Il reste alors à coder l'affectation entre deux valeurs de même type en utilisant la fonction standard memcpy
Utiliser la fonction qsort()
Vous devez maintenant adapter le code que vous avez fait pour appeler la fonction de tri qsort.
Il ne faut pas oublier que la fonction de comparaison est légèrement différente de ce que nous avons fait jusqu'à maintenant.
(elle en renvoie pas vrai ou faux mais -1, 0 ou +1)
Annuaire des languages
Fichiers binaires
- Faire une structure
donnee_tpour stocker un nom (char[100]), un langage (char[50]), une année (int) - Créer un tableau de structures avec quelques données :
donnee_t tab[] = { {"Gosling", "Java", 1993},
{"Van Rossum", "Python", 1991},
{"Stroustrup", "C++", 1983},
{"Ritchie", "C",1972}
};
- Sauvegarder ce tableau en mode binaire
- Lire ce qui a été sauvegardé...
| Auteur | Langage | Année |
| Backus John | FORTRAN | 1957 |
| Goldfarb Charles | GML | 1969 |
| Wirth Niklaus | Pascal | 1970 |
| Ritchie Dennis | C | 1972 |
| Kernighan Brian | C | 1972 |
| Sussman Gerald Jay | Scheme | 1975 |
| Steele Guy L | Scheme | 1975 |
| Naughton Patrick | Java | 1983 |
| Cox Brad | Objective C | 1983 |
| Berners Lee Tim | WWW | ~1990 |
| Van Rossum Guido | Python | 1991 |
| Gosling James | Java | 1993 |
| Lerdorf Rasmus | PHP | 1994 |
| Heich Brendan | Javascript | 1995 |
| Odersky Martin | Scala | 2003 |
| Hoare Graydon | RUST | 2006 |
| Lattner Chris | Swift | 2014 |
Tri des données
En utilisant qsort() et les bonnes fonctions de comparaison,
- afficher les langages suivant leur ordre d'apparition
- afficher les langages suivant l'ordre lexicographique
Questions
Que se passe-t-il dans les cas suivants :
- si les types "chaines de caractères" sont de type
char *? - si la structure est une liste chaînée et non plus un tableau ?


