A voir également:
- Erreur dans le programme...
- Erreur 0x80070643 - Accueil - Windows
- Programme demarrage windows 10 - Guide
- Erreur 0x80070643 Windows 10 : comment résoudre le problème de la mise à jour KB5001716 - Accueil - Windows
- Cette action ne peut pas être réalisée car le fichier est ouvert dans un autre programme - Guide
- Erreur 1001 outlook - Accueil - Bureautique
3 réponses
Utilisateur anonyme
Modifié par EchoIsON le 9/02/2016 à 18:48
Modifié par EchoIsON le 9/02/2016 à 18:48
Bonsoir.
Pourquoi le type de vos variables est "char" ? Les notes, c'est des nombres non ?
Comment pouvez-vous effectuer des operations entre des caracteres ?
EchoIsON.
Pourquoi le type de vos variables est "char" ? Les notes, c'est des nombres non ?
Comment pouvez-vous effectuer des operations entre des caracteres ?
EchoIsON.
jackdada
Messages postés
77
Date d'inscription
vendredi 31 juillet 2015
Statut
Membre
Dernière intervention
10 février 2016
19
10 févr. 2016 à 01:30
10 févr. 2016 à 01:30
Alors comme cela a été dit, il y a un problème sur le type de tes variable utilisé, enfin oui et non à la fois (je vais m'expliquer).
Il y a différent type de variable, qui te permettent de manipulé des caractère, des entier ou des flottant signé ou non. Je te laisse regarder ici pour plus de détaille https://forums.commentcamarche.net/forum/affich-37622105-langage-c-les-types-de-donnees
Tu souhaite manipuler des nombres, char n'est donc pas le type approprié. Il faut donc utilisé des int ou des float. Ce sont des notes, elles peuvent être à virgule, on partira donc sur des float.
Pour la saisie de tes nombre, tu as choisit d'utiliser fgets sauf que ceci crée des chaines de caractère et non des nombres. Il faut donc après avoir saisie un nombre sous forme de chaine de caractère avec fgets, le transformer en float avec strtof().
Il faut donc maintenant changer tes définition de variable par le type approprié et en rajouté une qui sera la chaine de caractère utilisé pour la saisie.
Après chaque fgets(entree, sizeof(entree), stdin), tu devra rajouter la conversion d'une chaine en un flottant. Vider le buffer après une saisie est également plus propre.
Exemple pour la saisie de NoteUn et CoefUn:
Il faudra aussi que tu enlève les (char) dans le calcule de la moyenne.
Une autre solution est également possible, si tu ne souhaite pas t’embêter avec la conversion de chaine de caractère en flottant.
L'utilisation du bon vieux scanf:
Je te met si après, le code que j'aurais fait pour le calcule de la moyenne en plus optimisé (fait avec des scanf, mais il est facilement transposable avec des fgets):
Il y a différent type de variable, qui te permettent de manipulé des caractère, des entier ou des flottant signé ou non. Je te laisse regarder ici pour plus de détaille https://forums.commentcamarche.net/forum/affich-37622105-langage-c-les-types-de-donnees
Tu souhaite manipuler des nombres, char n'est donc pas le type approprié. Il faut donc utilisé des int ou des float. Ce sont des notes, elles peuvent être à virgule, on partira donc sur des float.
Pour la saisie de tes nombre, tu as choisit d'utiliser fgets sauf que ceci crée des chaines de caractère et non des nombres. Il faut donc après avoir saisie un nombre sous forme de chaine de caractère avec fgets, le transformer en float avec strtof().
char entree[5]; float nombre; fgets(entree, sizeof(entree), stdin); nombre = strtof(entree, NULL);
Il faut donc maintenant changer tes définition de variable par le type approprié et en rajouté une qui sera la chaine de caractère utilisé pour la saisie.
char entree[5]; //Crée un tableau de 5 caractère pour stocker la chaine de caractère d'entrée. float NoteUn, NoteDeux, NoteTrois, NoteQuatre, NoteCinq, NoteSix; //Crée des variables pour les notes float CoeffUn, CoeffDeux, CoeffTrois, CoeffQuatre, CoeffCinq, CoeffSix; //Crée des variables pour les coefficients respectifs de chaque note float Moyenne; //Crée une variable pour la moyenne
Après chaque fgets(entree, sizeof(entree), stdin), tu devra rajouter la conversion d'une chaine en un flottant. Vider le buffer après une saisie est également plus propre.
Exemple pour la saisie de NoteUn et CoefUn:
char c; printf("Entrez la premiere note:"); fgets(entree, sizeof(entree), stdin); while ((c = getchar()) != '\n' && c != EOF) ;//on vide le buffer NoteUn = strtof(entree, NULL); printf("Voici la note saisie: %s", NoteUn); printf("Quel est son coefficient? :"); fgets(entree, sizeof(entree), stdin); while ((c = getchar()) != '\n' && c != EOF) ;//on vide le buffer CoeffUn = strtof(entree, NULL);
Il faudra aussi que tu enlève les (char) dans le calcule de la moyenne.
Une autre solution est également possible, si tu ne souhaite pas t’embêter avec la conversion de chaine de caractère en flottant.
L'utilisation du bon vieux scanf:
float nombre; char c; int r; do { printf("Entrez un nombre\n"); r=scanf("%f", &nombre); while ((c = getchar()) != '\n' && c != EOF) ;//on vide le buffer }while(r!=1); //j'utilise mon scanf dans une boucle afin de la sécurisé. Ainsi si ma saisie n'est pas autorisée (un caractère au lieu d'un chiffre par exemple), alors je boucle et redemande la saisie.
Je te met si après, le code que j'aurais fait pour le calcule de la moyenne en plus optimisé (fait avec des scanf, mais il est facilement transposable avec des fgets):
#include <stdio.h> #include <stdlib.h> int main(){ int i; int r; char c; int nbNote; float sumNote=0; float sumCoeff=0; float moyenne; do{ printf("Nombre de note?\n"); r=scanf("%d", &nbNote); while ((c = getchar()) != '\n' && c != EOF) ; }while(r!=1); float noteTab[nbNote][nbNote]; for(i=0; i<nbNote; i++){ do{ printf("Note %d?\n", i); r=scanf("%f", ¬eTab[i][0]); while ((c = getchar()) != '\n' && c != EOF) ; }while(r!=1); do{ printf("Coeff de la note %d?\n", i); r=scanf("%f", ¬eTab[i][1]); while ((c = getchar()) != '\n' && c != EOF) ; }while(r!=1); printf("La note %d est %.2f de coeff %.2f\n", i, noteTab[i][0], noteTab[i][1]); sumNote+= noteTab[i][0] * noteTab[i][1]; sumCoeff+= noteTab[i][1]; } moyenne = sumNote/sumCoeff; printf("Moyenne: %.2f\n", moyenne); return 0; }
[Dal]
Messages postés
6200
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
7 janvier 2025
1 097
Modifié par [Dal] le 10/02/2016 à 11:39
Modifié par [Dal] le 10/02/2016 à 11:39
Salut jackdada,
Je n'ai pas tout lu, mais à propos de ton dernier code, voilà quelques observations.
pour des nombres décimaux, sauf besoin particulier, utiliser des double est plus cohérent, et ton main devrait avoit un prototype
si on ne fait qu'additionner des notes pondérées avec des coefficients et additionner des coefficients, on calcule au fur et à mesure et le stockage dans un tableau n'est pas nécessaire, car il n'y a pas réutilisation des données.
ton tableau
outre le fait que le stockage n'est pas indispensable, le tableau utilise un espace inutile, puisque tu as juste besoin de 2 colonnes : une pour stocker la note, l'autre pour stocker le coefficient. Il ne faut pas autant de colonnes que de lignes.
les scanf pourraient, pour chaque note, demander la note et le coefficient, séparés par un espace. cela réduirait la redondance du code.
Dal
Je n'ai pas tout lu, mais à propos de ton dernier code, voilà quelques observations.
pour des nombres décimaux, sauf besoin particulier, utiliser des double est plus cohérent, et ton main devrait avoit un prototype
int main(void).
si on ne fait qu'additionner des notes pondérées avec des coefficients et additionner des coefficients, on calcule au fur et à mesure et le stockage dans un tableau n'est pas nécessaire, car il n'y a pas réutilisation des données.
ton tableau
float noteTab[nbNote][nbNote];nécessite C99.
outre le fait que le stockage n'est pas indispensable, le tableau utilise un espace inutile, puisque tu as juste besoin de 2 colonnes : une pour stocker la note, l'autre pour stocker le coefficient. Il ne faut pas autant de colonnes que de lignes.
les scanf pourraient, pour chaque note, demander la note et le coefficient, séparés par un espace. cela réduirait la redondance du code.
Dal
jackdada
Messages postés
77
Date d'inscription
vendredi 31 juillet 2015
Statut
Membre
Dernière intervention
10 février 2016
19
>
[Dal]
Messages postés
6200
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
7 janvier 2025
10 févr. 2016 à 15:45
10 févr. 2016 à 15:45
Le retour de la fameuse question du pourquoi float et pourquoi double. Je n'ai jamais bien saisie la différence entre ces deux type de flottant, hormis le fait que la taille du double est supérieur à celle du float, que lorsque l'on utilise un nombre à virgule dans une opération (3.5+2.6) ce sont en faite des double et qu'un nombre à virgule, 3.5 par exemple est différent s'il est dans un float ou dans un double.
Du fait qu'on manipule des note (qui ne sont donc pas volumineuse), pourquoi partir sur un double plutôt qu'un float. La logique voudrait d'utiliser un float du fait qu'il prend moins de place en mémoire non? Car moins de place en mémoire utilisé impliquerait moins de calcul donc un cout plus faible et une meilleurs optimisation. Pour m'a part ça a toujours été un peut au feeling entre float et double (tout dépend de la taille des donné qui seront utilisé), comme la personne du topic que tu ma passer. Et je ne trouve jamais de réponse précise à ce propos, a part en générale on utilisera un double.
Pour le tableau je suis repartit sur le fait qu'il stockait chaque note, mais vue que je fait le calcule au fur et a mesure avec sumNote et sumCoeff, c'est vrais que c'est inutile. Et pour sa taille je ne sais pas pourquoi je suis partit sur autant de ligne que de colonne sachant que je n'en utilise que 2 (surement la fatigue deriere cette histoire), la taille adéquate serait float noteTab[nbNote][2];
Pour ce qui est du c99, ceci à une importance uniquement pour le compilateur et comment il est configuré. Ce dernier lui signalera en cas de besoins du flag std=c99. Utilisant gcc, il y ai par défaut.
Du fait qu'on manipule des note (qui ne sont donc pas volumineuse), pourquoi partir sur un double plutôt qu'un float. La logique voudrait d'utiliser un float du fait qu'il prend moins de place en mémoire non? Car moins de place en mémoire utilisé impliquerait moins de calcul donc un cout plus faible et une meilleurs optimisation. Pour m'a part ça a toujours été un peut au feeling entre float et double (tout dépend de la taille des donné qui seront utilisé), comme la personne du topic que tu ma passer. Et je ne trouve jamais de réponse précise à ce propos, a part en générale on utilisera un double.
Pour le tableau je suis repartit sur le fait qu'il stockait chaque note, mais vue que je fait le calcule au fur et a mesure avec sumNote et sumCoeff, c'est vrais que c'est inutile. Et pour sa taille je ne sais pas pourquoi je suis partit sur autant de ligne que de colonne sachant que je n'en utilise que 2 (surement la fatigue deriere cette histoire), la taille adéquate serait float noteTab[nbNote][2];
Pour ce qui est du c99, ceci à une importance uniquement pour le compilateur et comment il est configuré. Ce dernier lui signalera en cas de besoins du flag std=c99. Utilisant gcc, il y ai par défaut.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
10 févr. 2016 à 16:00
10 févr. 2016 à 16:00
Le traitement d'un double n'est pas forcément plus long qu'un float. Cela dépend de pas mal de paramètre (compilateur / processeur, ...). Bref, la règle est simple : on utilise toujours double, sauf lorsque la place est critique :-).
Pour le C99, ce que voulait dire [Dal], c'est que l'instruction que tu as donnée n'est pas correcte en C89/90. Il vaut donc mieux plutôt utiliser les malloc... D'autant que pour un exercice scolaire, ça risque d'être considéré comme faux le VLA...
Pour le C99, ce que voulait dire [Dal], c'est que l'instruction que tu as donnée n'est pas correcte en C89/90. Il vaut donc mieux plutôt utiliser les malloc... D'autant que pour un exercice scolaire, ça risque d'être considéré comme faux le VLA...
jackdada
Messages postés
77
Date d'inscription
vendredi 31 juillet 2015
Statut
Membre
Dernière intervention
10 février 2016
19
10 févr. 2016 à 21:22
10 févr. 2016 à 21:22
La norme c99 n'a pas été inventé pour rien, pourquoi ne pas tirer profit des évolution apporté à un langage. J'ai moi même appris en école à utiliser le VLA donc c'est tout à fait correct de le faire sur un exercice scolaire.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
10 févr. 2016 à 23:08
10 févr. 2016 à 23:08
donc c'est tout à fait correct de le faire sur un exercice scolaire.
Sauf que c'est son prof qui choisit ;-). Et vu le niveau de l'exercice, il y a de fortes chances qu'il en soit à son début et qu'il ne connaisse pas encore le VLA. Même pas sûr qu'il connaisse l'allocation dynamique avec malloc()...
En tout cas, sur ce forum, c'est la 1ère fois que j'entends que le VLA est toléré à l'école.
Après, kyky est grand et prendra le risque s'il est joueur.
Sauf que c'est son prof qui choisit ;-). Et vu le niveau de l'exercice, il y a de fortes chances qu'il en soit à son début et qu'il ne connaisse pas encore le VLA. Même pas sûr qu'il connaisse l'allocation dynamique avec malloc()...
En tout cas, sur ce forum, c'est la 1ère fois que j'entends que le VLA est toléré à l'école.
Après, kyky est grand et prendra le risque s'il est joueur.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
10 févr. 2016 à 13:52
10 févr. 2016 à 13:52
Salut jackdata,
Je rajoute quelques par rapport aux remarques de [Dal].
fgets(entree, sizeof(entree), stdin);
while ((c = getchar()) != '\n' && c != EOF) ;//on vide le buffer
c n'est pas un char, mais un int.
Attention, tu ne peux pas vider le buffer comme ça puisque fgets() stocke le '\n' s'il y a la place.
Il faut t'assurer que le buffer clavier contient bien des données...
Je rajoute quelques par rapport aux remarques de [Dal].
fgets(entree, sizeof(entree), stdin);
while ((c = getchar()) != '\n' && c != EOF) ;//on vide le buffer
c n'est pas un char, mais un int.
Attention, tu ne peux pas vider le buffer comme ça puisque fgets() stocke le '\n' s'il y a la place.
Il faut t'assurer que le buffer clavier contient bien des données...
jackdada
Messages postés
77
Date d'inscription
vendredi 31 juillet 2015
Statut
Membre
Dernière intervention
10 février 2016
19
Modifié par jackdada le 10/02/2016 à 15:46
Modifié par jackdada le 10/02/2016 à 15:46
Effectivement, j'ai oublier de prendre ça en compte, le '\n' qui peut être stocker par fgets (n'utilisant jamais fgets, mais uniquement des scanf, j'ai pas l'habitude de faire cette vérification)
Il faut faire appel à cette fonction du coup pour vider le buffer(si besoins) suite au fgets (je l'ai mit dans une fonction cette fois car ça prend quelque ligne):
Donc après le fgets(entree, sizeof(entree), stdin); , il faut faire appel à la fonction par cette ligne clean(entree);
D'ailleurs une petite question pour toi fiddy, que ce produit il quand on utilise directement while ((c = getchar()) != '\n' && c != EOF) ; sans faire la vérification sur le '\n'
Il faut faire appel à cette fonction du coup pour vider le buffer(si besoins) suite au fgets (je l'ai mit dans une fonction cette fois car ça prend quelque ligne):
void clean(char *chaine){ int c; char *p = strchr(chaine, '\n'); if(p) *p = 0; else while ((c = getchar()) != '\n' && c != EOF) ; }
Donc après le fgets(entree, sizeof(entree), stdin); , il faut faire appel à la fonction par cette ligne clean(entree);
D'ailleurs une petite question pour toi fiddy, que ce produit il quand on utilise directement while ((c = getchar()) != '\n' && c != EOF) ; sans faire la vérification sur le '\n'
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
Modifié par fiddy le 10/02/2016 à 15:44
Modifié par fiddy le 10/02/2016 à 15:44
Il manque juste l'accolade et c'est parfait :-). De plus, avant d'appeler cette fonction, il vaudra mieux vérifier que fgets() a renvoyé une valeur non NULL.
Pour répondre à ta question, si tu oublies cette vérification et qu'il n'y a pas de '\n' dans le buffer, cela attendra tout simplement que l'utilisateur saisisse une donnée au clavier (avec validation). Mais sans affichage, l'utilisateur risque de penser que le programme a planté...
Pour répondre à ta question, si tu oublies cette vérification et qu'il n'y a pas de '\n' dans le buffer, cela attendra tout simplement que l'utilisateur saisisse une donnée au clavier (avec validation). Mais sans affichage, l'utilisateur risque de penser que le programme a planté...
jackdada
Messages postés
77
Date d'inscription
vendredi 31 juillet 2015
Statut
Membre
Dernière intervention
10 février 2016
19
>
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
10 févr. 2016 à 15:47
10 févr. 2016 à 15:47
J'ai rajouté l’accolade de fermeture oublié, merci de ta réponse
9 févr. 2016 à 19:26
Pourquoi le type de vos variables est "char" ? Les notes, c'est des nombres non ?
Donc le problème viendrait des types : il faudrait des "unsigned char" par exemple, c'est cela? Ou des "unsigned float", si l'on veut des nombres à virgule?
Comment pouvez-vous effectuer des operations entre des caracteres ?
Pour ceci, je ne sais pas du tout comment faire... Je sais qu'il faut peut-être utiliser des "%s" ou quelque chose comme ceci, mais je n'ai pas vraiment compris comment les utiliser...
Merci de m'avoir répondu si tôt,
Kyky
Modifié par EchoIsON le 9/02/2016 à 23:38
Nous sommes-nous mal compris ?
On veut bien des nombres.
char est une variable pour stocker un caractère, comme 'A', 'B', 'X' etc.
Par exemple :
int est une variable pour stocker un nombre entier (42, 152, 47, 0...)
double est une variable pour stocker un nombre à virgule (42,42; 58,54; 1,0249...)
Le fait d'ajouter unsigned devant une variable de type nombre permet de stocker des nombres positifs ou nuls, non négatifs, c'est tout.
Certes, char permet de stocker certains nombres (très peu), mais cette variable n'est pas faite pour cela, on stocke les nombres dans int, double ou float par exemple.
char sert avant tout à stocker UNE lettre, dont le code ASCII correspond à un nombre (qui vont en l'occurence jusqu'à 127, limite de stockage du type char, coincidence ?).
Et je ne vois pas pourquoi créer des tableaux, vous pouvez faire plus simple.
Ou alors j'ai mal compris ce que vous vouliez faire...
PS : Pour répondre à votre question
Ou des "unsigned float" ?
Oui, ce serait mieux, même qu'avec des char, une moyenne négative n'étant pas possible dans ce cas. De plus, unsigned char va de 0 à 255 et non de -127 à 127.
EchoIsON.
Modifié par jackdada le 10/02/2016 à 01:37
Et je ne vois pas pourquoi créer des tableaux, vous pouvez faire plus simple.
Il crée des tableau car il utilise un fgets et non un scanf pour les saisie, sauf qu'après, il ne convertie pas ces chaines de caractère en des nombres (entier ou flottant) c'est ce qui pose le problème justement lors du calcule de la moyenne. Mais en réalité 1 seul tableau réutilisé pour chaque saisie est nécessaire. Une autre solution est l'utilisation du scanf (à condition de le sécuriser)
10 févr. 2016 à 14:10
Attention aux raccourcis... Un char ne sert pas stocker une lettre, ni un caractère mais un nombre... Souvent on s'en sert pour y stocker la valeur correspondante à un caractère (code ASCII).
On peut donc tout à fait y stocker une note (une note est rarement supérieure à 255 (unsigned)). Mais si on veut un flottant, il faudra plutôt partir sur double.
Techniquement '\n' et '\0' ne sont pas des char mais des int ;-). Même si cela tient bien évidemment dans un char.