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 de passage par adresse dans un sous-programme


Sujet :

C

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 7
    Par défaut Problème de passage par adresse dans un sous-programme
    Bonjour,
    je reviens vers vous une seconde fois car je rencontre un nouveau problème que je n'arrive pas à résoudre seul. (toujours dans la réalisation de mon programme de Rogue-Like basique)
    Malgré mes recherches sur Internet, je n'arrive pas à comprendre, alors j'espère que vous pourrez m'aider à y voir plus clair.

    Le plus simple étant de vous présenter la partie du code posant problème, 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
     
    .
    .
    .
    //declaration procédure de combat//
    void combat(sHeros unJoueur, sMob unTableauDeMobs[LIGNES][COLONNES], int Coordonnee1, int Coordonnee2);
    .
    .
    .
    main()
    .
    .
    .
    //Sous programme de combat//
    void combat(sHeros joueur, sMob map[LIGNES][COLONNES], int x, int y)
    {
        int jo,jm;
        srand(time(NULL));
        jo=joueur.Habilete + rand()%6 + rand()%6;
        jm=(map[x][y].Habilete) + rand()%6 + rand()%6;
        if (jm>jo)
        {
            *joueur.Endurance = (joueur.Endurance-map[x][y].Degats);
            printf("%s vous attaque et vous a blesse.", map[x][y].Espece);
        }
        if (jo>jm)
        {
            *map[x][y].Endurance = (map[x][y].Endurance-2);
            printf("Vous avez touché %s.", map[x][y].Espece);
        }
        if (jo=jm)
        {
            printf("%s vous a rate, et vous ne touchez pas %s non plus.", map[x][y].Espece, map[x][y].Espece);
        }
    }
    A la compilation, j'obtiens alors 2 fois la même erreur sur les deux lignes avec un pointeur : invalid type argument of unary ‘*’ (have ‘int’)
    Les valeurs Endurance, Habileté sont des entiers dans les deux cas, et j'ai beau lire les nombreux topics traitant de cette erreur sur Google, pas moyen de comprendre mon erreur....

    (J'ai surement oublié d’intégrer à la portion de code présentée quelques détails qui peuvent être importants, si c'est le cas demandez-moi)

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Avec tes structures concernées ça serait déjà plus simple pour t'aider...

    Si tu pouvais donner aussi les lignes dans le code où tu as tes erreurs, ça aiderait aussi !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *joueur.Endurance = ...
    C'est louche ! non ?

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 7
    Par défaut
    Les structures concernées sont :
    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
    //Déclaration structure héros//
    struct Heros
    {
        int Corps, Intellect, Esprit, Or, Endurance, Habilete;
        char Nom[20];
    };
    typedef struct Heros sHeros;
     
    //Déclaration structure Monstre//
    struct Monstre
    {
        char Symbol;
        char* Espece;
        int Endurance, Habilete, Degats;
    };
    typedef struct Monstre sMob;
    Et les deux lignes qui me renvoient une erreur sont :
    - *joueur.Endurance = (joueur.Endurance-map[x][y].Degats);
    - *map[x][y].Endurance = (map[x][y].Endurance-2);

    Mais je ne vois pas ce qu'il y a de louche...

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Le moyen le plus simple dans un cas comme ça est de nous donner un code minimal reproduisant l'erreur. Cela permet de visualiser le code en un seul bloc, on peut le compiler et discuter par rapport aux numéros de lignes.

    Ces 2 lignes présentent le même pattern : *struct.champ = struct.champ. Pourquoi y a t-il une étoile d'un côté et pas de l'autre ?

  5. #5
    Invité
    Invité(e)
    Par défaut
    C'est surtout que la variable joueur passé en paramètre n'est pas un pointeur.

    Rien que ça explique le tout.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Maskeren 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
     
    struct Heros
    {
        int Corps, Intellect, Esprit, Or, Endurance, Habilete;
        char Nom[20];
    };
    typedef struct Heros sHeros;
     
    void combat(sHeros joueur, sMob map[LIGNES][COLONNES], int x, int y)
    {
            ...
            *joueur.Endurance = (joueur.Endurance-map[x][y].Degats);
    Bonjour
    joueur n'est pas un pointeur. Donc c'est joueur.Endurance= et non *joueur.Endurance=. D'ailleurs même si joueur était un pointeur ça n'irait pas non plus écrit comme ça car là, ça signifie que c'est "Endurance" qui est un pointeur et non "joueur". Il faudrait écrire en fait (*joueur).Endurance=, écriture qui a été implémentée par l'opérateur flèche => joueur->Endurance=.

    Autres remarques en passant: main est de type int, et c'est bien d'avoir mis un préfixe "s" à ton type structuré mais généralement on le réserve pour la structure elle-même et on met un préfixe "t" pour "type"...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct sHeros {
        int Corps, Intellect, Esprit, Or, Endurance, Habilete;
        char Nom[20];
    };
    typedef struct sHeros tHeros;

    Ou plus simplement (si on n'a pas besoin de réutiliser le nom de la structure avant d'avoir créé le type associé)...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct {
        int Corps, Intellect, Esprit, Or, Endurance, Habilete;
        char Nom[20];
    } tHeros;

    Citation Envoyé par Maskeren Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //Déclaration structure Monstre//
    struct Monstre {
        char Symbol;
        char* Espece;
        int Endurance, Habilete, Degats;
    };
    Ouh là là, j'espère que le membre "Espece" est alloué avant d'être rempli, ou bien qu'il pointe vers une zone mémoire statique parce que sinon, comportement indéterminé...
    Mon Tutoriel sur la programmation «Python»
    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
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 7
    Par défaut
    Voilà un code minimal pour avoir toutes les infos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <conio.h>
     
    #define LIGNES 20
    #define COLONNES 40
     
    #define SOL ' '
    #define ARAIGNEE 207
     
    //Déclaration structure héros//
    struct Heros
    {
        int Corps, Intellect, Esprit, Or, Endurance, Habilete;
        char Nom[20];
    };
    typedef struct Heros sHeros;
     
    //Déclaration structure Monstre//
    struct Monstre
    {
        char Symbol;
        char* Espece;
        int Endurance, Habilete, Degats;
    };
    typedef struct Monstre sMob;
     
    //declaration procédure de combat//
    void combat(sHeros unJoueur, sMob unTableauDeMobs[LIGNES][COLONNES], int Coordonnee1, int Coordonnee2);
     
    int main()
    {
        //Declaration personnage//
        sHeros Player;
        //Introduction//
        printf("\n Nom du personnage : ");
        scanf("%s",Player.Nom);
        system("cls");
        printf("\n Bienvenue %s.\n",Player.Nom);
        printf(" Une fois dans le donjon, tapez ? pour une liste des commandes, \n ainsi qu'une legende.\n");
        fflush(stdin);
        getchar();
        system("cls");
        //Attribution des caracteristiques//
        Player.Or=0;
        srand(time(NULL));
        Player.Corps= 10 + rand()%7;
        Player.Intellect= 10 + rand()%7;
        Player.Esprit= 10 + rand()%7;
        Player.Endurance=(Player.Corps)*2+Player.Esprit;
        Player.Habilete=((Player.Corps)*2+Player.Esprit+Player.Intellect)/4;
     
        //Déclaration des types de monstres//
        sMob VIDE={SOL,"Vide",0,0,0};
        sMob SPID={ARAIGNEE,"Araignee",3,10,3};
     
        //Map de monstres//
        sMob MobMap[LIGNES][COLONNES]=
        {
         ......    //Je vous épargne le tableau, il est très long et n'apporte rien ici//
        }
    return(0);
    }
     
    //Sous programme de combat//
    void combat(sHeros joueur, sMob map[LIGNES][COLONNES], int x, int y)
    {
        int jo,jm;
        srand(time(NULL));
        jo=joueur.Habilete + rand()%6 + rand()%6;
        jm=(map[x][y].Habilete) + rand()%6 + rand()%6;
        if (jm>jo)
        {
            *joueur.Endurance = (joueur.Endurance-map[x][y].Degats);
            printf("%s vous attaque et vous a blesse.", map[x][y].Espece);
        }
        if (jo>jm)
        {
            *map[x][y].Endurance = (map[x][y].Endurance-2);
            printf("Vous avez touché %s.", map[x][y].Espece);
        }
        if (jo=jm)
        {
            printf("%s vous a rate, et vous ne touchez pas %s non plus.", map[x][y].Espece, map[x][y].Espece);
        }
    }
    Je trouve ça bizarre aussi de faire pointeur=entier... mais ça fonctionne bien dans un autre sous programme.
    Sinon, pour ce qui est du préfixe 's' devant la structure, c'est notre prof d'algo qui y tient particulièrement, et j'ai choppé le réflexe du coup.

    Je suis désolé si j'écris des aberrations dans mon code, mais j'ai encore du mal avec les pointeurs....

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Maskeren Voir le message
    Je trouve ça bizarre aussi de faire pointeur=entier... mais ça fonctionne bien dans un autre sous programme.
    Mauvais réflexe. Ce n'est pas parce que "ça fonctionne" que c'est correct. Et (corollaire), écrire quelque chose d'incorrect reste incorrect. Le gros pb du C, c'est qu'une instruction incorrecte mais possible (stocker un entier dans une variable prévue pour recevoir une adresse est tout à fait possible puisqu'une adresse n'est en final que du nombre) produit un comportement indéterminé (c'est à dire "imprévisible"). Ca peut planter; ça peut ne pas planter; ça peut planter les jour pairs et fonctionner les jours impairs; ça peut fonctionner jusqu'au moment où tu lances Firefox et là ça plante. Bref c'est imprévisible.

    Autre chose: pas de fflush(stdin). Et ne dis surtout pas que c'est ton prof qui vous dit de le faire...

    Citation Envoyé par Maskeren Voir le message
    Sinon, pour ce qui est du préfixe 's' devant la structure, c'est notre prof d'algo qui y tient particulièrement, et j'ai choppé le réflexe du coup.
    Oui, "s" devant un nom de structure (comme mon premier exemple) c'est bien. Et par transitivité, "t" devant un nom de type. Ce n'est qu'une convention bien sûr mais avec ta façon de nommer les choses, le token "Monstre" et "Heros" devient inutilisable pour un nom de variable. Et pire, plus tard à la relecture, on peut penser que "Monstre" est un nom de variable alors que c'est un nom de structure...

    Citation Envoyé par Maskeren Voir le message
    Je suis désolé si j'écris des aberrations dans mon code, mais j'ai encore du mal avec les pointeurs....
    Alors faut régler ce soucis immédiatement avant de faire quoi que ce soit d'autre car les pointeurs sont l'essence du C...
    Mon Tutoriel sur la programmation «Python»
    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
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    ...

    Autre chose: pas de fflush(stdin). Et ne dis surtout pas que c'est ton prof qui vous dit de le faire...
    C'est la mode des profs qui enseigne le C sous windows, ça ...
    ( Je l'ai eu également en cours C, et le prof était tout perdu quand je lui ai dis que "ça marche pas sous Linux" )

  10. #10
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 7
    Par défaut
    J'ai lu la partie de la FAQ C qui explique pourquoi fflush(stdin) est déconseillé, mais je ne suis pas certain d'avoir compris.
    C'est simplement parce que ce n'est pas portable ?

    Citation Envoyé par archMqx. Voir le message
    C'est la mode des profs qui enseigne le C sous windows, ça ...
    ( Je l'ai eu également en cours, et le prof était tout perdu quand je lui ai dis que "ça marche pas sous Linux" )
    C'est effectivement notre cas, nos profs d'Algo nous ont dit qu'ils étaient tous sous Linux, ils en ont vanté les mérites, etc...
    " - Et donc ?
    - Et donc vous allez coder sous Windows. "

    Bon, ceci dit, quand je vois ce que fait un de mes amis qui est entré à Epitech cette année, je me dis que pour le moment, Windows ce sera très bien.

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Maskeren Voir le message
    C'est simplement parce que ce n'est pas portable ?
    D'une part effectivement. Et d'autre part, c'est que cela revient à nier le contenu de stdin au lieu de le traiter. Parce que s'il y a des trucs dedans, c'est que quelque chose l'y a mis et que celui qui l'y a mis a alors besoin que le programme le traite au lieu de le purger.
    Ce n'est pas parce que ça s'appelle "stdin" que c'est forcément lié au clavier. Il existe des outils qui permettent de lier la sortie d'un programme X à l'entrée d'un programme Y. Dans cette configuration, tout le stdout du programme X devient le stdin du programme Y. Ca permet ainsi d'établir des chaines de traitement complexes à partir de programmes simples (on voit plutôt ça dans le monde Unix/Linux). Or si un programme Z intermédiaire se met à purger stdin, tout s'écroule.
    Inversement si stdin contient des trucs génant, il faut alors remonter à la source du problème et soigner le mal plutôt que les symptômes.

    Accessoirement l'orgine est connue car c'est souvent scanf() (saisie "formatée") qui, contrairement à ce que t'a dit ton prof, n'est absolument pas fait pour la saisie humaine. Parce que ce que tape un humain est tout sauf formaté. Ne serait-ce que dans le <return> que tu tapes pour saisir ton nombre dans int nbr; scanf("%d", &nbr) et qui, n'étant pas numérique, reste alors dans stdin et polluant alors toute saisie ultèrieure.
    Donc pas de scanf alors pas de problème de stdin et donc pas de fflush(stdin).
    Voici une fonction permettant de saisir un nombre et laissant ton stdin aussi pur que le jour de sa naissance
    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
    int get_int(int *nbr)
    {
        char buf[1024];
        fgets(buf, 1024, stdin);
        return sscanf(buf, "%d", nbr);
    }
     
    int main()
    {
        int age;
        printf("Saisissez votre age\n");
        if (get_int(&age) != 0)
            printf("Vous avez %d ans\n", age);
        else
            printf("Votre saisie est incorrecte !!!\n");
    }

    Facilement adaptable aux float et aux doubles. Ensuite on peut lui demander d'afficher elle-même la question qu'on lui passera alors en paramètre, lui faire boucler tant qu'un nombre correct n'aura pas été saisi, bref faire une fonction de saisie vraiment contrôlée. Ceci dit, on peut pas en vouloir aux profs. Cette façon de saisir implique un certain degré de connaissances et sur le fonctionnement des choses et sur les pointeurs. Or, quand on débute et qu'on n'a pas ces connaissances et qu'il faut avoir une méthode de saisie pour les TP, scanf() reste alors la seule solution possible. Simplement ensuite il faut rapidement en changer.

    Faut pas te faire d'illusion: si les programmeurs Unix/Linux n'ont pas implémenté fflush(stdin), c'est qu'ils savaient qu'un code bien écrit n'en a pas besoin (et qu'ils n'allaient pas non plus se casser le noeud à implémenter quelque chose fait pour rattrapper du code écrit avec les pieds). Inversement le fait que ça ait été implémenté sous Windows laisse songeur quand à la qualité du code de cet OS...
    Mon Tutoriel sur la programmation «Python»
    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
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 7
    Par défaut
    Merci pour l'explication.
    Par contre, je vais tout de même éviter d'utiliser d'autres méthodes de saisie (du moins dans le cadre du projet), parce que notre prof aime moyennement qu'on utilise des solutions trop éloignées de celles qu'il nous a fourni.
    Je ne lui reproche pas ce manque de souplesse, parce qu'il ne fait pas ça pour nous gêner, mais bien parce que certains ne savent déjà pas faire certaines choses basiques.

    C'est pas pour faire preuve de condescendance que je vais dire ça, mais même moi qui suis un débutant, j'ai vu des choses qui piquaient les yeux.

    En tout cas, je vais devoir passer du temps sur les pointeurs, on nous avait prévenu que c'était délicat.

Discussions similaires

  1. Problème de passage par adresse.
    Par azmodai dans le forum C
    Réponses: 4
    Dernier message: 15/05/2010, 09h55
  2. Passage par valeur / passage par adresse
    Par jeje99 dans le forum C++
    Réponses: 13
    Dernier message: 16/02/2006, 10h29
  3. passage par adresse
    Par cari dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 01/02/2006, 11h33
  4. Réponses: 9
    Dernier message: 13/05/2005, 03h13
  5. [Debutant(e)]passage par adresse?
    Par cap2fosse dans le forum Langage
    Réponses: 4
    Dernier message: 24/09/2004, 10h05

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