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 :

Comment incrémenter une variable passée en paramètre à une fonction récursive


Sujet :

C

  1. #1
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut Comment incrémenter une variable passée en paramètre à une fonction récursive
    Salut à tous!
    J'essaye de faire un programme qui résoud le casse-tête des huit reines. IL s'agit de placer sur un échiquier 8 reines sur des diagonales,des verticales et des horizontales différentes.
    Voila le problème c'est que je n'arrive pas à arréter la fonction qui remplit l'échiquier, et le but de l'exercice est de retourner le nombre total de possibilités. Je voulais donc incrémenter une variable "soluce" à chaque fois que le programme réussit à placer huit reines.
    Mais quand je teste, le programme donne toujours à "soluce" des valeurs aléatoires. Le code:
    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
    void fill(int tab[8][8],int n, int soluce,int end)
    {
    	int i,j,k=-1;
    	char c;
    	//printf("SOLUCE_deb %d\n", *soluce);
    	if((end)!=2)
    	{
    		/*if(tab[0][7]==8)
    		{
    			scanf("&c",c);
    			printf("s%d",tab[0][7]);
    			(end)++;
    		}*/
    		for(i=0;i<8;i++)
    		{
    			if(tab[n][i]==8)
    			{
    				k=i;
    				cancel(tab,n,i);
    				break;
    			}
    		}
    		for(j=k+1;j<8;j++)
    		{
    			if(tab[n][j]==0)
    			{
    				lock(tab,n,j);
    				k=-2;
    				break;
    			}
    		}
    		if(k!=-2)
    		{
    			fill(tab,n-1,soluce,end);
    		}
    		if((n!=7)&&(k==-2))
    			fill(tab,n+1,soluce,end);
    		if((n==7)&&(k==-2))
    		{
    			//printf("soluce: %d,end: %d\n",*soluce,*end);
    			//printf("kjo");
    			//*printf("SOLUCE_deb %d\n", *soluce);
    			soluce++;
    			for(i=0;i<8;i++)//L'affichage n'est pas obligatoire,il me permet juste de vérifier qu'il y a 8 reines.
    			{
    				for(j=0;j<8;j++)
    					printf("%02d  ",tab[i][j]);
    				printf("\n");
    			}
    			printf("SOLUCE_fin %d\nend: %d", soluce,end);
    			printf("\n\n");
    			printf("soluce: %d,end: %d\n",soluce,end);
    			fill(tab,n,soluce,end);
    		}
    		if((tab[0][7]==0)&&((end)==1))
    		{
    			(end)++;
    		}
    	}
    }
    Fichiers attachés Fichiers attachés

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 892
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 892
    Points : 219 438
    Points
    219 438
    Billets dans le blog
    123
    Par défaut
    Bonjour,

    Ce forum, étant doté des dernières fonctionnalités du Web 2.5, propose des balises [ code ] et [ /code ] (sans espaces) permettant de donner une présentation digne des derniers films à effet spéciaux (Avatar) ou même 3D, pour le code (Et tout ça en TechniColor)
    De plus, grace à sa technologie touchscreen, vous pouvez (muni d'un dispositif de pointage) cliquer sur le bouton représentant un '#' afin d'intégrer directement les balises dans le messages.

    Pour votre problème, je pense que la solution trop simple est:
    - Utilisation d'une variable globale

    Mais, ce qui est conseillé, c'est de passé la variable soluce par pointeur, à la place de passer des copies à chaque appel à la fonction. Plus de détails -> http://chgi.developpez.com/pointeur/

  3. #3
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    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
    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
    {
    int i,j,k=-1;
    char c;
    //printf("SOLUCE_deb %d\n", *soluce);
    if((end)!=2)
    {
    /*if(tab[0][7]==8)
    {
    scanf("&c",c);
    printf("s%d",tab[0][7]);
    (end)++;
    }*/
    for(i=0;i<8;i++)
    {
    if(tab[n][i]==8)
    {
    k=i;
    cancel(tab,n,i);
    break;
    }
    }
    for(j=k+1;j<8;j++)
    {
    if(tab[n][j]==0)
    {
    lock(tab,n,j);
    k=-2;
    break;
    }
    }
    if(k!=-2)
    {
    fill(tab,n-1,soluce,end);
    }
    if((n!=7)&&(k==-2))
    fill(tab,n+1,soluce,end);
    if((n==7)&&(k==-2))
    {
    //printf("soluce: %d,end: %d\n",*soluce,*end);
    //printf("kjo");
    //*printf("SOLUCE_deb %d\n", *soluce);
    soluce++;
    for(i=0;i<8;i++)//L'affichage n'est pas obligatoire,il me permet juste de vérifier qu'il y a 8 reines.
    {
    for(j=0;j<8;j++)
    printf("%02d ",tab[i][j]);
    printf("\n");
    }
    printf("SOLUCE_fin %d\nend: %d", soluce,end);
    printf("\n\n");
    printf("soluce: %d,end: %d\n",soluce,end);
    fill(tab,n,soluce,end);
    }
    if((tab[0][7]==0)&&((end)==1))
    {
    (end)++;
    }
    }
    }
    Je vais essayer la variable globale tout de suite pour voir, mais je pour la variable "soluce" , j'utilise un pointeur (je crois) dans ce code. Parce qu'en appelant la fonction fill (dans le main) je lui envoie d'abord un int* (l'adresse de l'entier à incrémenter).Ensuite,comme c'est une fonction récursive je met directement "soluce" en paramètre au prochain rappel (soluce est un int* dans fill).

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut
    Tout marche nickel avec la variable globale!
    Mais je veux quand même comprendre pourquoi ça ne marchait pas avant.

  5. #5
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    En C, une fonction reçoit une "copie" des arguments qui lui sont passés. Elle peut les modifier à volonté, les modifications ne sont pas visibles pour l'appelant.

    Le fait de mettre une variable "en globale" résoud ce problème, parce que la fonction va aller modifier un emplacement mémoire commun à tout le monde.
    Cependant, c'est souvent loin d'être une solution optimale à tous les problèmes (maintenir du code avec des globales est très difficile).

    Une autre solution serait que la fonction fill retourne le nombre de solutions via l'instruction "return". Dans ton cas c'est peut-être le meilleur compromis "simplicité" vs "beauté du code".

    Enfin une solution consiste à passer un pointeur sur soluce, et non sa valeur. C'est pas forcément le plus simple, surtout si tu n'as pas d'expérience avec les pointeurs. Mais c'est très enrichissant, et obligatoire dès qu'un projet devient un peu sérieux.

  6. #6
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut
    Citation Envoyé par phi1981 Voir le message
    Une autre solution serait que la fonction fill retourne le nombre de solutions via l'instruction "return". Dans ton cas c'est peut-être le meilleur compromis "simplicité" vs "beauté du code".
    Pour tout ce qui est variable globale, j'ai compris.Mais comment la fonction fill peut elle renvoyer un nombre de solutions vu qu'elle s'appelle elle-même?C'est pourquoi j'ai préféré faire un void.

  7. #7
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 892
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 892
    Points : 219 438
    Points
    219 438
    Billets dans le blog
    123
    Par défaut
    Personnellement, en regardant le code (celui en piece jointe) je vois tres bien que vous n'utilisez pas de pointeur.
    Car, la fonction fill serait la suivante, avec un pointeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void fill(int tab[8][8],int n, int* soluce,int end)
    EDIT: J'avais oublie de mettre '*' pour pointeur

  8. #8
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    Citation Envoyé par dré kam Voir le message
    Pour tout ce qui est variable globale, j'ai compris.Mais comment la fonction fill peut elle renvoyer un nombre de solutions vu qu'elle s'appelle elle-même?C'est pourquoi j'ai préféré faire un void.
    Rien ne l'empeche de retourner "soluce" + la valeur retournée par la récursion d'elle même.

  9. #9
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut
    Pourquoi le prototype ne serait pas plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fill(int tab[8][8], int n, int* soluce, int end)
    , par exemple?
    Et quels sont les dangers des variables globales dans les "programmes sérieux"?

  10. #10
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 892
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 892
    Points : 219 438
    Points
    219 438
    Billets dans le blog
    123
    Par défaut


    J'avais fait une erreur lors de ma reponse precedente.

    D'ailleurs, il est vrai que le retour de fonction peut etre meilleur (comme solution).

    Le probleme des pointeurs, c'est que leurs fait faire des operations, changeant la variable pointe, ce qui entraine bien souvent, des acces a des parties de la memoire non detenu par le programme (Donc erreur, car le systeme nous empeche de toucher ce qui n'est pas a nous).
    De plus, le jour ou vous passer 'NULL' a votre fonction, cela crashe lamentable. (NULL ou autre pointeur invalide)

    Les pointeurs sont unes grande source de bugs, car on peut faire des choses incroyables avec.

  11. #11
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    Oui en effet, LittleWhite avait visiblement oublié une *
    ça prouve que tu suis !!

    Les problèmes avec les globales sont légions, du coup voici plutot mes expériences personnelles :
    - J'ai maintenu un programme qui était à l'origine conçu dans l'esprit "il n'y a qu'un seul document ouvert, du coup le texte de ce document est en globale". Evidemment mon premier job sur ce projet ça a été de faire en sorte qu'on puisse ouvrir plusieurs documents à la fois. Modifier toutes les fonctions qui accédaient au texte pour que désormais elles utilisent un pointeur vers le texte a été vraiment infernal.
    - Plein de fois où je dois modifier une globale, j'ai peur qu'une autre partie du programme cesse de fonctionner, tout simplement parce qu'elle ne s'attendait pas à ce que cette valeur change à ce moment là.
    - Le compilateur détecte le fait qu'une variable locale est utilisée avant d'être initialisée (presque toujours). Ce n'est pas le cas avec une globale.
    - J'adore pouvoir appeler une fonction écrite il y a plusieurs années par quelqu'un d'autre sans avoir à me dire "heu .... faut il que je positionne une globale à une certaine valeur avant de l'appeler ???".

  12. #12
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut
    C'est bien ce que j'avais fait dans mon programme initial, que j'ai dmodifié avant de créer la discussion (par désespoir sûrement!!). Mais j'avais un résultat bizarre: au 3 premières itérations j'avais des valeurs bizarres, puis ça incrémentait normalement à partir de 0.
    Finalement je crée une variable locale que j'incrémente et que le fonction fill retourne au main (parce que le main va être créé juste pour corriger mon taf).
    Et je peut déclarer mon problème résolu!
    Merci à tous!

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 10/03/2014, 21h54
  2. Modification d'une variable passée en paramètre
    Par kstou2001 dans le forum Shell et commandes GNU
    Réponses: 20
    Dernier message: 21/05/2012, 15h05
  3. Réponses: 4
    Dernier message: 23/09/2010, 22h32
  4. Réponses: 14
    Dernier message: 29/07/2008, 12h33
  5. Nom d'une variable passée en paramètre à une fonction
    Par cata2 dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 07/09/2007, 09h17

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