Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercices pour débutants en C

Au menu : zSommeChiffres (nombres, algo)

10 novembre 2008 à 21:14:45

Ce que j'appelle fonction systèmes, c'est toutes les fonctions déjà prête, au temps pour moi si je ne suis pas clair =)

Autres avantages: savoir comment marche certaines fonctions (ça peut toujours être utile ;) )

@Jaloyan1: si tu sais pas recoder strlen ou putstr ou islower ou je ne sais quoi, c'est assez problématique...

La correction tient sur environ 50 lignes je dirais, ce qui n'est pas énorme hein ;)
  • Partager sur Facebook
  • Partager sur Twitter
10 novembre 2008 à 21:17:45

Citation : crys'

Jaloyan1 : je ne comprend pas trop ta réaction : réécrire strlen est un jeu d'enfant, idem pour isupper ou islower. Il faut juste aller jeter un coup d'œil à la table ASCII et c'est codé en deux temps trois mouvements. Vraiment, cet exercice est simple et très utile (manipulation de char et de tableau de char), l'idée n'est pas de moi mais bien du posteur (Invading). ;)
Cet exercice vous permet donc, comme dit précédemment, de vous entraîner à la manipulation du type char mais aussi, ne l'oublions pas, de vous familiariser avec la norme ASCII. Que demander de plus ?


Perso, je recommanderais de faire l'exercice sans regarder la table ASCII (eh oui, c'est possible). Le code sera bien meilleur (plus portable surtout).
  • Partager sur Facebook
  • Partager sur Twitter
10 novembre 2008 à 21:19:57

Citation : yoch

Perso, je recommanderais de faire l'exercice sans regarder la table ASCII (eh oui, c'est possible). Le code sera bien meilleur (plus portable surtout).


C'est aussi une solution mais laissons nos zér0s coder ! :D
  • Partager sur Facebook
  • Partager sur Twitter
10 novembre 2008 à 21:31:55

Je suis d'accord avec yoch, même si parfois faut regarder une fois la table ASCII si on y connait rien ;). SI on peut eviter, autant le faire, le code n'en sera que plus lisible et simplifie!
  • Partager sur Facebook
  • Partager sur Twitter
10 novembre 2008 à 21:57:20

Citation : yoch


Perso, je recommanderais de faire l'exercice sans regarder la table ASCII (eh oui, c'est possible). Le code sera bien meilleur (plus portable surtout).


Moi, je ne saurais pas du tout choqué qu'on utilise le codage ascii. Si le programmeur aujourd'hui en herbe doit un jour coder sous un autre charset, il saura s'adapter. L'apprentissage du C est difficile parce que certains (et beaucoup en fait) s'ingénuent à le compliquer.
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 5:48:22

salut,



Citation : Invading

La correction tient sur environ 50 lignes je dirais, ce qui n'est pas énorme hein ;)


:-°:-°:-° Si, c'est ENORME... :p

Rassurez moi, on doit juste recoder la fonction:
char *strcapitalize(char *tab);
?

Donc, pas d'affichage, pas de saisie dans la fonction?... Sinon, je me suis planté dans ma soluce (Qui est loin de faire 50 lignes, j'ai certainement oublié quelque chose... :p:p )

a++
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
11 novembre 2008 à 9:06:13

Elle affiche aussi cette fonction hein ;)
Pas de saisie de chaine, pour tester vous aurez juste a la modifier, tout simplement.
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 12:06:06

Citation : GurneyH

char *strcapitalize(char *tab);


je comprends pas trop le * devant la fonction

par contre :
char strcapitalize(char *tab);

je comprends que c'est une fontion dont :
son nom est : strcapitalize
elle renvoie un resultat de type char
elle prend en parametre d'entree une variable "tab" de type char
suis je dans le vrai ?
merci
@+
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 12:55:40

Qu'est-ce qu'elle retourne exactement ? ^^ car renvoyer le tableau ne servirait à rien si je ne m'abuse...
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 13:28:24

tu as raison j'ai modifié, c'est la fonction qui renvoie le resultat, et non pas "tab"

char *strcapitalize(char *tab);


par contre cela je comprends toujours pas!
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 13:29:39

Ce n'est qu'un exemple de prototype. Du moment qu'il affiche ce qu'il faut, c'est bon =)
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 13:32:46

Citation : invading

Ce n'est qu'un exemple de prototype. Du moment qu'il affiche ce qu'il faut, c'est bon =)



peut être mais j'aimerais bien comprendre, plutot que de recopier quelque chose qui est flou pour moi. C'est le * qui me gêne devant le nom de la fonction ! :-°
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 13:37:50

Oui oui ^^' mais on cherche juste à comprendre :p

char *strcapitalize(char *tab);


Cette fonction prend en paramètre un tableau de char et je suppose qu'elle retourne ce même tableau une fois modifié ^^ Or, on en a vraiment pas besoin vu qu'un tableau est un pointeur. Dans mon optique, ça serait plutot :

void strcapitalize(char *tab);
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 13:50:08

salut,

char *sStrCapitalize(char *tab);

ça permet de faire :
printf("%s", zStrCapitalize(string));



oups, on a pas le droit à printf... :p

Beaucoup de fonctions standards ont un prototype similaire...

a++
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
11 novembre 2008 à 13:57:50

bon,
merci pour ta reponse.
je ranges cela dans une petite case, pour comprendre ultérieurement.....
@+
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 14:09:51

Merci de ta réponse GurneyH^^ J'ai enfin compris >.<
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 14:30:34

Citation : GurneyH

oups, on a pas le droit à printf... :p


Attention, quand on dit qu'on doit recoder toute fonction utilisée dans strcapitalize, ce sont uniquement toutes les fonctions appelées dans strcapitalize. Dans le reste du code, printf et tout le reste est autorisé mais l'algorithme de l'exercice doit se trouver uniquement dans strcapitalize.
On peut par exemple imaginer un main comme cela :
int main()
{
   char s[]={"sAlUt tOi !!"};
   printf(s); // ou printf("%s",s) pour ceux qui préfère : affiche "sAlUt tOi !!"
   printf("\n\n");
   printf(strcapitalize(s)); // affiche "Salut toi !!"
   return 0;
}

Ou alors si on préfère laisser la fonction de type void :
int main()
{
   char s[]={"sAlUt tOi !!"};
   printf(s);
   printf("\n\n");
   strcapitalize(s);
   printf(s);
   return 0;
}


zx-spectrum : char* est char n'est pas la même chose. Une variable char, c'est une variable dédiée à stocker un nombre de 0 à 255 en nous apparaissant telle un caractère. C'est une variable ordinaire si tu veux, de type char (comme il existe un type int, etc...). Quand nous écrivons char tab[]=..., nous déclarons un tableau de char (une suite de variables de type char que nous manipulons comme si c'était un tout). En paramètre d'une fonction, nous ne pouvons passez qu'une seule variable par paramètre. Pour passer tout un tableau, on envoie donc une seule information à la fonction : "Le tableau que je voulais t'envoyer se trouve à telle adresse...", ce sont les pointeurs. Et char* déclare un pointeur sur une variable char (quand on la fait pointer sur un tableau, cette variable pointe sur la première case du tableau : la première variable char de l'ensemble). Une fonction revoyant un char* nous dit "regarde à cette adresse...". J'espère que ces petites images t'aideront à comprendre. La notion de pointeur n'est pas compliquée.
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 14:44:25


Citation


bon,
merci pour ta reponse.
je ranges cela dans une petite case, pour comprendre ultérieurement.....
@+



Rassure toi, rien de compliqué... ;)

Si tu déclarais zStrCapitalize comme de type void, pour afficher le résultat de son travail tu devrais écrire:
...
sStrCapitalize(string);
printf("%s", string);


Par contre en la définissant comme une fonction qui renvoie char * tu peux utiliser son retour comme indiqué dans mon précèdent post... Je trouves ça très pratique !...

J'espère t' avoir aidé( et pas embrouillé :p ...)

a++


Crys' pour l'utilisation de printf, j'avais compris :p ... C'était juste par rapport aux nombreux posts ( intéressants d'ailleurs), qu' avait engendré la demande de ne pas se servir des fonctions standard, et juste pour plaisanter sur la taille de la fonction (50 lignes? :p:p:p )...
Enfin, j'ai quand même rajouté une petite fonction d'affichage pour ma solution...

a++
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
11 novembre 2008 à 15:46:04

Mmmmh en effet, peut etre 60 lignes ;):p Mais c'est surement pas la plus optimisée
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 16:02:46

Curieux, ma fonction tient en 9 lignes (avec accolade) et l'ensemble du code fait 17 lignes (et fonctionne parfaitement).
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 21:59:20

Citation : crys'

Curieux, ma fonction tient en 9 lignes (avec accolade) et l'ensemble du code fait 17 lignes (et fonctionne parfaitement).

La mienne fait 7 lignes :p
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 22:20:21

Euh, c'est bien beau de le faire en peu de ligne, moi si je veut je le fais en une ligne (et ça fonctionne très bien, je l'ai fait pour voir) mais se sera absolument illisible et incompréhensible ^^
  • Partager sur Facebook
  • Partager sur Twitter
11 novembre 2008 à 22:32:09

Citation : DzEt4

Euh, c'est bien beau de le faire en peu de ligne, moi si je veut je le fais en une ligne (et ça fonctionne très bien, je l'ai fait pour voir) mais se sera absolument illisible et incompréhensible ^^


Oui enfin quand je dis 7 lignes c'est en mettant à la ligne à chaque instruction et en indendant bien tout ça ;)
  • Partager sur Facebook
  • Partager sur Twitter
12 novembre 2008 à 16:43:48

Pour ceux qui aurait le courage de faire l'exo sans printf, n'oubliez pas les includes ;)
  • Partager sur Facebook
  • Partager sur Twitter
12 novembre 2008 à 18:22:25

Correction pour zTri



L'exercice zTri était un peu plus difficile que les précédents. En effet, j'ai constaté que très peu de personnes ont participé à l'exercice et seulement 3 codes ont été envoyé à réponse. ^^ Les suivants seront donc plus simples afin qu'un maximum de zér0s puissent s'entraîner.

Néanmoins, l'exercice était un excellent exercice d'algorithmique. L'implémentation de différents algorithmes de tri est un des meilleurs entraînements et sans doute l'un des premiers qu'on se fait en algorithmique. Pour rendre le programme vraiment intéressant, je conseillais d'implémenter au moins les trois tris en O(n²) que je proposais dans l'énoncé, c'est à dire : le tri à bulles, le tri par sélection et le tri par insertion.

Pour le principe des tris, veuillez vous référer aux liens. ;) Pour les implémentations, je peux vous conseiller ceci :
void tri_bulles(int* tab, size_t taille)
{
    unsigned short tab_en_ordre = 0;
    unsigned i;
    int temp;
    while(!tab_en_ordre) // ou while(tab_en_ordre==0)
    {
        tab_en_ordre = 1;
        for(i=0 ; i < taille-1 ; i++)
        {
            if(tab[i] > tab[i+1])
            {
                temp = tab[i];
                tab[i] = tab[i+1];
                tab[i+1] = temp;
                tab_en_ordre = 0;
            }
        }
        taille--;
    }
}

void tri_selection(int* tab, size_t taille)
{
    unsigned fin = taille-1, i, plus_grand;
    int temp;
    while(fin > 0)
    {
        plus_grand = 0;
        for(i = 1 ; i <= fin ; i++)
        {
            if(tab[i] > tab[plus_grand])
                plus_grand = i;
        }
        temp = tab[fin];
        tab[fin] = tab[plus_grand];
        tab[plus_grand] = temp;
        fin--;
    }
}

void tri_insertion(int* tab, size_t taille)
{
    unsigned i, j;
    int element_a_inserer, temp;
    for(i = 1; i < taille; i++)
    {
        element_a_inserer = tab[i];
        for(j = 0; j < i; j++)
        {
            if (element_a_inserer < tab[j])
            {
                temp = element_a_inserer;
                element_a_inserer = tab[j];
                tab[j] = temp;
            }
        }
        tab[i] = element_a_inserer;
    }
}


Ensuite pour compter le temps d'exécution des trois tris, je conseillais d'utiliser clock() et ce de la manière suivante :
#include <stdio.h>
#include <time.h>

int main(void)
{
   clock_t t1, t2;
   t1 = clock();
   maFonctionDeTri(blabla...);
   t2 = clock();
   // Merci à yoch pour l'astuce 
   printf(" Temps d'exécution : %.3lf secondes \n", (double)(t2-t1)/CLOCKS_PER_SEC);
   return 0;
}


A présent, le codage de zTri est un jeu d'enfant ! :D Ce n'est pas bien difficile voilà pourquoi je vous laisse avec ce code (que vous devriez maintenant comprendre) et ses commentaires :
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void tri_bulles(int* tab, size_t taille)
{
    unsigned short tab_en_ordre = 0; // booléen
    unsigned i;
    int temp;
    while(!tab_en_ordre) // ou while(tab_en_ordre==0)
    {
        tab_en_ordre = 1;
        for(i=0 ; i < taille-1 ; i++)
        {
            if(tab[i] > tab[i+1]) // comparaison des éléments adjascents
            {   // échange :
                temp = tab[i];
                tab[i] = tab[i+1];
                tab[i+1] = temp;
                tab_en_ordre = 0;
            }
        }
        taille--;
    }
}

void tri_selection(int* tab, size_t taille)
{
    unsigned fin = taille-1, i, plus_grand;
    int temp;
    while(fin > 0) // Tant que la zone de travail n'est pas nulle
    {
        plus_grand = 0;
        for(i = 1 ; i <= fin ; i++)
        {   // trouver le plus grand nombre :
            if(tab[i] > tab[plus_grand])
                plus_grand = i;
        } // échange :
        temp = tab[fin];
        tab[fin] = tab[plus_grand];
        tab[plus_grand] = temp;
        fin--;
    }
}

void tri_insertion(int* tab, size_t taille)
{
    unsigned i, j;
    int element_a_inserer, temp;
    for(i = 1; i < taille; i++)
    { // [boucle d'itération sur le tableau]
        element_a_inserer = tab[i];
        for(j = 0; j < i; j++)
        {  // [boucle d'insertion]
            if (element_a_inserer < tab[j])
            {   // échange :
                temp = element_a_inserer;
                element_a_inserer = tab[j];
                tab[j] = temp;
            }
        }
        tab[i] = element_a_inserer;
    }
}

void charger_tableau(int* sauvegarde, int* tab, size_t taille)
{
    unsigned i;
    for(i=0 ; i<taille ; i++)
        tab[i] = sauvegarde[i];
}

int hasard(int min, int max) // fonction de Natim pour les nombres aléatoires
{
    return (int)(min+((float)rand()/RAND_MAX*(max-min+1)));
}

int main(void)
{
   srand(time(NULL));

   int* tab = NULL;
   int* sauvegarde = NULL;
   int taille;
   unsigned i;
   clock_t t1, t2; // Pour le chrono

   printf(" [zTri] Comparatif de tris \n\n"
          " Choisissez une taille pour le tableau a trier : ");
   scanf("%d",&taille);
   getchar(); // avaler le '\n' 

   tab = malloc(sizeof(int)*taille);
   sauvegarde = malloc(sizeof(int)*taille);
   /* On crée un tableau de sauvegarde pour qu'un tri suivant un autre
      n'ai pas affaire à un tableau trié mais le même qu'au début
      du programme */

   if(tab == NULL || sauvegarde == NULL)
        return 1; // au cas où les malloc échouent

   for(i=0 ; i<taille ; i++)
       sauvegarde[i] = tab[i] = hasard(0,taille+5000);

///////////////////////////////////////////////////////////////
   printf("\n Tri a bulles en cours... ");
   t1 = clock();
   tri_bulles(tab,taille);
   t2 = clock();
   printf(" %.3lf secondes \n", (double)(t2-t1)/CLOCKS_PER_SEC);
   charger_tableau(sauvegarde,tab,taille);
///////////////////////////////////////////////////////////////
   printf("\n Tri par selection en cours... ");
   t1 = clock();
   tri_selection(tab,taille);
   t2 = clock();
   printf(" %.3lf secondes \n", (double)(t2-t1)/CLOCKS_PER_SEC);
   charger_tableau(sauvegarde,tab,taille);
///////////////////////////////////////////////////////////////
    printf("\n Tri par insertion en cours... ");
   t1 = clock();
   tri_insertion(tab,taille);
   t2 = clock();
   printf(" %.3lf secondes \n\n", (double)(t2-t1)/CLOCKS_PER_SEC);
///////////////////////////////////////////////////////////////

   free(tab);
   free(sauvegarde);

   printf(" Appuyez sur entrer pour quitter...");
   getchar();
   return 0;
}


Voilà, une fois que vous avez compris le principe, vous pouvez vous amuser à comparer d'autres tris connus. :)

A bientôt !

crys'
  • Partager sur Facebook
  • Partager sur Twitter
12 novembre 2008 à 18:56:31

Sympa ta correction !
Si je peux pinailler je dirais que le formateur pour les int est d (dans ton scanf) et qu'il serait mieux de mette int main (void) plutôt que int main ().

Voilà rien d'autre à dire sinon, bon exercice pour les Zéros, je pense que le peu de réponse est entièrement de la faute de yoch qui a fait peur à tout le monde :p
  • Partager sur Facebook
  • Partager sur Twitter
12 novembre 2008 à 21:02:51

Citation : Goost

Si je peux pinailler je dirais que le formateur pour les int est d (dans ton scanf) et qu'il serait mieux de mette int main (void) plutôt que int main ().


Mouais, hop, j'édite. :)
  • Partager sur Facebook
  • Partager sur Twitter
12 novembre 2008 à 21:55:51

merci crys pour la correction,je vais comparer avec mon algo pour le tri a insertion qui marche pas chez moi !
@+
  • Partager sur Facebook
  • Partager sur Twitter
12 novembre 2008 à 22:55:39

Citation : crys'


Pour les implémentations, je peux vous conseiller ceci :



Très bon travail, bien présenté et didactique. Je n'ai pas tout regardé, en particulier pas le tri à bulles qui est vraiment un tri complètement gadget ni vraiment le tri par insertion qui est assez lent.

Juste deux remarques :

Citation : crys'


void tri_selection(int* tab, size_t taille)
{
    unsigned fin = taille-1, i, plus_grand;
   /* */
}



Pourquoi déclarer taille avec le type size_t et ne pas faire de même pour fin ? En principe, les indices de tableaux sont déclarés en size_t.

Citation : crys'


Ensuite pour compter le temps d'exécution des trois tris, je conseillais d'utiliser clock() et ce de la manière suivante :

#include <stdio.h>
#include <time.h>

   /*  code coupé */
   printf(" Temps d'exécution : %.3lf secondes \n", (double)(t2-t1)/CLK_TCK);




la macro CLK_TCK n'est pas standard, utiliser plutot CLOCKS_PER_SEC
(curieux car un compilateur bien réglé montre immédiatement ce défaut).
  • Partager sur Facebook
  • Partager sur Twitter
13 novembre 2008 à 17:59:39

Citation : Goost

...je pense que le peu de réponse est entièrement de la faute de yoch qui a fait peur à tout le monde :p



Dans ce cas, j'en suis désolé, c'était surtout une discussion avec candide sur la difficulté de "génériciser" une fonction (ce qui est un point assez intéressant du C)... Mais je pense que les questions d'algorithmique font aussi systématiquement fuir les débutants...

Je mets tout de même mon code a l'étude pour ceux que cela intéresse. Commentaires bienvenus !

Bien sur, ce n'est pas ce qui était demandé de faire...

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <string.h>

#define swap(p1,p2,sz)          {                               \
                                    size_t j;                   \
                                    for (j=0; j<sz; j++)        \
                                    {                           \
                                        char ptmp = *(p1+j);    \
                                        *(p1+j) = *(p2+j);      \
                                        *(p2+j) = ptmp;         \
                                    }                           \
                                    NB_PERMUTATIONS++;          \
                                }

/* Va. globale pour compter les permutations */
size_t NB_PERMUTATIONS;

/* Structure pour les tests */
typedef struct
{
    /* pointeur de fonction */   
    void (*fn) (void*, size_t, size_t, int (*)(const void*, const void*));
    const char* nom;
} TRI;

void my_triselection (void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void *))
{
    char *debut = base;
    char *fin;
    char* ptr;
    char* max;
    for (fin = (char*)base+(size*(nmemb-1)); fin > debut; fin -= size)
    {
        max = fin;
        for (ptr=fin-size; ptr>=debut; ptr-=size)
        {
            if (compar(ptr, max) > 0)
            {
                max = ptr;
            }
        }
        if (max != fin)
        {
            /* On permute */
            swap (max, fin, size);
        }
    }
}

void my_tribulle (void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void *))
{
    char *debut = base;
    char *fin = (char*)base+(size*(nmemb-1));
    char *ptr1, *ptr2;
    int continuer = 1;
    while (continuer)
    {
        continuer = 0;
        for (ptr1=debut, ptr2=debut+size; ptr2<=fin; ptr1+=size, ptr2+=size)
        {
            if (compar(ptr1, ptr2) > 0)
            {
                continuer = 1;
                /* On permute */
                swap (ptr1, ptr2, size);
            }
        }
    }
}

void my_triinsertion (void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void *))
{
    char *debut = base;
    char* suiv;
    char *ptr;
    char *fin = (char*)base+(size*(nmemb-1));
    char tmp[100];
    int inserer;
    for (suiv = debut+size; suiv <= fin; suiv += size)
    {
        inserer = 0;
        for (ptr = debut; ptr < suiv && !(inserer = compar(ptr, suiv) > 0); ptr += size);
        if (inserer)
        {
            memcpy(tmp, suiv, size);
            memmove(ptr+size, ptr, suiv-ptr);
            memcpy(ptr, tmp, size);
            NB_PERMUTATIONS += (suiv-ptr)/size;
        }
    }
}

static int compare (void const *a, void const *b)
{
    int const *pa = a;
    int const *pb = b;
    /* evaluer et retourner l'etat de l'evaluation (tri croissant) */
    return *pa - *pb;
}

#define TABSIZE 10000
#define TABSIZEMAX 15000
#define NB_METHODES 3

int main (void)
{
    size_t i, j, n, x;
    int tab[TABSIZE] = {0};
    int tab2[TABSIZEMAX] = {0};

    TRI Tri[NB_METHODES];
    Tri[0].fn = my_triselection, Tri[1].fn = my_tribulle, Tri[2].fn = my_triinsertion;
    Tri[0].nom = "my_triselection", Tri[1].nom = "my_tribulle", Tri[2].nom = "my_triinsertion";

    clock_t t1, t2;
    srand(time(NULL));

    for (j=0; j<NB_METHODES; j++)
    {
        puts("-----------------");
        /* Test de validite de l'algo */
        int testtab[] = { 9, -1, 2, 6, -3, 7, 10, -8, -4, 0, -2, 4, -9, -7, 8, 6, 1, -5 };
        int expected_result[] = { -9, -8, -7, -5, -4, -3, -2, -1, 0, 1, 2, 4, 6, 6, 7, 8, 9, 10 };
        Tri[j].fn(testtab, sizeof testtab / sizeof *testtab, sizeof *testtab, compare);
        assert ( !memcmp(testtab,expected_result, sizeof testtab) );
        printf("%s OK !\n\n", Tri[j].nom);

        /* Initialise un tableau trié */
        for (n=0; n<TABSIZE; n++)
        {
            tab[n] = n;
        }
        printf("tri %s en cours sur %d entiers tries...\n", Tri[j].nom, TABSIZE);
        NB_PERMUTATIONS = 0;
        t1 = clock();
        Tri[j].fn(tab, sizeof tab / sizeof *tab, sizeof *tab, compare);
        t2 = clock();
        printf(" %.3lfs - %u permutations\n\n", (double) (t2-t1)/CLOCKS_PER_SEC, NB_PERMUTATIONS);

        /* Initialise un tableau trié a l'envers */
        for (n=0, i=TABSIZE; n<TABSIZE; i--, n++)
        {
            tab[n] = i;
        }
        printf("tri %s en cours sur %d entiers tries a l'envers...\n", Tri[j].nom, TABSIZE);
        NB_PERMUTATIONS = 0;
        t1 = clock();
        Tri[j].fn(tab, sizeof tab / sizeof *tab, sizeof *tab, compare);
        t2 = clock();
        printf(" %.3lfs - %u permutations\n\n", (double) (t2-t1)/CLOCKS_PER_SEC, NB_PERMUTATIONS);

        /* Initialise le tableau aleatoire */
        for (n=0 ; n<TABSIZEMAX ; n++)
        {
            tab2[n] = rand() % TABSIZEMAX;
        }
        printf("tri %s en cours sur %d entiers aleatoires...\n", Tri[j].nom, TABSIZEMAX);
        NB_PERMUTATIONS = 0;
        t1 = clock();
        Tri[j].fn(tab2, sizeof tab2 / sizeof *tab2, sizeof *tab2, compare);
        t2 = clock();
        printf(" %.3lfs - %u permutations\n\n", (double) (t2-t1)/CLOCKS_PER_SEC, NB_PERMUTATIONS);
    }
    return 0;
}

SORTIE :
-----------------
my_triselection OK !

my_triselection en cours sur 10000 entiers tries...
 0.421s - 0 permutations

my_triselection en cours sur 10000 entiers tries a l'envers...
 0.454s - 5000 permutations

my_triselection en cours sur 10000 entiers aleatoires...
 0.421s - 9991 permutations

-----------------
my_tribulle OK !

my_tribulle en cours sur 10000 entiers tries...
 0.000s - 0 permutations

my_tribulle en cours sur 10000 entiers tries a l'envers...
 1.907s - 49995000 permutations

my_tribulle en cours sur 10000 entiers aleatoires...
 1.718s - 25043131 permutations

-----------------
my_tri_insertion OK !

my_tri_insertion en cours sur 10000 entiers tries...
 0.485s - 0 permutations

my_tri_insertion en cours sur 10000 entiers tries a l'envers...
 0.078s - 0 permutations

my_tri_insertion en cours sur 10000 entiers aleatoires...
 0.250s - 0 permutations


Process returned 0 (0x0)   execution time : 5.734 s
Press any key to continue.

NOTES :
- Je crois qu'il est normal qu'un tri générique cède en performances a un tri plus ciblé. C'est surtout du aux appels a la fonction compar.
- Le tri insertion est limité par la taille de son buffer, on peut facilement corriger cela avec malloc...


EDIT: correction du code (voir plus bas).

EDIT2: correction du tri sélection. je laisse l'ancien code ici pour les curieux :
void my_triselection (void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void *))
{
    char *debut = base;
    char *fin;
    char* ptr;
    for (fin = (char*)base+(size*(nmemb-1)); fin >= debut; fin -= size)
    {
        for (ptr=fin-size; ptr>=debut; ptr-=size)
        {
            if (compar(ptr, fin) > 0)
            {
                swap (ptr, fin, size);
            }
        }
    }
}
  • Partager sur Facebook
  • Partager sur Twitter