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 :

[Structures de données] Accès à l'élément suivant d'un menu


Sujet :

C

  1. #1
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut [Structures de données] Accès à l'élément suivant d'un menu
    Bonjour,

    pour représenter un menu, j'ai proposé la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef struct menu{
    	char label[255];
    	struct menu *next; /* the next item */
    	struct menu *sub; /* the sub menu */
    } Menu;
    Voici le menu de mon exemple :


    Le problème qui se pose est lorsque j'essaye de récupérer l'élément suivant de 'Options' (c'est à dire 'Exit').
    Ma fonction nextMenu semble échouer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $ ./a.out 2>/dev/null
    main: call menuNext on label 'Play'
    main: label is now 'Options'
    main: call menuNext on label 'Options'
    main: label is now 'TVï¿'
    main: call menuNext on label 'TVï¿'
    main: label is now 'TVï¿'
    Voici le code complet :
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
     
    #include<stdio.h> /* For printf, fprintf */
    #include<stdlib.h> /* For NULL, stderr */
    #include<string.h> /* For strcpy */
     
    /* Structures */
    typedef struct menu{
    	char label[255];
    	struct menu *next; /* the next item */
    	struct menu *sub; /* the sub menu */
    } Menu;
     
    /* Functions */
    Menu* menuCreate(char* label, Menu *next, Menu *sub){
    	fprintf(stderr, "menuCreate: start\n");
    	Menu *menu;
    	menu = malloc(2 * sizeof(Menu));
    	strcpy(menu->label, label);
    	menu->next = next;
    	menu->sub = sub;
    	fprintf(stderr, "\tmenuCreate: label='%s'\n", menu->label);
    	fprintf(stderr, "menuCreate: end\n");
    	return(menu);
    }
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	/* if it is found */
    	if(menu->label==label){
    		fprintf(stderr, "\tmenuNext: label '%s' found\n", menu->label);
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu->next);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu);
    		}
    	}
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    			menuNext(menu->sub, label);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    			menuNext(menu->next, label);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    	}
    }
     
    /* Main function */
    int main(){
    	Menu *menu1, *menu_current;
    	menu1=menuCreate(
    		"Play\0",
    		menuCreate(
    			"Options\0",
    			menuCreate(
    				"Exit\0",
    				NULL,
    				NULL
    			),
    			menuCreate(
    				"Video\0",
    				menuCreate(
    					"Audio\0",
    					menuCreate(
    						"Control\0",
    						menuCreate(
    							"Game\0",
    							menuCreate(
    								"Back\0",
    								NULL,
    								NULL
    							),
    							NULL
    						),
    						NULL
    					),
    					NULL
    				),
    				NULL
    			)
    		),
    		NULL
    	);
    	menu_current=menu1;
     
    	/* Call menuNext 3 times */
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
     
    	return(0);
    }
    Qui peut m'expliquer pourquoi je n'obtiens pas 'Exit'?

    Merci beaucoup.

  2. #2
    Membre émérite
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	if(menu->label==label){
    C'est comme celà que tu compare des chaines de caractères ?

  3. #3
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Ah oui bien vu

    Voici la correction donc :
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
     
    #include<stdio.h> /* For printf, fprintf */
    #include<stdlib.h> /* For NULL, stderr */
    #include<string.h> /* For strcpy */
     
    /* Structures */
    typedef struct menu{
    	char label[255];
    	struct menu *next; /* the next item */
    	struct menu *sub; /* the sub menu */
    } Menu;
     
    /* Functions */
    Menu* menuCreate(char* label, Menu *next, Menu *sub){
    	fprintf(stderr, "menuCreate: start\n");
    	Menu *menu;
    	menu = malloc(2 * sizeof(Menu));
    	strcpy(menu->label, label);
    	menu->next = next;
    	menu->sub = sub;
    	fprintf(stderr, "\tmenuCreate: label='%s'\n", menu->label);
    	fprintf(stderr, "menuCreate: end\n");
    	return(menu);
    }
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	/* if it is found */
    	if(strcmp(menu->label, label) == 0){
    		fprintf(stderr, "\tmenuNext: label '%s' found\n", menu->label);
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu->next);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu);
    		}
    	}
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    			menuNext(menu->sub, label);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    			menuNext(menu->next, label);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    	}
    }
     
    /* Main function */
    int main(){
    	Menu *menu1, *menu_current;
    	menu1=menuCreate(
    		"Play\0",
    		menuCreate(
    			"Options\0",
    			menuCreate(
    				"Exit\0",
    				NULL,
    				NULL
    			),
    			menuCreate(
    				"Video\0",
    				menuCreate(
    					"Audio\0",
    					menuCreate(
    						"Control\0",
    						menuCreate(
    							"Game\0",
    							menuCreate(
    								"Back\0",
    								NULL,
    								NULL
    							),
    							NULL
    						),
    						NULL
    					),
    					NULL
    				),
    				NULL
    			)
    		),
    		NULL
    	);
    	menu_current=menu1;
     
    	/* Call menuNext 3 times */
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
     
    	return(0);
    }
    Pourtant le programme réagit toujours de la même façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $ ./a.out 2>/dev/null
    main: call menuNext on label 'Play'
    main: label is now 'Options'
    main: call menuNext on label 'Options'
    main: label is now 't¿'
    main: call menuNext on label 't¿'
    main: label is now 't¿'
    Pourquoi ne parvient t'il pas à passer à l'élément suivant de 'Options'?

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pourquoi la fonction menuNext() ne renvoie t-elle rien lorsqu'on passe par le else du if(strcmp(menu->label, label) == 0)... et pourquoi les valeurs de retour des appels récursifs à menuNext() sont-elles ignorées ?

  5. #5
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    C'est vrai, il me semble que quelques return ont été oubliés

    Voici la correction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
     
    #include<stdio.h> /* For printf, fprintf */
    #include<stdlib.h> /* For NULL, stderr */
    #include<string.h> /* For strcpy */
     
    /* Structures */
    typedef struct menu{
    	char label[255];
    	struct menu *next; /* the next item */
    	struct menu *sub; /* the sub menu */
    } Menu;
     
    /* Functions */
    Menu* menuCreate(char* label, Menu *next, Menu *sub){
    	fprintf(stderr, "menuCreate: start\n");
    	Menu *menu;
    	menu = malloc(2 * sizeof(Menu));
    	strcpy(menu->label, label);
    	menu->next = next;
    	menu->sub = sub;
    	fprintf(stderr, "\tmenuCreate: label='%s'\n", menu->label);
    	fprintf(stderr, "menuCreate: end\n");
    	return(menu);
    }
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	/* if it is found */
    	if(strcmp(menu->label, label) == 0){
    		fprintf(stderr, "\tmenuNext: label '%s' found\n", menu->label);
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu->next);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu);
    		}
    	}
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    			return(menuNext(menu->sub, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    			return(menuNext(menu->next, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    	}
    }
     
    /* Main function */
    int main(){
    	Menu *menu1, *menu_current;
    	menu1=menuCreate(
    		"Play\0",
    		menuCreate(
    			"Options\0",
    			menuCreate(
    				"Exit\0",
    				NULL,
    				NULL
    			),
    			menuCreate(
    				"Video\0",
    				menuCreate(
    					"Audio\0",
    					menuCreate(
    						"Control\0",
    						menuCreate(
    							"Game\0",
    							menuCreate(
    								"Back\0",
    								NULL,
    								NULL
    							),
    							NULL
    						),
    						NULL
    					),
    					NULL
    				),
    				NULL
    			)
    		),
    		NULL
    	);
    	menu_current=menu1;
     
    	/* Call menuNext 3 times */
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
    	printf("main: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label);
     
    	return(0);
    }
    Le résultat me satisfait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $ ./a.out 2>/dev/null
    main: call menuNext on label 'Play'
    main: label is now 'Options'
    main: call menuNext on label 'Options'
    main: label is now 'Exit'
    main: call menuNext on label 'Exit'
    main: label is now ' `õù6þ6þ¿86þ¿ ùê·Àôù·`õù6þ6þ¿X6þ¿8P`õù6þ6þ¿x6þ¿Ph`õù6þ6þ¿6þ¿hÄ6þ¿ôïù·àLþ·'
    Je pense aussi que j'ai commis une boulette sur l'allocation mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    menu = malloc(2 * sizeof(Menu));
    Devrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    menu = malloc(sizeof(Menu));
    tout simplement.
    Pas vrai?

  6. #6
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pas vrai?
    Si évidemment !

  7. #7
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Ok dans ce cas une petite correction s'impose :
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
     
    #include<stdio.h> /* For printf, fprintf */
    #include<stdlib.h> /* For NULL, stderr */
    #include<string.h> /* For strcpy */
     
    /* Structures */
    typedef struct menu{
    	char label[255];
    	struct menu *next; /* the next item */
    	struct menu *sub; /* the sub menu */
    } Menu;
     
    /* Functions */
    Menu* menuCreate(char* label, Menu *next, Menu *sub){
    	fprintf(stderr, "menuCreate: start\n");
    	Menu *menu;
    	menu = malloc(sizeof(Menu));
    	strcpy(menu->label, label);
    	menu->next = next;
    	menu->sub = sub;
    	fprintf(stderr, "\tmenuCreate: label='%s'\n", menu->label);
    	fprintf(stderr, "menuCreate: end\n");
    	return(menu);
    }
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	/* if it is found */
    	if(strcmp(menu->label, label) == 0){
    		fprintf(stderr, "\tmenuNext: label '%s' found\n", menu->label);
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu->next);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu);
    		}
    	}
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    			return(menuNext(menu->sub, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    			return(menuNext(menu->next, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    	}
    }
     
    /* Main function */
    int main(){
    	Menu *menu1, *menu_current;
    	menu1=menuCreate(
    		"Play\0",
    		menuCreate(
    			"Options\0",
    			menuCreate(
    				"Exit\0",
    				NULL,
    				NULL
    			),
    			menuCreate(
    				"Video\0",
    				menuCreate(
    					"Audio\0",
    					menuCreate(
    						"Control\0",
    						menuCreate(
    							"Game\0",
    							menuCreate(
    								"Back\0",
    								NULL,
    								NULL
    							),
    							NULL
    						),
    						NULL
    					),
    					NULL
    				),
    				NULL
    			)
    		),
    		NULL
    	);
    	menu_current=menu1;
     
    	/* Call menuNext on 'Play' */
    	printf("\nmain: call menuNext on label '%s'\n", "Play\0");
    	menu_current=menuNext(menu1, "Play\0");
    	printf("main: label is now '%s'\n", menu_current->label); /* Options */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Exit */
     
    	/* Call menuNext when there isn't a next */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Exit */
     
    	/* Call menuNext on 'Video' */
    	printf("\nmain: call menuNext on label '%s'\n", "Video\0");
    	menu_current=menuNext(menu1, "Video\0");
    	printf("main: label is now '%s'\n", menu_current->label); /* Audio */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Control */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Game */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Back */
     
    	/* Call menuNext when there isn't a next */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Back */
     
    	return(0);
    }
    Voici le résultat :
    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
     
    $ ./a.out 2>/dev/null
     
    main: call menuNext on label 'Play'
    main: label is now 'Options'
     
    main: call menuNext on label 'Options'
    main: label is now 'Exit'
     
    main: call menuNext on label 'Exit'
    main: label is now '▒`E
    ž▒¡®¿▒¡®¿H¡®¿▒Iû·ÀD
    ž`E
    ž▒¡®¿▒¡®¿h¡®¿(X8`E
    ž▒¡®¿▒¡®¿¡®¿8XH`E
    ž▒¡®¿▒¡®¿š¡®¿HXhÔ¡®¿ô?
    žàž'
     
    main: call menuNext on label 'Video'
    main: label is now 'Audio'
     
    main: call menuNext on label 'Audio'
    main: label is now 'Control'
     
    main: call menuNext on label 'Control'
    main: label is now 'Game'
     
    main: call menuNext on label 'Game'
    main: label is now 'Back'
     
    main: call menuNext on label 'Back'
    main: label is now 'Back'
    J'ai ajouté tous les cas de tests possibles pour l'appel de la fonction menuNext. Sur 8 cas, 1 pose problème, celui lorsque j'essaye d'avoir le suivant de 'Exit' alors qu'il n'y en a pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    main: call menuNext on label 'Exit'
    main: label is now '▒`E
    ž▒¡®¿▒¡®¿H¡®¿▒Iû·ÀD
    ž`E
    ž▒¡®¿▒¡®¿h¡®¿(X8`E
    ž▒¡®¿▒¡®¿¡®¿8XH`E
    ž▒¡®¿▒¡®¿š¡®¿HXhÔ¡®¿ô?
    žàž'
    Le programme était sensé me renvoyer 'Exit' étant donné que le suivant de 'Exit' n'existe pas.
    Il a pourtant bien réussi à le faire pour 'Back' étant donné que le suivant de 'Back' n'existe pas, il m'a retourné 'Back'.

    Pourquoi ne parvient-t-il pas à me retourner le suivant de 'Exit'?

  8. #8
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    La fonction menuNext() a encore la possibilité de sortir sans renvoyer une valeur :
    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
    Menu* menuNext(Menu *menu, char* label){
    ...
    	if(strcmp(menu->label, label) == 0){...
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){...
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){...
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    	}
    /***********************************************************
     On peut arriver ici : si menu->sub == NULL et menu->next == NULL et pas de return ....
    ************************************************************/
    }

  9. #9
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Sérieux il faut avoir l'œil partout
    Je te remercie beaucoup.

    Voici la correction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
    #include<stdio.h> /* For printf, fprintf */
    #include<stdlib.h> /* For NULL, stderr */
    #include<string.h> /* For strcpy */
     
    /* Structures */
    typedef struct menu{
    	char label[255];
    	struct menu *next; /* the next item */
    	struct menu *sub; /* the sub menu */
    } Menu;
     
    /* Functions */
    Menu* menuCreate(char* label, Menu *next, Menu *sub){
    	fprintf(stderr, "menuCreate: start\n");
    	Menu *menu;
    	menu = malloc(sizeof(Menu));
    	strcpy(menu->label, label);
    	menu->next = next;
    	menu->sub = sub;
    	fprintf(stderr, "\tmenuCreate: label='%s'\n", menu->label);
    	fprintf(stderr, "menuCreate: end\n");
    	return(menu);
    }
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	/* if it is found */
    	if(strcmp(menu->label, label) == 0){
    		fprintf(stderr, "\tmenuNext: label '%s' found\n", menu->label);
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu->next);
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    			fprintf(stderr, "menuNext: end\n");
    			return(menu);
    		}
    	}
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    			return(menuNext(menu->sub, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    			return(menuNext(menu->next, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    		fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    		return(menu);
    	}
    }
     
    /* Main function */
    int main(){
    	Menu *menu1, *menu_current;
    	menu1=menuCreate(
    		"Play\0",
    		menuCreate(
    			"Options\0",
    			menuCreate(
    				"Exit\0",
    				NULL,
    				NULL
    			),
    			menuCreate(
    				"Video\0",
    				menuCreate(
    					"Audio\0",
    					menuCreate(
    						"Control\0",
    						menuCreate(
    							"Game\0",
    							menuCreate(
    								"Back\0",
    								NULL,
    								NULL
    							),
    							NULL
    						),
    						NULL
    					),
    					NULL
    				),
    				NULL
    			)
    		),
    		NULL
    	);
    	menu_current=menu1;
     
    	/* Call menuNext on 'Play' */
    	printf("\nmain: call menuNext on label '%s'\n", "Play\0");
    	menu_current=menuNext(menu1, "Play\0");
    	printf("main: label is now '%s'\n", menu_current->label); /* Options */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Exit */
     
    	/* Call menuNext when there isn't a next */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Exit */
     
    	/* Call menuNext on 'Video' */
    	printf("\nmain: call menuNext on label '%s'\n", "Video\0");
    	menu_current=menuNext(menu1, "Video\0");
    	printf("main: label is now '%s'\n", menu_current->label); /* Audio */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Control */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Game */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Back */
     
    	/* Call menuNext when there isn't a next */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Back */
     
    	return(0);
    }
    Et le résultat :
    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
     
    $ ./a.out 2>/dev/null
     
    main: call menuNext on label 'Play'
    main: label is now 'Options'
     
    main: call menuNext on label 'Options'
    main: label is now 'Exit'
     
    main: call menuNext on label 'Exit'
    main: label is now 'Back'
     
    main: call menuNext on label 'Video'
    main: label is now 'Audio'
     
    main: call menuNext on label 'Audio'
    main: label is now 'Control'
     
    main: call menuNext on label 'Control'
    main: label is now 'Game'
     
    main: call menuNext on label 'Game'
    main: label is now 'Back'
     
    main: call menuNext on label 'Back'
    main: label is now 'Back'
    Cette fois la fonction retourne une valeur quoi qu'il arrive. Mais le problème c'est qu'elle retourne des valeurs fausses sur 1 cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    main: call menuNext on label 'Exit'
    main: label is now 'Back'
    Le programme nous dit que le suivant de 'Exit' c'est 'Back'. C'est une erreur car 'Exit' n'a pas de suivant et 'Exit' devrait donc être retourné.

    Donc ce n'est pas encore ça...
    Comment parvenir à renvoyer 'Exit' lorsqu'on appel menuNext sur 'Exit' ?

  10. #10
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Finalement au lieu de tricher sur les valeurs autant renvoyer NULL quand effectivement il n'y a plus d'élément suivant. Ça simplifie grandement le problème.
    De toute façon, je pourrais toujours passer par une fonction intermédiaire qui vérifie si l'élément suivant est NULL. Dans ce cas, elle ne modifiera pas la position dans le menu.

    Voici 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
     
    #include<stdio.h> /* For printf, fprintf */
    #include<stdlib.h> /* For NULL, stderr */
    #include<string.h> /* For strcpy */
     
    /* Structures */
    typedef struct menu{
    	char label[255];
    	struct menu *next;
    	struct menu *sub;
    } Menu;
     
    /* Functions */
    Menu* menuCreate(char* label, Menu *next, Menu *sub){
    	fprintf(stderr, "menuCreate: start\n");
    	Menu *menu;
    	menu = malloc(sizeof(Menu));
    	strcpy(menu->label, label);
    	menu->next = next;
    	menu->sub = sub;
    	fprintf(stderr, "\tmenuCreate: label='%s'\n", menu->label);
    	fprintf(stderr, "menuCreate: end\n");
    	return(menu);
    }
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	/* if it is found */
    	if( (strcmp(menu->label, label) == 0) && (menu->next != NULL)){
    		fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    		fprintf(stderr, "menuNext: end\n");
    		return(menu->next);
    	}
    	else{
    		/* if it has a sub */
    		if(menu->sub != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    			return(menuNext(menu->sub, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a sub\n", menu->label);
    		}
    		/* if it has a next */
    		if(menu->next != NULL){
    			fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    			return(menuNext(menu->next, label));
    		}
    		else{
    			fprintf(stderr, "\tmenuNext: label '%s' havn't a next\n", menu->label);
    		}
    	}
    	fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    	return(NULL);
    }
    Les résultats sont satifsaisants pour mon ancien exemple.
    Voici un nouvel exemple de menu :



    Pour cet exemple, les résultats sont incorrects :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $ ./a.out 2>/dev/null
     
    main: call menuNext on label 'Play'
    main: label is now 'Options'
     
    main: call menuNext on label 'Options'
    main: label is now '(null)'
    En effet, l'élément suivant de 'Options' devrait être 'Exit'.

    Voici le main :
    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
     
    /* Main function */
    int main(){
    	Menu *menu1, *menu_current;
    	menu1=menuCreate(
    		"Play\0",
    		menuCreate(
    			"Options\0",
    			menuCreate(
    				"Exit\0",
    				NULL,
    				NULL
    			),
    			menuCreate(
    				"Video\0",
    				menuCreate(
    					"Audio\0",
    					menuCreate(
    						"Control\0",
    						menuCreate(
    							"Game\0",
    							menuCreate(
    								"Back\0",
    								NULL,
    								NULL
    							),
    							NULL
    						),
    						NULL
    					),
    					NULL
    				),
    				NULL
    			)
    		),
    		menuCreate(
    			"1 player\0",
    			menuCreate(
    				"2 players\0",
    				menuCreate(
    					"Back\0",
    					NULL,
    					NULL
    				),
    				NULL
    			),
    			NULL
    		)
    	);
    	menu_current=menu1;
     
    	/* Call menuNext on 'Play' */
    	printf("\nmain: call menuNext on label '%s'\n", "Play\0");
    	menu_current=menuNext(menu1, "Play\0");
    	printf("main: label is now '%s'\n", menu_current->label); /* Options */
    	printf("\nmain: call menuNext on label '%s'\n", menu_current->label);
    	menu_current=menuNext(menu1, menu_current->label);
    	printf("main: label is now '%s'\n", menu_current->label); /* Exit */
    return(0);
    }
    Je pense que le problème vient de l'instruction return dans menuNext, lorsqu'il y a un sub menu, qui provoque une interruption de la fonction. Dans ce cas, l'élément suivant (next) n'est pas parcouru...

    Comment parvenir à parcourir complètement mon arbre même si des sub menus sont présents?

  11. #11
    Membre confirmé Avatar de YuGiOhJCJ
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2005
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2005
    Messages : 206
    Par défaut
    Trouvé!
    Il fallait placer une conditionnelle sur un appel récursif
    Seulement si l'appel récursif est fructueux, alors effectuer un return.
    Ca évite ainsi d'interrompre la fonction s'il on doit continuer :

    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
     
    Menu* menuNext(Menu *menu, char* label){
    	fprintf(stderr, "menuNext: start\n");
    	fprintf(stderr, "\tmenuNext: looking for next of label '%s'\n", label);
     
    	Menu * menu_sub;
     
    	/* if it is found */
    	if( (strcmp(menu->label, label) == 0) && (menu->next != NULL)){
    		fprintf(stderr, "\tmenuNext: next found (label='%s')\n", menu->next->label);
    		fprintf(stderr, "menuNext: end\n");
    		return(menu->next);
    	}
    	/* if it has a sub */
    	if(menu->sub != NULL){
    		fprintf(stderr, "\tmenuNext: label '%s' have a sub\n", menu->label);
    		if( (menu_sub = menuNext(menu->sub, label)) != NULL){
    			return(menu_sub);
    		}
    	}
    	/* if it has a next */
    	if(menu->next != NULL){
    		fprintf(stderr, "\tmenuNext: label '%s' have a next\n", menu->label);
    		return(menuNext(menu->next, label));
    	}
    	fprintf(stderr, "\tmenuNext: no next found (label='%s')\n", menu->label);
    	return(NULL);
    }
    Les résultats sont corrects.
    Seul problème, j'utilise comme clé de recherche de l'élément la chaine de caractères label. Or, il peut arriver que label ne soit pas unique dans l'ensemble du menu. Par exemple, 'Back' apparait deux fois dans l'ensemble du menu. Il faut donc que je travail directement sur l'adresse de menu, et non sur le label.

    Voilà résolu donc

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

Discussions similaires

  1. L'accès aux éléments d'une structure de données
    Par Imene MI dans le forum Débuter
    Réponses: 3
    Dernier message: 06/03/2015, 18h17
  2. iterateur accès à l'élément suivant
    Par vbaddict44 dans le forum C++
    Réponses: 10
    Dernier message: 08/06/2012, 18h10
  3. accès aux éléments d'une structure
    Par titou35 dans le forum Débuter
    Réponses: 4
    Dernier message: 05/03/2009, 10h23
  4. Réponses: 6
    Dernier message: 12/09/2007, 16h58
  5. Accès aux éléments d'une structure
    Par licorne dans le forum Pascal
    Réponses: 1
    Dernier message: 15/02/2007, 18h44

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