Problème de logique [Résolu]

Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
Bonjour,
j'ai un projet de quizz à faire et je dois coder une fonction pour supprimer tous les thèmes et j'ai ça comme prototype. Je vois pas comment je pourrais faire pour faire ça
int supprimerTousLesThemes()
{
    return -1;
}

elle :
o supprime tous les thèmes stockés.
o renvoie le nombre de thèmes qui ont été supprimés.

Configuration: Windows / Chrome 72.0.3626.109
Afficher la suite 

3 réponses

Meilleure réponse
Messages postés
8909
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
12 novembre 2019
449
1
Merci
bonjour, où les thèmes sont-ils stockés?

Dire « Merci » 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CommentCaMarche

CCM 70871 internautes nous ont dit merci ce mois-ci

yg_be
Messages postés
8909
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
12 novembre 2019
449 > Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
pour préparer cette collaboration, tu peux déjà réfléchir à ce que devra faire supprimerTousLesThemes(): quelles seront les différences entre "avant" et "après"?
Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
Avant le table contient soit des thèmes, soit rien (ça ne change rien de toute façon si ?) et après il ne reste plus rien et la fonction doit renvoyer le nombre de thèmes supprimés. Donc, j'dois trouver un moyen de remplacer les thèmes par qqch mais quoi ? Des Null byte ? Et en même temps compter chaque fois que j'en supprime un.
yg_be
Messages postés
8909
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
12 novembre 2019
449 > Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
as-tu envisagé d'utiliser supprimerTheme()?
Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
c'est pas bête ça, j'y avait pas pensé ^^
Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
Et du coup, je peux faire une boucle while qui appel supprimerTheme() et qui incrémente un compteur à chaque itération ainsi je peux renvoyer le cpt pour dire combien de thème j'ai supprimé. Mais je passe quoi comme paramètre à la fonction supprimerTheme() ? Parce que, dans le prototype j'dois passer un identifiant :

// supprime un thème.
// si l'identifiant reçu en paramètre correspond à un thème stocké, celui-ci est supprimé et elle renvoie 1.
// si l'identifiant reçu en paramètre ne correspond à aucun thème stocké, elle renvoie 0.
int supprimerTheme(int identifiant);

Du coup j'dois prévoir dans la fonction supprimerTheme() un cas spécifique pour quand elle sera appelée dans supprimerTousLesTheme() ?
Commenter la réponse de yg_be
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
818
1
Merci
Salut Natsuko410,

Je pense que c'est une fausse piste que d'envisager te servir de
int supprimerTheme(int identifiant);
pour
int supprimerTousLesThemes();
, compte tenu de ta situation, car tu ne sais pas comment lister les identifiants existants, vu que tu n'as pas d'interface définie te permettant d'obtenir cette information, et que tu ne fais pas toi même l'implémentation de la partie du code qui affecte les identifiants à des thèmes ajoutés....

C'est la fonction appelante qui va indiquer à
int supprimerTheme(int identifiant);
l'identifiant à utiliser.

Tu dois faire autrement.

S'agissant du format des identifiants, tu sais qu'il s'agit d'un entier signé et qu'il peut valoir n'importe quelle valeur pouvant être représentée par un
int
au choix de la personne qui implémente cette partie,... toute sauf une.

Et, par élimination, cette valeur est celle qui devrait nécessairement représenter une case "vide" du tableau.

Tu détermines cela en lisant attentivement le commentaire descriptif des entrées et sorties de
int ajouterTheme(struct Theme theme);
et leur signification.

Armé de cette seule information, tu dois être capable de supprimer tous les thèmes, même sans savoir à l'avance quel est l'identifiant qui a pu être octroyé aux différents thèmes stockés.

Dal

Dire « Merci » 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CommentCaMarche

CCM 70871 internautes nous ont dit merci ce mois-ci

[Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
818 -
Tu peux utiliser une seule boucle dans
supprimerTheme()
si tu ne décales pas.

Aussi, si tu décales, tu dois décaler les libellés avec les identifiants qui leur correspondent. Sinon, tu vas corrompre la base. Note qu'en C, tu peux faire des affectations de
struct
directement. C'est à dire que tu peux faire
themes[i] = themes[i+1];
et que le compilateur s'occupera de la copie de tout le contenu.

Mon idée pour utiliser
int supprimerTheme(int identifiant)
dans
SupprimerTousLesThemes()
, est de passer à
supprimerTheme()
tous les identifiants disponibles dans le tableau en énumérant tout son contenu de l'indice
0
à l'indice
NB_THEMES_MAX-1
et d'utiliser la valeur de retour pour décompter ce qui est supprimé dans un compteur. Dans ce cas,
supprimerTheme()
va recevoir des valeurs représentant des emplacements "occupés" et des valeurs représentant des emplacements "vides" (
0
étant déterminé par déduction comme étant l'identifiant des emplacements vides)

Sachant que la valeur de retour :

- vaut 1 si une entrée a été supprimée
- vaut 0 si l'entier qui a été passé comme identifiant n'est pas un identifiant valide pour désigner un emplacement "plein" ou n'est pas trouvé (dans ces deux cas, on est d'accord que rien n'a été supprimé)

    for (int i = 0; i < NB_THEMES_MAX; i++)
        n += supprimerTheme(themes[i].identifiant);

Ce code accumulera dans n (qu'il faudra penser à déclarer et initialiser), le nombre de suppressions, à condition que
supprimerTheme()
retourne 0 dans les deux cas précités.

Si tu fais des décalages, le code ci-dessus en 2 lignes devra être complexifié, car sinon tu vas sauter une case qui ne sera pas vérifiée. Tu te compliques la vie pour rien, à mon sens, en voulant décaler les entrées, mais c'est toi qui vois :-)

Pour supprimer une entrée, il suffit de mettre son identifiant à
0
, c'est tout. Si l'identifiant est à
0
, cet emplacement est marqué comme disponible pour
int ajouterTheme(struct Theme theme);
, qui pourra l'utiliser pour y insérer des données et remplacer le
0
par un identifiant qu'elle déterminera.
Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
Après avoir discuter un peu avec le chef de groupe, et avoir écouté un peu leur logique j'en suis arrivé à avoir ça
int supprimerTheme(int identifiant)
{
    int i;

    if (identifiant>0 && identifiant<=nbThemes)
    {
        for(i=identifiant-1;i<nbThemes-2;i++) strcpy(themes[i].libelle,themes[i+1].libelle);
        nbThemes--;
        return (1);
    }
    else return (0);
}

int supprimerTousLesThemes()
{
    int nbThemesDel;
    nbThemesDel=nbThemes;
    nbThemes=0;
    return (nbThemesDel);
}

Donc, je sais pas si cette manière de fonctionner est aussi performante que celle que tu m'as proposée mais bon...
[Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
818 -
Ah, ben si vous êtes d'accord entre vous, tout va bien :-)

Je t'ai donné des indications, libre à toi de les suivre ou pas.

Ton implémentation de
supprimerTheme()
altère la correspondance entre les identifiants et leurs libellés créée par
ajouterTheme()
. J'ai déjà attiré ton attention sur ce problème et t'ai indiqué des solutions. Si pour vous cela n'est pas un problème, tant mieux.

Ton implémentation de
supprimerTheme()
utilise, d'une façon que je me m'explique pas, l'identifiant comme index du tableau de thèmes. Imagine que
ajouterTheme()
choisisse comme identifiant 4242, tu essaieras donc d'accéder à
themes[4241].libelle
... quelle est la taille maximale de ton tableau ?

Ton implémentation de
supprimerTousLesThemes()
ne supprime aucun thème, mais renvoie quand même un nombre.

Votre préoccupation ne devrait pas être la performance, juste que les fonctions développées fassent ce qu'elles sont sensées faire ;-)
Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
Voilà, après le retour des profs, les fonctions ne sont pas bonnes car elles ne suppriment pas réellement les thèmes donc j'dois tout recommencer
yg_be
Messages postés
8909
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
12 novembre 2019
449 > Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
-
bien sûr, supprimerTousLesThemes() doit appeller supprimerTheme().
Commenter la réponse de [Dal]
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
0
Merci
Du coup, je recommences depuis le début, et je ne suis pas beaucoup plus avancé depuis le retour des profs, voici ce que je dois faire :
 // supprime un thème.
 // si l'identifiant reçu en paramètre correspond à un thème stocké, celui-ci est supprimé et elle renvoie 1.
 // si l'identifiant reçu en paramètre ne correspond à aucun thème stocké, elle renvoie 0.
 int supprimerTheme(int identifiant);

 // supprime tous les thèmes stockés.
 // renvoie le nombre de thèmes qui ont été supprimés.
 int supprimerTousLesThemes();


Voilà les tests que je dois passer :
void test_supprimer_theme1()
{
    int nbEfface = supprimerTheme(theme1.identifiant);
    TEST_ASSERT_EQUAL(1, nbEfface);
    TEST_ASSERT_EQUAL(2, nombreThemes());
}

void test_supprimer_theme4()
{
    int nbEfface = supprimerTheme(4);
    TEST_ASSERT_EQUAL(0, nbEfface);
    TEST_ASSERT_EQUAL(2, nombreThemes());
}

void test_supprimer_theme3()
{
    int nbEfface = supprimerTheme(theme3.identifiant);
    TEST_ASSERT_EQUAL(1, nbEfface);
    TEST_ASSERT_EQUAL(1, nombreThemes());
}

void test_supprimer_theme2()
{
    int nbEfface = supprimerTheme(theme2.identifiant);
    TEST_ASSERT_EQUAL(1, nbEfface);
    TEST_ASSERT_EQUAL(0, nombreThemes());
}

void test_supprimer_tous_les_themes()
{
    ajouterTheme(theme1);
    ajouterTheme(theme2);
    ajouterTheme(theme3);
    TEST_ASSERT_EQUAL(3, nombreThemes());
    int nbThemesSupprimes = supprimerTousLesThemes();
    TEST_ASSERT_EQUAL(3, nbThemesSupprimes);
    TEST_ASSERT_EQUAL(0, nombreThemes());
}


Et voici mon code :
int supprimerTheme(int identifiant)
{
    char vide='\0';
    int i=0;
    if ((identifiant>0) && (identifiant<nbThemes))
    {
        i=identifiant-1;
        if (themes[i].identifiant==identifiant)
        {
            for(i;i<nbThemes-2;i++)
            {
                themes[i].identifiant=themes[i+1].identifiant;
                strcpy(themes[i].libelle,themes[i+1].libelle);
            }
        themes[nbThemes-1].identifiant=0;
        strcpy(themes[nbThemes-1].libelle,vide);
        nbThemes--;
        return (1);
    }
    else return(0);
}

int supprimerTousLesThemes()
{
    int nbThemesDel=0;
    char vide='\0';
    themes[nbThemes-1].identifiant=0;
    strcpy(themes[nbThemes-1].libelle,vide);
    for(i=nbThemes-2;i>=0;i--)
    {
        themes[i].identifiant=themes[i+1].identifiant;
        strcpy(themes[i].libelle,themes[i+1].libelle);
        nbThemesDel++;
    }
    nbThemes=0;
    return (nbThemesDel);
}

Et voilà les erreurs que j'ai :


Donc, voilà j'ai modifié plusieurs fois mon code sans succès, je sais pas quoi faire...
Natsuko410
Messages postés
32
Date d'inscription
samedi 23 février 2019
Statut
Membre
Dernière intervention
11 mai 2019
> [Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
-
j'ai eu une réponse et le chef a répondu mot pour mot " La fonction rajoute un identifiant au theme reçu en paramètres "
[Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
818 -
Pour tester supprimerTheme() il te faudra, en plus du nombre de thèmes requis par tes tests, pour avoir la possibilité de faire
int nbEfface = supprimerTheme(theme1.identifiant);
, simuler un
struct Theme
dénommé theme1 existant dont tu puisses utiliser l'identifiant, par exemple comme cela :

struct Theme theme1 = { .identifiant = 42 };

etc.

le seul test que je ne comprends pas bien est
void test_supprimer_theme4()
, car il teste ceci :

    int nbEfface = supprimerTheme(4);
    TEST_ASSERT_EQUAL(0, nbEfface);

ce qui suppose que 4 ne soit pas un identifiant existant dans le contexte testé ... cela ne dérive pas de la spec,... à moins que les tests soient eux-même partie de la spec, auquel cas ajouterTheme() aurait l'interdiction d'affecter un identifiant valant 4 (en plus d'un identifiant valant 0, qui signifie un emplacement vide)...

j'avoue que je suis un peu perplexe sur la signification de ce test là ... mais peut-être me manque-t-il des informations ...
yg_be
Messages postés
8909
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
12 novembre 2019
449 > [Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
-
je crois deviner que les tests partagés font partie d'une suite de tests plus larges, dont les premiers testent d'autres fonctions.
[Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
818 -
j'ai eu une réponse et le chef a répondu mot pour mot " La fonction rajoute un identifiant au theme reçu en paramètres "

oui, mais elle n'ajoute pas un thème à la table, alors que cela est exigé par la spécification :

// ajoute un theme.
// cette fonction doit affecter un identifiant au thème reçu en paramètre.
// elle renvoie l'identifiant affecté au thème.
// si table est pleine, elle renvoie 0.
[Dal]
Messages postés
5278
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 novembre 2019
818 -
Si tu veux avancer dans ton propre travail, je te suggère fortement de créer tes propres jeux de tests, selon la méthode illustrée dans mes posts ci-dessus #44 et #46.
Commenter la réponse de Natsuko410