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

SL & STL C++ Discussion :

List et Vector : mise au point


Sujet :

SL & STL C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut List et Vector : mise au point
    Bonsoir,

    Je travaille actuellement sur un petit projet où je fais des requête sql à l'aide de QSql et à l'aide de quelques fonctions je crée une liste de message.

    Pour l'instant c'est très lourd, mais je compte bien faire différemment.

    J'utilisais les vector mais le fait de parcourir mon vector et de faire des push_back, invalidait l'iterator.

    Du coup, je suis passé au liste. Et là plus de problème. Je me demande tout de même si ce n'est pas un peu sale.

    Voici :

    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
     
    void Feeder::update()
    {
            std::wstring tempString;
            queryExec("SELECT * FROM staff WHERE salary > 1000");
     
            std::list<SimpleMessage*>::iterator it = m_messageList.begin();
     
     
            while (queryNext()) 
            {
               tempString = (getValue(1).toString()).toStdWString () ;
     
                if( it != m_messageList.end() )
                {
                    if(*it)
                    {   
                        if( (*it)->getContent() == tempString )
                        {
                            ++it;
                        }
                        else 
                        {   
                            m_messageList.push_back( new SimpleMessage( (getValue(1).toString()).toStdWString ()) );  
                        }
                    }
                    else
                    {
                        cout<<"error  NULL pointer on MessageList... "<<endl;
                    }
                }
                else
                {
                    m_messageList.push_back( new SimpleMessage( (getValue(1).toString()).toStdWString ()) );
                    it = m_messageList.begin();
                }
            }
    }
    Merci d'avance !

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Je ne suis pas sur d'avoir tout compris à ce que tu voulais faire et en particulier pourquoi tu veux maintenir un itérateur sur ton conteneur. Cet itérateur varie assez étrangement dans ton code - dont je n'ai pas tout saisi.
    Donc, je vais dire 2 ou 3 bêtises en espérant qu'elles ne tombent pas trop à côté :
    1/ Si tu veux des chaînes distinctes, et bien précises le dans ta requête SQL plutôt que dans le traitement C++. Ce sera sans contexte + efficace.
    2/ Si tu veux utiliser un vector, tu peux faire une première fois un SELECT COUNT(*) FROM staff WHERE salary > 1000, puis un reserve pour éviter les réallocation permanente. Attention reserve ne créé pas d'éléments mais permet de réallouer le tableau interne. Si la liste était vide, elle reste vide.
    3/Tu peux utiliser un indice (valide) pour accéder à tes éléments et l'opérateur [] sur ton vecteur.
    4/ Pourquoi avoir un conteneur de pointeur (SimpleMessage*) et pas directement d'éléments (SimpleMessage)?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Alors :

    1. Je n'ai pas compris la première question.

    2. je n'ai pas vraiment compris la réponse du point deux.

    3. pour l'histoire de l'indice, je compte faire cela pour la suite. J'enregistre où est-ce que je me trouvais la dernière fois que j'ajoutais un message et je n'ajoute que si l'indice suivant contient des informations.

    Mais pour le moment je souhaite comprendre, la manière compliqué qui fut mon premier jet.

    4. hum, je fais comment pour créer dynamiquement mes objets messages qui seront effacés, ajoutés comme cela au bon vouloir des moments où ils arrivent dans la BDD ?

    Merci de cette réponse rapide !

  4. #4
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,

    J'utilisais les vector mais le fait de parcourir mon vector et de faire des push_back, invalidait l'iterator.
    Dans ce genre de cas, on peux s'en sortir en convertissant en offset, puis en repassant en itérateur après l'opération d'insertion.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    if( (*it)->getContent() == tempString )
    {
       ++it;
    }
    else 
    {  
       std::vector<int>::difference_type offset = std::distance(m_messageList.begin(), it);
       m_messageList.push_back( new SimpleMessage( (getValue(1).toString()).toStdWString ()) );
       it = m_messageList.begin();
       std::advance(it, offset);           
    }
    Ceci dit, j'ai les mêmes réserves que 3DArchi sur ton code. La logique a l'air un peu bizarre et je n'arrive pas à traduire en mot ce que le code fait.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    1/ Peux-tu expliquer ce qu'est supposé faire ta fonction ? Je ne comprend pas pourquoi tu fais le test if( (*it)->getContent() == tempString ) et comment évolue ton itérateur. Est-ce pour ne pas insérer une chaîne déjà existante ?
    2/ Si tu utilises un vecteur et que tu rajoutes beaucoup d'éléments, il est plus performant de faire d'abord un mon_vecteur.reserve(nb_element), puis des mon_vect.push_back. D'où l'idée de faire une première requête pour compter les éléments et réserver, puis une seconde pour récupérer les éléments.
    4/ Je ne vois pas le rapport. Tu peux très bien ajouter ou enlever des éléments d'un conteneurs. Maintenant, si tu dois être amené à faire beaucoup d'opération d'ajout/suppression alors reste sur une std::list. Ce sera + performant qu'un std::vector.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Alors c'est très simple !

    Je viens intéroger la base de donnée,

    Je regarde si la liste à un élément,

    sinon j'ajoute le premier élément.

    Je regarde le champs de la table qui m'intéresse, et je compare le champs au contenu du message.

    Si le champs en question est présent dans le message je passe mon chemin.
    Sinon j'ajoute un message à la liste de message avec le nouveau contenu du champs.

    Ainsi, j'ajoute des SimpleMessages à chaque nouveau champs rempli dans la table concernée.

    Je parcours à chaque appel de la fonction update tous les champs de table et les compare à la liste courante. Oui c'est long et stupide mais je n'avais pas pensé à mettre un flag pour voir s'il y a du nouveau ou encore utilisé les idée de chaque ligne de ma table pour maintenir à jour ma liste de SimpleMessage.

    Comme j'étais sur un bug que je ne comprenais pas (avec l'utilisation de vector) et que j'ai résolu par un changement en list, je préférais poser la question.

    Merci

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Je maintiens ne pas bien comprendre...
    Pour le 1er élément, sors le de ta boucle, ça t'évitera de faire le test à chaque itération.
    Pour ce qui est de comparer par rapport au champs : tu peux déjà demander des DISTINCT dans ta requête SQL ou rajouter des WHERE XXXX NOT IN ou quelque chose de ce genre (voire les spécialistes de SQL) pour permettre à SQL de ne te retourner que les valeurs qui t'intéresse.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    1/ Peux-tu expliquer ce qu'est supposé faire ta fonction ? Je ne comprend pas pourquoi tu fais le test if( (*it)->getContent() == tempString ) et comment évolue ton itérateur. Est-ce pour ne pas insérer une chaîne déjà existante ?
    Exactement (ce qui n'est pas très malin)

    Citation Envoyé par 3DArchi Voir le message
    2/ Si tu utilises un vecteur et que tu rajoutes beaucoup d'éléments, il est plus performant de faire d'abord un mon_vecteur.reserve(nb_element), puis des mon_vect.push_back. D'où l'idée de faire une première requête pour compter les éléments et réserver, puis une seconde pour récupérer les éléments.
    Ok, je ne savais pas... Je vais faire cela

    Citation Envoyé par 3DArchi Voir le message
    4/ Je ne vois pas le rapport. Tu peux très bien ajouter ou enlever des éléments d'un conteneurs. Maintenant, si tu dois être amené à faire beaucoup d'opération d'ajout/suppression alors reste sur une std::list. Ce sera + performant qu'un std::vector.
    Je m'imaginais que cela était moin "couteux" puisque si je fais un vector<SimpleMessage>, et non vector<SimpleMessage*>, il va créer une copie et après chaque push_back le SimpleMessage orignal sera supprimé.

    Même si le résultat final (j'ai bien accès à mes SimpleMessage dans la liste ou le vector) est le même, les opérations effectuées sont différentes.

    C'est la constatation que je fais, si je fais des "output" à l'appel du destructeur d'objet SimpleMessage :

    Dans le cas de vector<SimpleMessage>, l'appelle des destructeurs à lieu après chaque pushback alors qu'avec un vector<SimpleMessage*>, l'appel du destructeur n'a lieu que lorsque je quitte le programme.


    Merci encore !

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je maintiens ne pas bien comprendre...
    Pour le 1er élément, sors le de ta boucle, ça t'évitera de faire le test à chaque itération.
    Pour ce qui est de comparer par rapport au champs : tu peux déjà demander des DISTINCT dans ta requête SQL ou rajouter des WHERE XXXX NOT IN ou quelque chose de ce genre (voire les spécialistes de SQL) pour permettre à SQL de ne te retourner que les valeurs qui t'intéresse.
    Je ne connais rien à SQL. Ce que tu dis là m'intéresse ! Mais pour le moment restons-en au list et vector. En fait, je me demande pour quelle raison, un push_back sur un vector invalide l'iterator alors que sur une liste au premier abord pas de problème....

  10. #10
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    lorsque tu insère un élément dans un vector, il peut avoir besoin ^'être entièrement réalloué par manque de place. De ce fait, le début du vector ne sera plus le même. Sur une liste, il n'y a pas de réallocation, il y a juste un nouveau maillon qui est ajouté dans la liste ce qui ne change pas (trop) les iterator.

    Un petit coup d'oeil ici pour comprendre un peu plus (j'ai pas trouvé en français)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    lorsque tu insère un élément dans un vector, il peut avoir besoin ^'être entièrement réalloué par manque de place. De ce fait, le début du vector ne sera plus le même. Sur une liste, il n'y a pas de réallocation, il y a juste un nouveau maillon qui est ajouté dans la liste ce qui ne change pas (trop) les iterator.

    Un petit coup d'oeil ici pour comprendre un peu plus (j'ai pas trouvé en français)
    Ok, donc même si mon code n'est pas futé, c'est tout simplement l'implémentation de std::vector dans la STL qui entraine l'invalidation de l'iterateur ? il aurait été possible que push_back() renvoit le nouvel iterateur, comme le fait erase() ?

    Je n'ai pas vu ces informations dans la FAQ. Ais-je mal cherché ?

    Merci en tous cas.

  12. #12
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par SpongeBob Voir le message
    il aurait été possible que push_back() renvoit le nouvel iterateur, comme le fait erase() ?
    Pas besoin. Le nouvel itérateur dans le cas d'un push_back c'est le dernier élément, or le dernier élément est toujours accessible par la fonction back().

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Pas besoin. Le nouvel itérateur dans le cas d'un push_back c'est le dernier élément, or le dernier élément est toujours accessible par la fonction back().
    hum...donc dans mon code... comment pourrais-je faire avec l'utilisation de back(), je ne vois pas.

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Je pense que tu as un problème sur ton algorithme (ne serait-ce que parce que même ton explication en langage courant était peu compréhensible).
    Tu as donc une table staff avec différentes colonnes dont salary et celle que tu accèdes avec getValue(1) (appelons là C1).
    Ta table contient plusieurs lignes (enregistrements).
    Tu veux récupérer les enregistrement pour lesquels salary>1000.
    C'est ensuite que cela devient plus flou.
    Tu veux rajouter le résultat de cette requête dans m_messageList sauf s'il est déjà dans m_messageList ?

    1/ La requête : pourquoi ne pas faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT DISTINCT C1 FROM staff WHERE salary>1000
    DISTINCT te permet de ne récupérer que des enregistrement différents. Si tu as 2 lignes qui ont le même C1, une seule sortira en résultat.
    Pourquoi faire un SELECT * si au final tu ne fais que getValue(1). Ne demande que ce dont tu as besoin. Les échanges SQL<->C++ en seront normalement améliorés.

    2/ Ensuite l'ajout : tu parcours ton résultat et vérifie qu'il n'est pas dans les existant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Pour tous les résultats R de ma requête
        Rechercher dans m_messageList un élément E tel que E.getContent() == R.C1()
        Si E non trouvé :
               rajouter un nouvel element E(R.C1())
        Fin si
    Fin pour
    Si c'est ça que tu veux faire, alors ton idée de maintenir un itérateur pour ta recherche ne fonctionne pas.

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Tu veux rajouter le résultat de cette requête dans m_messageList sauf s'il est déjà dans m_messageList ?

    1/ La requête : pourquoi ne pas faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT DISTINCT C1 FROM staff WHERE salary>1000
    DISTINCT te permet de ne récupérer que des enregistrement différents. Si tu as 2 lignes qui ont le même C1, une seule sortira en résultat.
    Pourquoi faire un SELECT * si au final tu ne fais que getValue(1). Ne demande que ce dont tu as besoin. Les échanges SQL<->C++ en seront normalement améliorés.
    Je vais changer ça.

    Citation Envoyé par 3DArchi Voir le message
    2/ Ensuite l'ajout : tu parcours ton résultat et vérifie qu'il n'est pas dans les existant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Pour tous les résultats R de ma requête
        Rechercher dans m_messageList un élément E tel que E.getContent() == R.C1()
        Si E non trouvé :
               rajouter un nouvel element E(R.C1())
        Fin si
    Fin pour
    Si c'est ça que tu veux faire, alors ton idée de maintenir un itérateur pour ta recherche ne fonctionne pas.
    Oui ça ne fonctionne pas avec les Vector mais bien avec les listes.

    Merci.

  16. #16
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Si cela ne marche pas avec les vecteurs...c'est tout simplement que tu l'as mal implémenté
    Le code tel que tu l'a présenté en début de fil ne fait pas ce que je t'ai décrit juste au dessus.

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Salut,
    Si cela ne marche pas avec les vecteurs...c'est tout simplement que tu l'as mal implémenté
    Le code tel que tu l'a présenté en début de fil ne fait pas ce que je t'ai décrit juste au dessus.
    Voici une première correction :

    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
     
    void Feeder::update()
    {
            std::wstring tempString;
     
            queryExec("SELECT Name FROM staff WHERE salary > 1000");
     
            std::list<SimpleMessage>::iterator it = m_messageList.begin();
     
            if( it == m_messageList.end() )
            {
                m_messageList.push_back( new SimpleMessage((getValue(0).toString()).toStdWString ()) );
                it = m_messageList.begin();
            }
     
            while (queryNext()) 
            {
                   tempString = (getValue(0).toString()).toStdWString() ;
     
                    if( (*it).getContent() != tempString )
                    {
                        m_messageList.push_back( new SimpleMessage(tempString) );  
                    }
                    else 
                    {   
                        ++it;
                    }
            }
     
    }
    Je ne parcours pas toute la liste pour savoir si oui ou non le mot présent dans liste Message message existe dans la BDD, mon but est d'ajouter un message à la liste Message uniquement si le message est nouveau.
    Et normalement je dois retrouver les messages dans la liste dans le même ordre que ceux de la BDD. Donc si un nouveau message avec le même contenu arrive, je pourrais l'ajouter puisque à cette place rien n'existera, non ?

  18. #18
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,

    Citation Envoyé par SpongeBob Voir le message
    Donc si un nouveau message avec le même contenu arrive, je pourrais l'ajouter puisque à cette place rien n'existera, non ?
    Non.
    Aucun ordre n'est garantie dans le résultat d'une requête SQL à moins que tu en es explicitement spécifié un. Donc,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Name FROM staff WHERE salary > 1000
    peut très bien retourner une première fois : "toto, titi, tata" puis la fois suivante "tata,toto,titi".
    Si tu veux un ordre alors il faut le spécifier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Name FROM staff WHERE salary > 1000  ORDER BY Name
    Ensuite, si tu veux utiliser cette hypothèse, effectivement, tu peux t'inspirer de l'algo d'union :
    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
     
    it_1 = début de ta liste C++
    it_2 = début du résultat de ta requête
    tant que it_1 n'est pas à la fin ET it_2 n'est pas à la fin
         si *it_1<*it_2
                ++it_1
         sinon si *it_2<*it_1
                 Insérer *it_2 avant it_1
                 ++it_2
         sinon (*it_1==*it_2)
              ++it_1; ++it_2;
    fin tant que
    // si on n'a pas épuisé it_2, c'est qu'on a épuisé it_1 : 
    tant que it_2 n'est pas à la fin
        ajouter *it_2 à la fin de la liste C++
        ++it_2
    fin tant que

  19. #19
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Par défaut
    OK !
    Merci tout fonctionne nickel !
    Je n'ai plus qu'à développer tout le reste.

    Merci beaucoup pour toutes ces indications qui m'ont été toute très utiles.

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

Discussions similaires

  1. Convertir List en Vector
    Par michaelbob dans le forum Collection et Stream
    Réponses: 12
    Dernier message: 10/05/2011, 16h25
  2. Mise au point d'un bon algo
    Par cryptorchild dans le forum Langage
    Réponses: 3
    Dernier message: 08/10/2005, 17h04
  3. Petite mise au point avec gluUnProject.
    Par fatpat94 dans le forum OpenGL
    Réponses: 1
    Dernier message: 27/07/2005, 15h40
  4. [Mise au point] dhcp
    Par Ernest dans le forum Développement
    Réponses: 5
    Dernier message: 07/10/2004, 17h56
  5. Questions de mise aux points
    Par nicoo dans le forum DirectX
    Réponses: 5
    Dernier message: 11/05/2004, 14h01

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