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 :

Problème chaîne sans pointeur


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut Problème chaîne sans pointeur
    Bonjour

    Je me suis mis à la programmation sous C depuis quelques semaines seulement, et suis bloqué sur un exercice :

    Sans utiliser de pointeur, Ecrire la fonction partie_presente qui retourne 1 si une chaîne de caractère est présente dans une autre chaine de caractères et 0 sinon. Les deux chaînes seront passées en paramètre de la fonction.

    J'ai beau tourné le problème dans tous les sens, je n'arrive pas, je suis un novice, et c'est ma première de mande sur le forum, espérant ne pas l'avoir déposé dans le mauvais endroit, et espérant une aide de votre part.

    D'avance merci.

    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
     
    #include<stdio.h>
    #include<string.h>
    /* c'est du langage C */
    int partie_presente(char ch1 [], char ch2[])
    {
        int i=0, j=0, k=0;
        int h=0, ps=0;
        printf("Entrez une chaîne de caractères: ");
        fgets(ch1,1000,stdin);
        printf("Entrez la séquence recherchée: ");
        fgets(ch2,1000,stdin);
        char tmp[strlen(ch2)];
     
        for(i=0; i<strlen(ch1); i++)
        {
            for(j=i; j<strlen(ch2) ; j++)
            {
                strncpy(tmp, ch1,strlen(ch2));
                 h=strcmp(tmp,ch2);          
            }
            if(h==0)
                {
                    ps=1;
                }
        }
     
        if(ps==1)
            printf("La séquence est présente\n");
        else
            printf("La séquence n'est pas présente\n");
     
        return ps;
    }
     
    int main()
    {
         char ch1[1000], ch2[1000];
         partie_presente(ch1, ch2);
         return 0;
    }

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Je ne vois pas trop ce que le "sans utiliser de pointeur" apportera à l'exercice. Peut-être pour te forcer à utiliser la notation indicée mais bon, quand on en arrive au point où on remplace les indices par des pointeurs on a alors atteint un niveau où les indices c'est peanut. Je suis d'ailleurs étonné qu'on t'interdise les pointeurs mais qu'on t'autorise strlen() ou strcmp() (accessoirement moi j'aurais plutôt vu ici strncmp() !!!) car d'une part on ne sait plus si cet exo est là pour t'apprendre l'algo et la manipulation des strings ; et d'autre part, les arguments que tu passes à ces fonctions ce sont des pointeurs.

    Sinon question algo c'est pas super compliqué. Une première boucle avec un indice "i" qui balaye ch1. Une seconde boucle avec un second indice "j" qui balaye ch2. Là, si ch2[j] est différent de ch1[i+j] alors tant pis, on passe au "i" suivant et si on atteint la fin de ch1 c'est définitivement perdu (on peut aussi, pour optimiser, s'arrêter avant quand on sait que ch2 ne rentrera plus dans ce qui reste). Et si on arrive à un moment donné à amener "j" au bout de ch2 alors gagné, ch2 est bien dans ch1.
    Bien entendu, si (comme je le pense) pas de strlen() alors il faut se repérer au '\0' terminant toute chaine pour savoir quand terminer la première ou seconde boucle.

    Quelques détails annexes: une fonction qui doit chercher un truc n'a pas à se préoccuper de la saisie du truc (qu'est-ce qui te dit que le truc ne proviendra pas demain d'un fichier ou d'une bdd ?). Comme Paris face à Priam (ne te préoccupe que de ton épée et de son épée), une fonction qui traite des chaines qu'elle reçoit ne se préoccupe que de les recevoir.
    Et introduire strlen() comme condition de fin de boucle est super lourd (le calcul de la taille est effectué à chaque tour de boucle). Comme je l'ai dit, tu as le '\0' qui te permet de savoir quand terminer ta boucle.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  3. #3
    Membre éclairé
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    septembre 2015
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : septembre 2015
    Messages : 143
    Points : 657
    Points
    657
    Par défaut
    Bonjour


    Beaucoup de choses à dire sur ton code !


    Citation Envoyé par VitelAdam Voir le message
    Les deux chaînes seront passées en paramètre de la fonction.
    ce n'est pas fait

    Tu fais ensuite 2 boucles for (on verra dans un deuxième temps pour les optimisations)
    mais tu n'utilises ni i, ni j, donc à quoi servent ces 2 boucles ?

    à quoi sert ici l'appel à strncpy ?
    pourquoi tu utilises strcmp ? (ça sert à comparer 2 chaines, alors que tu cherches à savoir si A est présent dans B, d'ailleurs avec ou sans la casse ?)


    ton code doit être :
    1. saisie des chaines
    2. contrôle sur les chaines
    3. affichage du résultat

  4. #4
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    bonjour

    @Xelland
    Merci pour ce retour. Ce que j'ai mis est une partie d'un long exercice, j'ai demandé et saisi les deux chaine pour plus de clarté.

    @Sve@r
    Merci pour vos tuyaux, je viens de tester mais il retourne toujours vrai (çàd chaine 2 présente dans chaine 1) dès qu'il trouve un seul caractère.
    Voici ce que j'ai fait , et espérant plus d'éclaircissement, je commence à désespérer ...
    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
     
     
    #include<stdio.h>
    #include<string.h>
     
    int partie_presente(char ch1 [], char ch2[])
    {
        int i=0, j=0;
    	printf("Entrez une chaîne de caractères: ");
    	fgets(ch1,1000,stdin);
    	printf("Entrez la séquence recherchée: ");
    	fgets(ch2,1000,stdin);
     
        for(i = 0; ch1[i] != '\0'; ++i)
    	{
            for(j=0;j<=strlen(ch2);++j)
                while (ch2[j] != ch1[i+j])
    			{
    	            i=i+1;
    	            return 1;
    			}
    	}
    }
     
    int main()
    {
    	 char ch1[1000], ch2[1000];
    	 partie_presente(ch1, ch2);
    	 if (partie_presente)
    	 printf("La séquence est présente\n");
    	 return 0;
    }

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par VitelAdam Voir le message
    Voici ce que j'ai fait , et espérant plus d'éclaircissement, je commence à désespérer ...
    Ta seconde boucle (sur j) utilise encore strlen(). Ok ça le fait mais si la première utilise le '\0', on se demande pourquoi tu n'appliques pas le même procédé sur toutes les chaines.
    Maintenant à quoi sert la 3° boucle ? Je n'ai jamais parlé d'une 3° boucle. J'ai dit "si ch2[j] est différent de ch1[i+j]" et un "si" n'a jamais été traduit par une boucle (boucle inutile puisque tu quittes la fonction à la première itération).
    La base d'un algo c'est le papier et le crayon. Comment tu ferais avec un papier et un crayon si tu ne pouvais voir qu'une lettre à la fois ?
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Sinon question algo c'est pas super compliqué. Une première boucle avec un indice "i" qui balaye ch1. Une seconde boucle avec un second indice "j" qui balaye ch2. Là, si ch2[j] est différent de ch1[i+j] alors tant pis, on passe au "i" suivant et si on atteint la fin de ch1 c'est définitivement perdu (on peut aussi, pour optimiser, s'arrêter avant quand on sait que ch2 ne rentrera plus dans ce qui reste). Et si on arrive à un moment donné à amener "j" au bout de ch2 alors gagné, ch2 est bien dans ch1.
    Bien entendu, si (comme je le pense) pas de strlen() alors il faut se repérer au '\0' terminant toute chaine pour savoir quand terminer la première ou seconde boucle.

    Merci beaucoup pour ce retour, j'ai repris le tout à zéro (et pour être honnête : avec de l'aide ) , et ça marche maintenant. Il faut dire que je me suis compliqué la vie tout seul.
    Pour ce qui est des pointeurs, c'était la consigne.
    Merci encore.
    Problème résolu.

  7. #7
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    1 244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 1 244
    Points : 6 066
    Points
    6 066
    Par défaut
    C'était la consigne, pourtant c'est impossible d'écrire cette fonction sans pointeur. Il y en a partout. Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    bool  partie_presente( const char  ch1[], const char  ch2[] ) {
        const size_t  lg1 = strlen( ch1 );
        const size_t  lg2 = strlen( ch2 );
        if ( lg1 < lg2 )
            return  false;
        for ( size_t  i = 0u ;  i <= lg1 - lg2 ;  ++i )
            if ( strncmp( &ch1[i], ch2 , lg2 ) == 0 )
                return  true; 
        return false;
    }
    C'est mal, j'ai utilisé strlen() et strncmp() qui sont des fonctions qui reçoivent des pointeurs.
    Mais la fonction partie_presente() elle aussi est une fonction qui reçoit 2 pointeurs en paramètres. La notation char ch1[] est en fait juste un alias pour dire char* ch1. Et oui ch1 et ch2 et &ch1[i] sont bien 3 pointeurs.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par VitelAdam Voir le message
    Merci beaucoup pour ce retour, j'ai repris le tout à zéro (et pour être honnête : avec de l'aide ) , et ça marche maintenant. Il faut dire que je me suis compliqué la vie tout seul.

    Problème résolu.
    Reprendre à zéro ça peut être une bonne solution qu'il ne faut en effet pas négliger. Des études ont montré qu'il est parfois plus rentable de tout reprendre à zéro que de s'entêter dnas l'erreur. Unix par exemple a été d'abord un échec pendant 5 ans. Au bout de 5 ans d'efforts, les chercheurs ont tout foutu au panier, ont repris à zéro et ont sorti Unix en 2 ans.
    De l'aide oui tu en as le droit il n'y a pas de mal à ça. Mais maintenant tu ne voudrais pas nous mettre ton code qu'on voit si on peut optimiser certains détails ? Surtout je suis curieux de voir comment est traduit la contrainte "sans pointeur"...

    Citation Envoyé par dalfab Voir le message
    C'était la consigne, pourtant c'est impossible d'écrire cette fonction sans pointeur. Il y en a partout.
    Ce que je pense (et si l'exo est posté je pourrai en avoir confirmation) c'est qu'il ne faut pas utiliser de pointeur dans l'algo. Exemple un for (char *pt=ch; *pt != '\0'; pt++) trt(*pt) sera interdit au profit de for (size_t i=0; ch[i] != '\0'; i++) trt(ch[i]). Je pense aussi que le prof ne veut pas qu'on écrive une sous-fonction qui (par exemple) ferait le boulot de strncmp() (ça a été ma première idée quand j'ai répondu à ce post et ensuite je me suis dit "oui mais on ne pourra pas appeler cette fonction sans lui passer un pointeur") et veut qu'on fasse l'algo dans la fonction principale qui, elle, reçoit fatalement un pointeur mais on ne peut pas faire autrement.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Mais maintenant tu ne voudrais pas nous mettre ton code qu'on voit si on peut optimiser certains détails ? Surtout je suis curieux de voir comment est traduit la contrainte "sans pointeur"...
    Sans aucun problème, le code est joint .
    Quand j'ai parlé de pointeur c'est *char

    Merci encore.
    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
     
    #include <stdio.h>
    #include <string.h>
     
    int partie_presente(char ch[], char seq[])
    {
        int i=0, p=0;
        while(ch[i]!='\0')
        {
            int j=0;
            int k=i;
            while(ch[k]==seq[j])
            {
                k++;
                j++;
     
                if(seq[j+1]=='\0') 
                    p=1;
            }
            i++;
        }
        return p;
    }
     
     
    int main()
    {
        char ch[1000], seq[1000];
        int r=0;
     
        printf("Entrez une chaîne de caractères: ");
        fgets(ch,1000,stdin);
        printf("Entrez la séquence recherchée: ");
        fgets(seq,1000,stdin);
     
        partie_presente(ch, seq);
        r=partie_presente(ch, seq);
     
        if (r==1)
            printf("La séquence est présente\n");
        else if(r==0)
                printf("La séquence n'est pas présente\n");
        return 0;
    }

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par VitelAdam Voir le message
    Quand j'ai parlé de pointeur c'est *char
    Bon ben ça c'est clairement inutile. Ecrire char ch[] ou char *ch pour ton paramètre, c'est exactement pareil, quand on passe un tableau à une fonction on ne lui passe que l'adresse de son premier élément, adresse qui sera alors stockée dans une variable apte à stocker une adresse donc un pointeur. Et la syntaxe n'y fera rien. J'aurais pu admettre toute autre raison telles que celles que j'ai évoquées dans mon post précédent mais refuser l'écriture pointeur juste pour la cacher est probablement une des pires (et des plus inutiles) raison qui soient.

    Sinon ton code il est pas mal du tout. Juste le while () début peut être remplacé par un for () et "p" peut être supprimée si au lieu d'écrire p=1 tu écris directement return 1 (on a trouvé, plus la peine de continuer). Mais certains profs n'aiment pas cette façon de faire que de quitter une fonction en plein milieu car ils disent que cela nuit à la lisibilité du code.

    Accessoirement dans le main() tu appelles 2 fois la fonction. Et bon, t'es sûr que le if (r == 0) dans le "else" est utile ???
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  11. #11
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message

    Mais certains profs n'aiment pas cette façon de faire ...
    Merci pour le conseil,
    à 59 ans, et comme j'ai dit dans mon premier post, je viens de commencer la programmation sous C pour m'occuper et "ne pas vieillir trop vite", aider mes neurones à ne pas tourner en rond en cette période de confinement, déconfinement, couvre-feu, présentiel, télétravail ..... , et la lecture ne me suffit plus pour ne pas ...
    Pourquoi le "C", ? par hasard , après lecture de plein de post sur internet, et ça me rappel les années 80, quand j'étais étudiant, les langages "Basic", puis "QuickBasic" puis "Pascal" et enfin le "Turbo Pascal" avec leurs "goto" ... , ça me manque les "goto", et il parait qu'il faut les éviter dans le "C".
    Merci.
    Cordialement

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    J'ai réécrit la fonction à la mode C

    Code c : 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
    int partie_presente(char ch[], char seq[]) {
    	int i;
     
    	// On traite la chaine
    	for (i=0; ch[i] != '\0'; i++) {
    		int p=1;		// On considère que la séquence est précente
    		int j, k;
     
    		// On traite la séquence
    		for (j=0, k=i; seq[j] != '\0'; j++, k++) {
    			// S'il y a une différence
    			if (ch[k] != seq[j]) {
    				p=0;	// La séquence n'est pas présente
    				break;	// Inutile de continuer la séquence
    			}
    		}
    		// Si p n'a pas été modifié, alors la séquence est présente
    		if (p == 1) return 1;
    	}
    	// Toute la chaine a été traitée, la séquence n'est pas présente
    	return 0;
    }

    Cet algo est un algo type des recherches dans les ensembles (style chaque élement de l'ensemble B est présent dans l'ensemble A). En C on ne peut pas dire "je regarde tous les éléments d'un coup" car on n'a accès qu'à un élément à la fois.
    Dans ce cas, on part du principe que la recherche est vraie dès le départ et qu'effectivement chaque élément de l'ensemble B est réellement présent dans l'ensemble A ; et on cherche ensuite un seul élément qui n'y est pas. Si on le trouve, alors la recherche bascule définitivement en fausse. Sinon elle est vraie. Et donc suffit d'une variable de type "flag" pour initialiser le "la recherche est vraie" puis si la recherche se révèle fausse on la bascule et en fin de boucle on regarde si elle a ou n'a pas basculé.
    Juste ici une particularité supplémentaire parce que ce n'est pas parce que "cde" n'est pas dans "abc" qu'on ne le trouvera pas si la chaine principale est "abcdef". Donc on réinitialise l'algo à chaque itération de la chaine principale et si toute la chaine est traitée sans qu'on sorte à vrai alors c'est que la séquence n'a définitivement pas été trouvée.

    Pour les goto il ne faut pas généraliser à l'extrème. Un "goto" est un outil ; et s'il est employé dans son domaine d'usage alors tout ira bien. Sa mise à l'index vient du fait qu'en basic il n'y a que ça pour créer des algo ce qui a conduit à une utilisation abusive qui amène alors un code finalement illisible. Mais ce n'est pas parce qu'en basic son utilisation a été catastrophique qu'en C ce sera le cas. C'est comme les sucreries, un peu ça va mais il ne faut pas en abuser.
    Exemple dune fonction C un peu complexe où on demande 3 ressources (exemple fichier, mémoire, accès réseau) mais où tout échec sur l'une des 3 conduit alors à quitter la fonction tout en libérant les ressources précédentes qui auraient elles réussi
    Code c : 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
    int fct(...) {
    	r1=ressource1();
    	if (r1 == echec) return -1;
     
    	r2=ressource2();
    	if (r2 == echec) {
    		libérer(r1);
    		return -2;
    	}
     
    	r3=ressource3();
    	if (r3 == echec) {
    		libérer(r1);
    		libérer(r2);
    		return -3;
    	}
    	... (travail)...
     
    	// Fin de la fonction
    	libérer(r1);
    	libérer(r2);
    	libérer(r3);
    	return 0;
    }
    Comme tu le vois, pour être propre cela t'amène à de nombreuses répétitions qui s'alourdiront si tu as 4, 5, 6 ressources.

    Le même avec goto
    Code c : 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
    int fct(...) {
    	int retour=0;
    	r1=ressource1();
    	if (r1 == echec) {
    		retour=-1;
    		goto liberation;
    	}
     
    	r2=ressource2();
    	if (r2 == echec) {
    		retour=-2;
    		goto liberation;
    	}
     
    	r3=ressource3();
    	if (r3 == echec) {
    		retour=-3;
    		goto liberation;
    	}
    	... (travail)...
     
    	liberation:
    	// Fin de la fonction
    	libérer(r1);
    	libérer(r2);
    	libérer(r3);
    	return retour;
    }
    N'est-ce pas plus... simple à coder et à relire (en un mot plus "efficace") ?
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  13. #13
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 790
    Points : 8 485
    Points
    8 485
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Comme tu le vois, pour être propre cela t'amène à de nombreuses répétitions qui s'alourdiront si tu as 4, 5, 6 ressources.
    bof

    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
    int fct(...) {
        r1 = ressource1();
     
        if (r1 != echec) {
            r2 = ressource2();
     
            if (r2 != echec) {
                r3 = ressource3();
     
                if (r3 != echec) {
     
    //              travail
     
                    libérer(r3);
                } else { return -3; }
     
                libérer(r2);
            } else { return -2; }
     
            libérer(r1);
        } else { return -1; }
     
        return 0;
    }
    Et avec les macros (parce que je kiffe les macros ) ... mais peut ne pas marcher, il faut passer 1 argument de + (ne pas se tromper), et libérer dans le sens inverse.

    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
    #define RESSOURCE_GET_TEST(R, NUM) \
        R = ressource ## NUM (); \
         \
        if (R != echec) {
     
    #define RESSOURCE_RELEASE_OR_ERROR(R, NUM) \
        } else { return -NUM; } \
         \
        libérer(R);
     
     
    int fct(...) {
        RESSOURCE_GET_TEST(r1, 1)
        RESSOURCE_GET_TEST(r2, 2)
        RESSOURCE_GET_TEST(r3, 3)
     
    //  travail
     
        RESSOURCE_RELEASE_OR_ERROR(r3, 3)
        RESSOURCE_RELEASE_OR_ERROR(r2, 2)
        RESSOURCE_RELEASE_OR_ERROR(r1, 1)
     
        return 0;
    }
    N'est-ce pas plus... simple à coder et à relire (en un mot plus "efficace") ?

  14. #14
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message

    J'ai réécrit la fonction à la mode C
    ....

    Cet algo est un algo type des recherches dans les ensembles (style chaque élément de l'ensemble B est présent dans l'ensemble A). En C on ne peut pas dire "je regarde tous les éléments d'un coup" car on n'a accès qu'à un élément à la fois.
    ...

    Pour les goto il ne faut pas généraliser à l'extrême.
    ...
    Excellent ! J'en apprends des choses ici .... merci.


  15. #15
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par foetus Voir le message

    Et avec les macros (parce que je kiffe les macros ) ... mais peut ne pas marcher, il faut passer 1 argument de + (ne pas se tromper), et libérer dans le sens inverse.
    Merci pour ce retour, mais je ne sais pas encore ce qu'est une macro dans C, je ne suis qu'à mes débuts.
    Je me suis mis au C que depuis 5-6 semaines. Je le fais le soir (pas tard) quand j'ai tout fini après le travail.

    Au fait l'exercice est en plusieurs étapes, voilà le résumé :
    1) Sans utiliser les pointeurs, compter le nombre de caractères d'une chaine .
    2) Copier un tableau de caractère dans un tableau de même dimension.
    3) Ranger un tableau de nombres dans un ordre croissant.
    4) Chercher si un caractère est dans une chaine.
    5) Chercher si une chaine de caractères est dans une chaine.
    6) le prochain :

    Je pense, vu comment sont présentés les exercices, que le but est de trier une liste de personne (Nom-Prénom) et la mettre dans l'ordre alphabétique , et donc utilisation de tableaux de deux dimensions ... ça va trop vite pour moi.

  16. #16
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    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
    int fct(...) {
        r1 = ressource1();
     
        if (r1 != echec) {
            r2 = ressource2();
     
            if (r2 != echec) {
                r3 = ressource3();
     
                if (r3 != echec) {
     
    //              travail
     
                    libérer(r3);
                } else { return -3; }
     
                libérer(r2);
            } else { return -2; }
     
            libérer(r1);
        } else { return -1; }
     
        return 0;
    }
    Le souci principal de cette façon de coder (qui est en fait la façon académique qu'on apprend dans les livres d'algo) c'est que si tu as 7 ou 8 ressources et que tu tabules à chaque étape, tu te retrouves à coder ton travail sur les 3 dernières colonnes de droite de ton écran.
    Et bon là ça restait encore simple. Maintenant si on alloue un tableau 3D dimension par dimension avec obligation de nettoyage de tout ce qui a été alloué si échec interne...

    Citation Envoyé par foetus Voir le message
    N'est-ce pas plus... simple à coder et à relire (en un mot plus "efficace") ?
    Quel humour

    Citation Envoyé par VitelAdam Voir le message
    Je me suis mis au C que depuis 5-6 semaines.
    Je ne sais pas pourquoi tu as eu brusquement envie de faire du C... mais si c'est juste pour t'amuser à programmer alors perso j'aurais plutôt conseillé Python. C'est un langage de plus en plus plébiscité. Il est rapide, a une syntaxe agréable et permet de monter rapidement de petits trucs sympas (bien plus rapidement qu'en C). Tout en offrant aussi une granularité équivalente au C car il permet aussi de descendre au niveau du bit.
    Le même sujet en Python: def partie_presente(ch, seq): return seq in ch. Je pense qu'il n'y a pas photo concernant la simplicité et assez simple sur sa syntaxe.
    Mais le C te donnera l'occasion d'explorer effectivement des choses très bas niveau dans ton os comme la manipulation des fichiers, de la mémoire, etc. Bon comme je l'ai dit tout dépend de ton besoin (aucun langage de programmation n'est parfait. Il n'existe même pas un langage meilleur que d'autres ; il n'y a que des langages en adéquation ou peu conseillés pour des buts particuliers, Herbert Mayer)

    Citation Envoyé par VitelAdam Voir le message
    Au fait l'exercice est en plusieurs étapes, voilà le résumé :
    1) Sans utiliser les pointeurs, compter le nombre de caractères d'une chaine .
    2) Copier un tableau de caractère dans un tableau de même dimension.
    3) Ranger un tableau de nombres dans un ordre croissant.
    4) Chercher si un caractère est dans une chaine.
    5) Chercher si une chaine de caractères est dans une chaine.
    6) le prochain :
    Le 1 et 2 ok. J'aimerais bien voir comment tu as traité le 3 (à mon avis tu as dû partir sur un tri à bulles).

    Citation Envoyé par VitelAdam Voir le message
    Je pense, vu comment sont présentés les exercices, que le but est de trier une liste de personne (Nom-Prénom) et la mettre dans l'ordre alphabétique , et donc utilisation de tableaux de deux dimensions ... ça va trop vite pour moi.
    Hum... oui la 2D ça le fait mais ici je partirais plutôt sur une structure qui offre des avantages de syntaxe. Mais cela dépend de si tu connais ou pas la notion de structure.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  17. #17
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 790
    Points : 8 485
    Points
    8 485
    Par défaut
    Citation Envoyé par VitelAdam Voir le message
    Merci pour ce retour, mais je ne sais pas encore ce qu'est une macro dans C, je ne suis qu'à mes débuts.
    En C, il y a le préprocesseur
    Préprocesseur C, source wiki en français

    En gros, les étapes sont : préprocesseur puis compilation puis édition des liens.
    Le préprocesseur est là pour faire des traitements avant la compilation. Ce sont tous les mots clefs qui commencent pas # :
    • #include : pour inclure 1 fichier. Le préprocesseur va remplacer l'appel par l'intégralité du fichier
    • #define/ #undef : pour définir/ supprimer des macros, c'est à dire des bouts de code pas forcément 1 fonction/ procédure. Le préprocesseur va remplacer l'appel par le code et y remplacer les paramètres. Et il est très basique, il faut faire très attention, il y a des fois des surprises.
    • #define/ #undef : pour définir/ supprimer des variables globales constantes. On peut aussi passer par la bascule -D avec gcc
    • #if/ #ifdef]/ #ifndef/ #else/ #elsif/ #endif/ defined : pour faire du code spécifique pour 1 plateforme spécifique/ pour 1 cible spécifique (debug, release, ...)
    • #pragma/ #pragma link : pour définir des options de compilation/ d'édition des liens
    • #error/ #warning : pas certain que celles là sont de la norme

    Tu verras, le préprocesseur est très très basique ... et des fois surprenant


    Citation Envoyé par Sve@r Voir le message
    Le souci principal de cette façon de coder (qui est en fait la façon académique qu'on apprend dans les livres d'algo) c'est que si tu as 7 ou 8 ressources et que tu tabules à chaque étape, tu te retrouves à coder ton travail sur les 3 dernières colonnes de droite de ton écran.
    Écran 4K 32 pouces, 250 colonnes à l'aise, rien à carrer

    Plus sérieusement , l'avantage par rapport au goto, c'est que tu peux faire des macros et oublier l'indentation (mon 2ième code). Avec le goto, les répétitions sont moins visibles/ évidentes et tu as toujours à la fin 1 bout de code (quelques lignes) avec toutes les libérations.
    Sinon tu peux faire également à la toute fin, tester chaque variable et si elle n'est pas NULL, la libérer. C'est 1 peu comme le goto mais avec + de tests

  18. #18
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    janvier 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : janvier 2021
    Messages : 8
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Sve@r Voir le message


    J'aimerais bien voir comment tu as traité le 3 (à mon avis tu as dû partir sur un tri à bulles).

    ...

    Hum... oui la 2D ça le fait mais ici je partirais plutôt sur une structure qui offre des avantages de syntaxe. Mais cela dépend de si tu connais ou pas la notion de structure.
    Ci-joint ce que j'ai fait pour le 3.
    Je ne sais pas de quoi tu parles en parlant de "notion de structure". ça va trop vite pour moi ....

    Autrement, je vais faire une pause et revenir sur le tout début et refaire les exercices ou d'autres dans le même état d'esprit, pas la peine de cavaler si ce n'est pas encore bien assimiler.

    Merci.
    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
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    int main()
    {
        int i, j, N, tmp, max;
    //Saisie de la taille du tableau
        printf("Saisir la taille du tableau:");
        scanf("%i", &N);
     
    //Définition du tableau selon la taille prédéfinie
        int tab[N];
     
    //Saisie des valeurs du tableau
        for(i=0; i<N; i++)
        {
        	printf("Saisir le nombre n° %i:", i+1);
            scanf("%i",&tab[i]);
        }
     
    //Tri par sélection du tableau
        for (i=0; i<=N-1; i++)
        {
    	max=i;
    	for (j=i+1; j<N; j++)
    	{
    		if (tab[j] > tab[max]) 
    		{
    			max=j;
    		}
        }
    	tmp=tab[i];
    	tab[i]=tab[max];
    	tab[max]=tmp;
        }
     
    //Affichage du tableau trié dans l'ordre décroissant
        for (i=0; i<N; i++)  
        {
    	printf("%7i", tab[i]);
        }
        return 0;	
    }

  19. #19
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 790
    Points : 8 485
    Points
    8 485
    Par défaut
    Citation Envoyé par VitelAdam Voir le message
    Ci-joint ce que j'ai fait pour le 3.
    Ton code n'est pas correct

    Déjà, il faut définir (avec ou sans initialisation) toutes tes variables au début. Il me semble que c'est la norme C99 qui permet de la flexibilité.
    Et le problème c'est que tu utilises 1 VLA ("variable-length array") ... déprécié depuis la norme C11. En gros, c'est 1 tableau qui est défini avec comme taille 1 variable.

    Il faut passer par l'allocation dynamique : malloc et free

    Et tu peux faire 1 macro ... la fameuse macro swap (mais qui dépend de la variable tmp)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define SWAP_2_INTS(X, Y) \
    	tmp = X; \
    	X = Y; \
    	Y = tmp;

  20. #20
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 806
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 806
    Points : 24 168
    Points
    24 168
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    Il faut passer par l'allocation dynamique : malloc et free
    A mon avis, il n'en est pas encore là...

    @VitelAdam La remarque de foetus est tout à fait correcte pour un code de pro mais d'un trop haut niveau pour un débutant.
    Ce qu'il te dit, c'est qu'écrire tab[N] (avec N variable) ce n'est pas super tip/top car cela est un mix entre un tableau de taille fixe et un tableau alloué dynamiquement. Or quand on a le cul entre deux chaises, on a de grandes chances de tomber.
    L'allocation dynamique permet de demander de la ram quand la taille n'est pas connue au moment où on écrit le code (ou si la taille varie). Et surtout si l'OS ne peut pas donner la taille demandée il te prévient et tu peux utiliser une solution de contournement, ce que ne fait pas le tab[N] (dans ce cas ton code plante). Mais comme ici ce n'est pas le sujet du TP (qui est clairement pour t'apprendre à trier un tableau et non pour t'apprendre à gérer l'allocation dynamique), de mon côté je te conseille de te définir une taille arbitraire (ex tab[10]) et bloquer l'utilisateur à une saisie de 10 chiffres.
    Et de façon plus générale, quand on te dit "faites ceci avec votre tableau", ne te préoccupe pas de demander à l'utilisateur quelle taille il veut pour son tableau, ce n'est clairement pas le but du TP. Ni même de le remplir. Tu fais une fonction qui reçoit le tableau et qui fait le job en présumant que le tableau est rempli et ensuite tu peux coder le remplissage dans le main() ou même créer le tableau déjà rempli. Et en plus cela t'apprendra à découper les choses et à différencier "entrée des données" (qui pourront ne pas venir obligatoirement du clavier) et "traitement des données"; qui est une méthode de programmation évolutive.
    Exemple où j'ai repris ton code selon ces principes de découpage
    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    // Prototypes des fonctions
    void swap(int*, int*);
    void tri(int[], size_t, char);
    void saisie(int tab[], size_t n);
    void affich(int tab[], size_t n);
     
    // Fonction de swap entre deux int
    void swap(int *x, int *y) {
    	int tmp;
    	tmp=(*x);
    	(*x)=(*y);
    	(*y)=tmp;
    }
     
    // Fonction de tri
    void tri(int tab[], size_t n, char sens) {
    	size_t i;
    	size_t j; 
    	size_t max;
     
    	// Tri par sélection du tableau
    	for (i=0; i < n; i++) {
    		// Recherche élément à changer de place
    		max=i;
    		for (j=i+1; j < n; j++) {
    			switch (sens) {
    				case '<': // Tri croissant
    					if (tab[j] < tab[max]) max=j;
    					break;
    				case '>': // Tri décroissant
    					if (tab[j] > tab[max]) max=j;
    					break;
    			}
    		}
     
    		// Swap entre élément courant et élément sélectionné
    		if (i != max) swap(&tab[i], &tab[max]);
    	}
    }
     
    // Saisie du tableau
    void saisie(int tab[], size_t n) {
    	size_t i;
     
    	// Saisie des valeurs du tableau
    	for (i=0; i < n; i++) {
    		printf("Saisir le nombre n° %lu:", i+1);
    		scanf("%i",&tab[i]);
    	}
    }
     
    // Affichage du tableau
    void affich(int tab[], size_t n) {
    	size_t i;
     
    	// Affichage des valeurs du tableau
    	for (i=0; i < n; i++)
    		printf("%7i", tab[i]);
    }
     
    // Programme principal
    int main() {
    	size_t n;
     
    	// Saisie de la taille du tableau
    	printf("Saisir la taille du tableau:");
    	scanf("%lu", &n);
     
    	// Définition du tableau selon la taille prédéfinie
    	int tab[n];
     
    	// Saisie des valeurs du tableau
    	saisie(tab, n);
     
    	// Tri du tableau dans le sens de mon choix
    	tri(tab, n, '>');
     
    	// Affichage du tableau trié
    	affich(tab, n);
    }
    C'est comme les légos. Plus une fonction est minimaliste, plus tu peux la réutiliser facilement dans différentes configurations.


    Sinon une structure c'est un ensemble permettant de regrouper divers éléments (exemple une date sera un jour, un mois et une année). L'avantage c'est que la structure est ensuite manipulable d'un bloc (tu peux la prendre, la passer à une fonction et la fonction aura alors accès à ses éléments jour/mois/année). Bref un truc à manipuler au lieu de 3 tout en ayant quand-même accès ensuite aux trois. Bon tu apprendras ça plus tard.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Liste chaînée sans pointeur
    Par lyes312 dans le forum Langage
    Réponses: 19
    Dernier message: 21/06/2008, 19h39
  2. Problème de gestion de chaînes avec pointeur
    Par LorDjidane dans le forum C
    Réponses: 18
    Dernier message: 19/10/2005, 16h40
  3. [String] Récupérer une sous -chaîne sans split
    Par Crazyblinkgirl dans le forum Langage
    Réponses: 3
    Dernier message: 19/07/2004, 15h45
  4. [TTreeView] Problème avec les pointeurs d'objet
    Par BlackWood dans le forum Composants VCL
    Réponses: 2
    Dernier message: 02/07/2004, 15h31
  5. Problème passage de pointeur
    Par mick74 dans le forum MFC
    Réponses: 2
    Dernier message: 21/04/2004, 19h34

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