IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Amélioration possible d'un bout de code


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 327
    Par défaut Amélioration possible d'un bout de code
    Bonsoir,

    Voila j'ai coder ce petit morceau de code dont le but est d'avoir un inverse symétrique 3 par 3 dans un tableau, je ne sais pas si je me suis bien expliqué, je vais donc vous donner un exemple qui seras beaucoup plus parlant:

    Admettons le tableau suivant: (chaque chiffre représente une case)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1 2 3 4 5 6 7 8 9 10 11 12
    Le résultat du code sera:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    10 11 12 7 8 9 4 5 6 1 2 3
    J'espère que ceci est déjà plus clair, mais si besoin n'hésitez surtout pas à demander plus de détails. Le code est donc celui-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #include <stdio.h>
    #include <stdlib.h>
     
    int main (void)
    {
        int *Buffer;
        int *newBuffer;
        int d = 0;
        int f = 11;
        int i;
     
        Buffer = malloc (12 * sizeof (int));
        newBuffer = malloc (12* sizeof (int));
     
        if (Buffer != NULL || newBuffer != NULL)
        {
            Buffer[0] = 1;
            Buffer[1] = 2;
            Buffer[2] = 3;
            Buffer[3] = 4;
            Buffer[4] = 5;
            Buffer[5] = 6;
            Buffer[6] = 7;
            Buffer[7] = 8;
            Buffer[8] = 9;
            Buffer[9] = 10;
            Buffer[10] = 11;
            Buffer[11] = 12;
     
            while (d < 12)
            {
                newBuffer[d] = Buffer[f-2];
                newBuffer[d+1] = Buffer[f-1];
                newBuffer[d+2] = Buffer[f];
                f -= 3;
                d += 3;
            }
     
            for (i=0;i<12;i++)
            {
                printf ("%d ", newBuffer[i]);
            }
            printf ("\n");
            free (Buffer);
            free (newBuffer);
        }
        else
        {
            printf ("Allocation memoire impossible");
            free (Buffer);
            free (newBuffer);
            exit (1);
        }
     
        return 0;
    }
    Je voulais donc savoir si il y a des optimisations possibles pour arriver au même résultat. Merci d'avance

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 088
    Par défaut
    J'ai plusieurs remarque sur ton code :

    Tu utilise l'allocation dynamique, mais ca ne sert a RIEN.
    Tu ne retient pas la taille du tableau et tes boucle for parcourront toujours 12 fois et non tailleTableauFois.
    Dans ton cas, autant mettre un define ou 12 partout et faire des tableau statique.


    Tu utilise 2 tableau, alors que 1 tableau est suffisant. Il s'agit du principe de permutation circulaire (c'est un de ses noms) ou il suffit de declarer une troisieme variable temporaire.

    En cas d'erreur du malloc, tu utilise printf. Ca n'informe pas de la cause. C'est bien de tester, mais faut aussi afficher pourquoi ca va pas.
    Donc, utilise perror pour ca.


    Ensuite, c'est quoi ca ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            Buffer[0] = 1;
            Buffer[1] = 2;
            Buffer[2] = 3;
            Buffer[3] = 4;
            Buffer[4] = 5;
            Buffer[5] = 6;
            Buffer[6] = 7;
            Buffer[7] = 8;
            Buffer[8] = 9;
            Buffer[9] = 10;
            Buffer[10] = 11;
            Buffer[11] = 12;
    Une boucle, et en limite la tailleTableau.


    Bon, ce que j'ai fait, c'est une structure et 4 fonction associé. Ca peut te sembler tirer par les cheveux ou meme sortir un marteau piqueur pour ecraser une mouche, mais dans le main, c'est plus clair tout d'un coup.

    Autre chose, j'ai un peu tasser tout dans la fonction permuter, donc ca peut etre deroutant au premier abord.
    Le principe est simple.

    On prend TailleTableau, on divise par 3. On obtient le nombre de bloc de trois.
    Ensuite, c'est simple, on fait un permutation circulaire, c'est a dire qu'on va s'arreter a la moitier des bloc et que le 1er est echanger avec le dernier, le 2eme avec l'avant dernier etc etc

    donc, tailleTableau/3 = nombre de bloc
    tailleTableau/3/2 = nombre de bloc a permuter.

    Voici mon code, avec toutes les remarque faites avant.
    Bonne lecture.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
    #include <stdio.h>
    #include <stdlib.h>
     
     
    typedef struct Tableau1D
    {
        int *Buffer;
        int taille;
    } Tableau1D;
     
    void Tableau1D_Initialiser (Tableau1D* LeTableau, int longueur);
    void Tableau1D_Detruire (Tableau1D* LeTableau);
     
    void Tableau1D_Afficher (Tableau1D* LeTableau);
    void Tableau1D_PermuterPar3 (Tableau1D* LeTableau);
     
     
    int main (void)
    {
        Tableau1D LeTableau;
        Tableau1D_Initialiser (&LeTableau, 15);
     
     
        Tableau1D_Afficher (&LeTableau);
        Tableau1D_PermuterPar3 (&LeTableau);
        Tableau1D_Afficher (&LeTableau);
     
     
        Tableau1D_Detruire (&LeTableau);
        return EXIT_SUCCESS;
    }
     
    void Tableau1D_Initialiser (Tableau1D* LeTableau, int longueur)
    {
        int i;
     
        if (longueur%3 != 0)
        {
            printf("la taille doit etre un multiple de 3\nArret du programme\n\n");
            exit (EXIT_FAILURE);
        }
     
        LeTableau->Buffer = malloc (longueur * sizeof (int));
        if (LeTableau->Buffer == NULL)
        {
            perror("Allocation memoire impossible");
            exit (EXIT_FAILURE);
        }
     
        LeTableau->taille = longueur;
     
        for (i=0 ; i<longueur ; i++)
            LeTableau->Buffer[i] = i+1;
    }
     
    void Tableau1D_Detruire (Tableau1D* LeTableau)
    {
        free (LeTableau->Buffer);
    }
     
    void Tableau1D_Afficher (Tableau1D* LeTableau)
    {
        int i;
        for (i=0 ; i<LeTableau->taille ; i++)
        {
            if (i%3 == 0 && i!=0)
                printf (" ");/* Juste un petit espace pour demarquer un peu les bloc de trois */
            printf ("%d ", LeTableau->Buffer[i]);
        }
        printf ("\n\n");
    }
     
    void Tableau1D_PermuterPar3 (Tableau1D* LeTableau)
    {
        int i;
        for (i=0 ; i<(LeTableau->taille/3)/2 ; i++)
        {
            int j;
            for (j=0 ; j<3 ; j++)
            {
                int temp = LeTableau->Buffer[i*3+j];
                LeTableau->Buffer[i*3+j] = LeTableau->Buffer[LeTableau->taille - 3 - i*3 +j];
                LeTableau->Buffer[LeTableau->taille - 3 - i*3 +j] = temp;
            }
        }
     
    }

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 327
    Par défaut
    Merci, en effet c'est mieux je pense que je prendrais ta version Merci encore

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @SofEvans : Une remarque :
    Ensuite, c'est simple, on fait un permutation circulaire, ....
    Ce n'est pas une permutation circulaire.

  5. #5
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 088
    Par défaut
    Hum, le fait d'echanger la valeur de deux variable via une troisieme temporaire, mon prof de C a dit que c'etait une permutation circulaire.

    Bon, ici, j'en fait trois, mais sinon, tu appele ca comment ? ca a un nom ?

    (dès que j'ai vu que diogene a repondu a un de mes post, j'ai direct penser : j'ai fait quoi comme boulette encore ? )

  6. #6
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Hum, le fait d'echanger la valeur de deux variable via une troisieme temporaire, mon prof de C a dit que c'etait une permutation circulaire.
    ...
    Ta phrase
    Ensuite, c'est simple, on fait un permutation circulaire, c'est a dire qu'on va s'arreter a la moitier des bloc et que le 1er est echanger avec le dernier, le 2eme avec l'avant dernier etc etc
    semblait qualifier la transformation du tableau, pas le mécanisme de permutation de deux éléments, d'où ma remarque.
    (dès que j'ai vu que diogene a repondu a un de mes post, j'ai direct penser : j'ai fait quoi comme boulette encore ? )

  7. #7
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 088
    Par défaut
    Oui, maintenant que je relis cette phrase la, c'est vrai que c'est ambigue.
    Merci de le preciser, la permutation circulaire na pas pour principe de s'arreter a la moitier du tableau mais bien de permuter des valeur via une 3eme variable temporaire.

    Noter que l'on pourrait utiliser ^ pour ne pas declarer la 3eme variable, mais ce n'est valable que pour les entier.

    a=2
    b=4

    a^=b;
    b^=a;
    a^=b;

  8. #8
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Puisqu'on est dans le domaine de l'amélioration du code, je vais donner aussi mon avis.
    Lorsqu'on est dans le cadre où on sait EXACTEMENT le nombre de valeurs, de cases, ou je ne sais quoi, au lieu de trouver le rang à traiter par calcul (deux multiplications et trois additions), je pense qu'il vaut mieux utiliser la méthode de sxitch, suivant le principe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    for (int i=0; i<12; i++)
    {
      int ja; //rang ancien
      int jb; // rang nouveau
      switch (i)
      {
        case 0:
        case 1:
        case 2:
          ja=1; jb=10; break;
        case 3:
        case 4:
        case 5:
          ja=4; jb=7; break;
    ...
      }
      int tmp=tab[ja];
      tab[ja]=tab[jb] ; 
      etc.
    }
    Je n'ai pas mis le détail, donc ce code est incomplet ET faux, c'est juste pour le principe.
    Il est vrai qu'en nombre de lignes, c'est généralement un peu plus, pour la relecture, l'avantage est évident, et en temps d'exécution c'est meilleur.

    Autre remarque. Dans le main, LeTableau est une structure déclarée en tant que valeur. Par contre, pour des raisons bien connues, il est passé en référence. Alors que le paramètre de la fonction est un pointeur.
    Je préfère l'écriture suivante qui me parait plus claire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    int main (void)
    {
        Tableau1D* LeTableau;
        Tableau1D_Initialiser (LeTableau, 12);  // 12 naturellement
     
     
        Tableau1D_Afficher (LeTableau);
        Tableau1D_PermuterPar3 (LeTableau);
        Tableau1D_Afficher (LeTableau);
     
     
        Tableau1D_Detruire (LeTableau);
        return EXIT_SUCCESS;
    }
    ou mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    int main (void)
    {
        Tableau1D* LeTableau;
        LeTableau = Tableau1D_Initialiser (12);
     
     
        Tableau1D_Afficher (LeTableau);
        LeTableau = Tableau1D_PermuterPar3 (LeTableau);
        Tableau1D_Afficher (LeTableau);
     
        Tableau1D_Detruire (LeTableau);
        return EXIT_SUCCESS;
    }
    Naturellement en modifiant les déclarations de fonction en conséquence.

    J'ai mis l''*' juste après le type. Par ailleurs, je n'aime pas beaucoup l'opérateur '&'. En fait je ne l'utilise que dans la déclaration d'une fonction lorsque je veux que la fonction modifie le paramètre concerné.

    Voilà, j'ai tout dit.
    Bonne journée.

  9. #9
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 088
    Par défaut
    C'est le forum C ici, pas le forum C++.
    Il n'y a pas de reference et j'utilise les pointeur.


    Peut tu me faire le code avec switch d'une permutation 3 par 3 d'un tableau de 3000 element ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        Tableau1D* LeTableau;
        Tableau1D_Initialiser (LeTableau, 12);  // 12 naturellement
    Ceci m'as l'air dangereux en C puisque LeTableau est un pointeur non initialiser et que Tableau1D_Initialiser ne s'en charge pas.
    Lorsque l'on manipule des pointeur, les fonction renvoie des adresse comme les FILE* ou SDL_Surface* (en SDL).

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Essayons de s'expliquer.
    D'abord, sur l'allocation du tableau. Il est bien évident que le code serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // si on veut faire une allocation dynamique. 
    int* Letableau = (int*)malloc(sizeof(int) * longueur);
    ...
    free (LeTableau);
    // sinon
    int LeTableau[longueur].
    Quant au switch, je suppose qu'il faut avoir écrit du code pour comprendre l'intérêt.
    1- il ne s'agit naturellement pas d'un tableau de 3000, mais par exemple d'un tableau de 9 positions (les 4 angles d'un rectangle, le milieux des côtés et le centre du rectangle) très utilisé en graphisme, ou les 9 cases l'un pavé de pixels de 3x3, ou les 48 position de recherche en colimaçon.
    2- trait de génie, sûrement pas mais une longue pratique.

    D'ailleurs, je vous ferai remarquer très respectueusement que j'ai exposé mon avis sur un forum d'échange et que la question posée était uniquement théorique.
    Enfin, mais je n'ai pas osé le dire tout à l'heure, je ne met JAMAIS un exit() dans une fonction. Je renvoie un code erreur que je peux traiter dans la fonction d'appel.

    Dans le cas présent, faire une structure et des fonctions, c'est vraiment pour se faire plaisir.

    Petit complément.
    Imaginons que ce programme ne soit pas simplement un exercice, mais serve à quelque-chose, par exemple les données existent, pour je ne sais quelle raison elles ont été rentrées à l'envers, le but étant de les remettre en ordre.
    Il est bien évident que la valeur du tableau n'a aucune chance d'être égale à son rang +1. Ce seront des valeurs quelconques, lues dans un fichier.
    L'exemple donné par l'auteur de la question, c'est à dire 12 valeurs organisées de 1 à 12 nous a permis de comprendre facilement le but de la manip. Mais en aucun cas, dans la réalité ces valeurs ne seront stockées dans une boucle en faisant tab{i]=i+1: J'en conclue que dans ce cadre de cette exercice et surtout de son explication, il était justifié d'écrire l'attribution de chaque valeur comme cela a été fait par l'auteur de la question.
    Dernière modification par Invité ; 04/07/2010 à 19h49.

  11. #11
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 088
    Par défaut
    Excusez moi d'avoir été si brusque, mais par rapport a ce qu'a ecrit le PO, je voyais vraiment pas comment on peut utiliser le switch.

    Le switch ,bien que plus clair, me semble très lourd, trop lourd.

    Enfin, mais je n'ai pas osé le dire tout à l'heure, je ne met JAMAIS un exit() dans une fonction. Je renvoie un code erreur que je peux traiter dans la fonction d'appel.
    Ca depend. y'a un moment ou faut arreter de renvoyer l'ascenceur de toute facon. Ici, je fait en sorte que soit la structure soit coherente, soit le programme plante. On peut toujours ameliorer en faisant un boucle de demande dans l'intialisation.

    Dans le cas présent, faire une structure et des fonctions, c'est vraiment pour se faire plaisir.
    Je crois pas, non. Le fait de faire une structure et d'y "associer" des fonction permet de bien delimiter ce que l'on fait.

    Avec l'ancien code, les variable etait partout, toutes de le main, il fallait voir ou commencer et finnissait l'intialisation/permutation/affichage.
    Bref, la, on a 4 fonction on ne peut plus clair. Suffit de les appeler comme on veut. Preuve en est que dans le main, c'est hyper clair.

    Petit complément.
    Imaginons que ce programme ne soit pas simplement un exercice, mais serve à quelque-chose, par exemple les données existent, pour je ne sais quelle raison elles ont été rentrées à l'envers, le but étant de les remettre en ordre.
    Il est bien évident que la valeur du tableau n'a aucune chance d'être égale à son rang +1. Ce seront des valeurs quelconques, lues dans un fichier.
    L'exemple donné par l'auteur de la question, c'est à dire 12 valeurs organisées de 1 à 12 nous a permis de comprendre facilement le but de la manip. Mais en aucun cas, dans la réalité ces valeurs ne seront stockées dans une boucle en faisant tab{i]=i+1: J'en conclue que dans ce cadre de cette exercice et surtout de son explication, il était justifié d'écrire l'attribution de chaque valeur comme cela a été fait par l'auteur de la question.
    Euh,

    Si le tableau n'est pas trié, aucune chance qu'il le soit en faisant des permutation symetrique par bloc de trois.
    De plus, en general, on fait une initialisation de tableau par boucle for.
    Soit c'est demander par l'utilisateur -> boucle for
    par un fichier -> boucle for
    par un autre flux -> boucle for

    bref, a moins d'entrer en dur, on fait une boucle. De plus, ici, il fait tab[i] = i+1, pourquoi ne fait'il pas une boucle ?


    Enfin bref, désolé de mettre mal exprimer, mais le coup du switch me laisse tres dubitatif.

  12. #12
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par SofEvans Voir le message
    Ca depend. y'a un moment ou faut arreter de renvoyer l'ascenceur de toute facon.
    Le problème de la sortie brutale du programme via un exit c'est la libération des ressources :
    • Certaines (la mémoire notamment) sont libérées par le système sur de nombreux OS (dont Windows, Linux, etc.) mais ce n'est pas garanti partout.
    • D'autres ne le sont tout simplement pas ou le sont beaucoup plus tard.

    En remontant l'erreur, tu laisses au moins la possibilité à toutes les autres couches de libérer les ressources dont elles sont responsables.

  13. #13
    Invité
    Invité(e)
    Par défaut
    Bonjour gl,
    C'est bien ça la raison incontournable, mais il y en a une autre plus cachée.
    Quand on écrit une fonction on ne sait pas forcément l'ampleur du programme qui va éventuellement l'utiliser. Si elle tombe en erreur, même grave, à cause d'une fausse manip de l'utilisateur, ce serait ennuyeux se sortir en catastrophe.
    Cordialement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. la sauvegarde des bouts de code ?
    Par blackhorus dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 02/10/2005, 14h34
  2. [XML][XSL] déplacer bout de code XML
    Par majanissa dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 14/09/2005, 18h17
  3. Besoin d'explications sur un bout de code
    Par zizitop dans le forum C
    Réponses: 7
    Dernier message: 26/04/2005, 15h51
  4. bout de code à dechifrer svp
    Par bball dans le forum C
    Réponses: 32
    Dernier message: 21/01/2005, 00h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo