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 :

Echanger deux valeurs


Sujet :

C

  1. #1
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par Horrigan
    Sisi, j'ai bien compris ce qu'étaient les pointeurs et comment on s'en servait, mais ce que j'ai pas compris, c'est leur utilité, mon livre n'en fait pas mention
    Il te reste des choses a apprendre, c'est normal. Fais tourner ce petit programme, par exemple, et essaie d'expliquer pourquoi cela ne se passe pas comme prevu:
    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
     
    #include <stdio.h>
     
    void swap(int a, int b)
    {
      int temp = a;
      a = b;
      b = temp;
    }
     
    int main(void)
    {
       int c = 3;
       int d = 87;
     
       printf("c = %d d = %d\n", c, d);
       swap(c, d);
       printf("c = %d d = %d\n", c, d);
     
       return 0;
    }

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 30
    Par défaut
    c = 3 d = 87
    c = 3 d = 87

    ahhhhh !!!!
    c'est pas possible
    vraiment là je comprends pas

  3. #3
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Horrigan
    c = 3 d = 87
    c = 3 d = 87

    ahhhhh !!!!
    c'est pas possible
    vraiment là je comprends pas
    C'est tout simplement parce que les passages de paramètres en C se font par recopie de la valeur. Si on modifie la valeur d'un paramètre, on ne modifie pas la variable originale.

    Pour pouvoir la modifier, une seule solution, passer son adresse
    à la fonction, ce qui la rend accessible via un paramètre de type pointeur (il suffit d'utiliser l'opérateur * pour atteindre la valeur de la variable).

  4. #4
    Membre confirmé Avatar de skip78
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 247
    Par défaut
    Autrement dit :
    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
     
    #include <stdio.h>
     
    void swap(int* a, int* b)
    {
      int temp;
      temp = *a;
      *a = *b;
      *b = temp;
    }
     
    int main(void)
    {
       int c = 3;
       int d = 87;
     
       printf("c = %d d = %d\n", c, d);
       swap(&c,&d);
       printf("c = %d d = %d\n", c, d);
     
       system("pause");
       return 0;
    }
    Ici on fait un truc assez astucieux c'est que l'on à même pas besoin de manipuler les pointeurs dans le main, on les inverse juste dans la fonction, à laquelle on fournit les deux adresses. Ainsi on à bien des pointeurs sur adresse, donc des valeurs.

    Sinon tu peut faire ca :

    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
     
    #include <stdio.h>
     
    typedef struct duo{
      int a,b;
    }duo;
     
    duo swap(int c,int d)
    {
      duo x;
      int temp = c;
      x.a = d;
      x.b = temp;
      return x;
    }
     
    int main(void)
    {
       int c = 3;
       int d = 87;
       duo y;
     
       printf("c = %d d = %d\n", c, d);
       y = swap(c, d);
       printf("c = %d d = %d\n", y.a, y.b);
       system("pause");
       return 0;
    }

  5. #5
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par skip78
    Autrement dit :
    T'es gentil, mais le but est de faire refléchir le P.O., pas de poster des solutions toutes faites qu'il va recopier sans comprendre...

  6. #6
    Membre confirmé Avatar de skip78
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 247
    Par défaut
    Oui je suis d'accord mais sincèrement il faut le voir pour comprendre. Tu peut pas trouver ca tout seul ... Il s'agit donc de comprendre pourquoi il faut faire comme ca, et de visualiser le cheminement de l'information. Ensuite, un fois le principe acquis, il pourra s'entrainer avec des petits exercices.
    Mais souviens toi l'époque ou tu ne connaissais pas les pointeurs (en tout cas pour moi c'était comme ca) il t'as fallu quelques minutes pour comprendre le principe, mais pour comprendre comment les utiliser c'est autre chose. Par conséquent un programme exemple me parait indispensable. Ce programme est d'ailleurs le programme référencé comme celui expliquant le mieux le principe c'est pas comme si c'était la partie de son projet sur laquelle il buttait ...

  7. #7
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    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
     
    #include <stdio.h>
     
    typedef struct duo{
      int a,b;
    }duo;
     
    duo swap(int c,int d)
    {
      duo x;
      int temp = c;
      x.a = d;
      x.b = temp;
      return x;
    }
     
    int main(void)
    {
       int c = 3;
       int d = 87;
       duo y;
     
       printf("c = %d d = %d\n", c, d);
       y = swap(c, d);
       printf("c = %d d = %d\n", y.a, y.b);
       system("pause");
       return 0;
    }
    Pour ma part, j'aurais tout de même transmis l'adresse de la structure duo dans la fonction swap au lieu des 2 entiers.
    En fait, comme la première méthode mais avec une structure.

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Et pourquoi pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void swap(int *pa, int *pb)
    {
    *pa ^= *pb ^= *pa ^= *pb;
    }
    Ici, pas besoin de structure, ni de temporaire.
    Par contre, je trouve que la fonction d'homeostasie embrouille l'utilisateur plusqu'autre chose: D'une part, le temporaire ne sert à rien, d'autre part, on se retrouve avec un type de retour différent du type d'entrée.
    Mais même en gardant le prototype, j'aurais plutôt fait comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    duo swap(int c, int d)
    {
    duo x = { d, c };
    return x;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Médinoc
    Et pourquoi pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void swap(int *pa, int *pb)
    {
    *pa ^= *pb ^= *pa ^= *pb;
    }
    Ici, pas besoin de structure, ni de temporaire.
    Par contre, je trouve que la fonction d'homeostasie embrouille l'utilisateur plusqu'autre chose: D'une part, le temporaire ne sert à rien, d'autre part, on se retrouve avec un type de retour différent du type d'entrée.
    Mais même en gardant le prototype, j'aurais plutôt fait comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    duo swap(int c, int d)
    {
    duo x = { d, c };
    return x;
    }
    Hum, tu n'as pas défini la structure (dans le genre embrouillage, c'est pas mal aussi...). Pas sûr que ce soit plus simple au niveau de l'appel...

    Le swap() avec les pointeurs est 'idiomatique'. Il est extensible aux autres types facilement.

    La solution XOR est élégante sur le plan mathématique, mais pourrait très bien générer des traps avec des types autres que unsigned char (valeur intermédiaire interdite).

  10. #10
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Par contre, je trouve que la fonction d'homeostasie embrouille l'utilisateur plusqu'autre chose: D'une part, le temporaire ne sert à rien, d'autre part, on se retrouve avec un type de retour différent du type d'entrée.
    Mais ce n'est pas mon fonction, je proposais qu'au lieu de retourner une structure, de transmettre directement l'adresse de la structure dans cette fonction proposée.
    En fait, un jour j'ai lu qu'il faut éviter de retourner des structures, notamment celle qui dépasse plus de deux objets. Ici ce n'est pas la cas car il y en a juste deux. Par contre je ne suis plus trop la raison? Peut être un problème d'alignement...mais je ne m'avancerais pas sur cela!

    void swap(int *pa, int *pb)
    {
    *pa ^= *pb ^= *pa ^= *pb;
    }
    Ceci, je n'avais jamais vu....Eh bien, impressionnant!

  11. #11
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par homeostasie
    Mais ce n'est pas mon fonction, je proposais qu'au lieu de retourner une structure, de transmettre directement l'adresse de la structure dans cette fonction proposée.
    Tout à fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    typedef struct
    {
       int a;
       int b;
    }
    duo;
     
    void swap (duo *this)
    {
       int a = this->a;
       this->a = this->b;
       this->b = a;
    }

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Emmanuel: Je supposais la structure déjà définie dans l'autre code, bien entendu

    homeostasie: Oups, je te présente humblement mes excuses, je n'avais pas vu que tu ne faisais que la citer.
    Le problème pour retourner une structure, c'est la taille. Si la structure est trop grande pour tenir dans un ou deux registres (8 octets tiennent dans EDX:EAX sur un i386), il faut retourner la structure en passant par la mémoire, ce qui est compliqué.

    Pour la fonction, elle n'est pas de moi (je l'avais vu sur un autre forum), mais je l'avais appréciée. En développant un peu, on arrive assez facilement à voir comment ça marche.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Bon comme vous avez l'air de bien vous amuser avec l'échange de valeurs, c'est inutile de continu à polluer la question de Horrigan.

    Citation Envoyé par Médinoc
    En développant un peu, on arrive assez facilement à voir comment ça marche.
    C'est l'opérateur XOR qui fait tout le travail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    C = A xor B
    A = C xor B
    B = C xor A
    Quelqu'un connait la fonction parfaire qui fonctionne avec tous les types, sans variable temporaire ni risque de débordement ?

  14. #14
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    Citation Envoyé par Médinoc
    Et pourquoi pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void swap(int *pa, int *pb)
    {
    *pa ^= *pb ^= *pa ^= *pb;
    }
    Astucieux en théorie, mais à éviter dans la pratique : ce genre de code est cauchemardesque pour un compilateur parce que inoptimisable.
    Donc même sans variable temporaire additionnelle , certainement le swap le plus lent du monde !

  15. #15
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    J'ai failli avoir une crise cardiaque : je ne souvenais pas d'avoir demarre un sujet sur 'echanger deux valeurs'

    Citation Envoyé par rigobert
    Astucieux en théorie, mais à éviter dans la pratique : ce genre de code est cauchemardesque pour un compilateur parce que inoptimisable.
    Le plus gros probleme avec la methode des ^, c'est qu'elle n'est pas portable : *pa est evalue deux fois dans la meme sequence, donc le comportement est indefini.

  16. #16
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    gege2061: Pourquoi ajoutes-tu un temporaire?

    Citation Envoyé par DaZumba
    *pa est evalue deux fois dans la meme sequence, donc le comportement est indefini.
    ah, bizarre. Pour moi, c'était supposé faire à tout les coups l'équivalent de ceci (l'expression de départ étant évaluée de droite à gauche) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void swap(int *pa, int *pb)
    {
    *pa ^= *pb;	//A = A xor B  ---> a=A^B    b=B
    *pb ^= *pa;	//B = A xor B  ---> a=A^B    b=A^B^B --> a=A^B  b=A
    *pa ^= *pb;	//A = A xor B  ---> a=A^A^B  b=A     --> a=B    b=A
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par DaZumba
    J'ai failli avoir une crise cardiaque : je ne souvenais pas d'avoir demarre un sujet sur 'echanger deux valeurs'
    Désolé pour le choc

    Citation Envoyé par Médinoc
    gege2061: Pourquoi ajoutes-tu un temporaire?
    Parce que c'est juste le fonctionnement de xor et sans temporaire ça revient à la même chose que ton code : pas très lisible

  18. #18
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par Médinoc
    ah, bizarre. Pour moi, c'était supposé faire à tout les coups l'équivalent de ceci (l'expression de départ étant évaluée de droite à gauche)
    Non, c'est indefini, pour la meme raison que i++ = i++; est indefini.
    Il y a une interessante discussion ici.

Discussions similaires

  1. Echange de valeurs entre deux Strings
    Par Daborem dans le forum Débuter
    Réponses: 6
    Dernier message: 31/05/2015, 09h02
  2. Echanger les valeurs entre deux select
    Par otmaneo01 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 22/03/2015, 11h13
  3. Echange de valeurs entre deux fenêtres en C#-WPF
    Par Invité dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 07/01/2014, 02h13
  4. Echanger la valeur de deux variables
    Par gege2061 dans le forum Télécharger
    Réponses: 0
    Dernier message: 30/11/2010, 17h34
  5. Echanger/Swap de deux valeurs dans une table
    Par Yvan76 dans le forum Requêtes
    Réponses: 1
    Dernier message: 07/08/2009, 16h23

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