Problème "char" en C++

Fermé
ikki - Modifié le 4 juil. 2017 à 14:58
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 31 juil. 2017 à 10:32
Bonjour,

voici un programme que j'ai tapé sur Eclipse :
#include <stdio.h>   // printf et scanf
#include <conio.h>   // getch
#include <stdlib.h>  // system cls

// programme principal
int main () {
 
 // Ne pas oublier d'attribuer les valeur des variables
 int note, cumul = 0, nb = 0;
1) char rep=O;
 
 // On boucle tant que la réponse est oui
 while (rep=O) {
  printf ("Entrer une note = ");
  scanf ("%d", ¬e);
  cumul += note;
  nb++;
  printf ("Voulez vous continuer ? (O/N)");
  scanf ("%c",&rep); // On utilise %c pour les caracteres
  
 }
2) printf ("cumul/nb");
 
 getch ();
 return 0;
}


EDIT : Ajout des balises de code (la coloration syntaxique).

Explications disponibles ici :ICI

Merci d'y penser dans tes prochains messages.
Jordane45


C'est un programme simple mais j'ai deux soucis:
En 1) Eclipse me signal une erreur le disant que "O" n'est pas déclarer dans le scope.
et en 2) je n'arrive pas à afficher le résultat de cumul/nb.

Merci beaucoup de toute aide que vous pouvez me rapporter.

12 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
13 juil. 2017 à 10:30
Bonjour,

Plusieurs remarques :
- pas de
#include <conio.h>
ce n'est pas portable, et pas utile dans ton cas
- pour rep, le plus simple est de faire un
do { ... } while(...)

- pour la saisie et l'affichage, le c++ permet de s'en sortir facilement avec les flux (
std::cin
et
<<
pour la saisie ;
std::cout
et
>>
pour l'affichage)
- attention au moment de faire le calcul de la moyenne : le c++ choisira le type de l'opérande gauche, donc un int / int donne un int, il faut donc comme indiqué par Dalfab penser à multiplier par 1.0 à gauche ou mieux, à caster le numérateur.

L'erreur :
" 'rep' is not declared in the scope'" 
signifie que
rep
n'est pas déclaré.
- On appelle scope (horizon) une paire d'accolade. On appelle cela comme ça car cela détermine la portée d'une variable (sa portée correspond à la paire d'accolade qui la contient qui est la plus imbriquée).
- Toute variable en C/C++ doit être préalablement déclarée. Note que les variables des types de bases (non objet) ne sont pas initialisée à une valeur par défaut. Donc déclarer un int ne l'initialise pas à 0 dans le cas général.

Il n'est pas très clair si une note doit être un entier positif (
unsigned int
, ou
unsigned
en abrégé) ou un nombre décimal (donc un
float
ou un
double
). On peut donc définir un type intermédiaire
note_t
qui va permettre de ne faire cette considération qu'à un seul endroit du code.

Voici une implémentation fonctionnelle qui tient compte de toutes ces remarques :

#include <iostream> // std::cin, std::cout, std::endl

int main() {
    typedef unsigned note_t;
    note_t cumul = 0;
    unsigned nb = 0;
    char rep;

    do {
        note_t note; 
        std::cout << "Entrer une note:" << std::endl;
        std::cin >> note;
        cumul += note;
        nb++;
        std::cout << "Voulez-vous continuer? (o/n)" << std::endl;
        std::cin >> rep;
    } while (rep == 'o');

    std::cout << "Résultat : " << double(cumul) / nb << std::endl;
    return 0;
}


Résultat :

Entrer une note:
10
Voulez-vous continuer? (o/n)
o
Entrer une note:
20
Voulez-vous continuer? (o/n)
n
Résultat : 15


Bonne chance
2
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101
3 juil. 2017 à 08:48
Bonjour,

Un char littéral se définit en mettant le caractère entre des apostrophes. Il faut faire 'O' plutôt que O.*
Un test d'égalité se fait avec un double égal, donc
 while (rep=='O')
.
Pour le printf, on peut indiquer un message entre guillemets, mais il faut aussi indiquer que le veut un nombre, donc ici
printf( "cumul/nb = %f" , (double)cumul/nb );
.
Il doit y avoir d'autres erreurs
0
Merci de votre réponse

Alors j'ai appliqué la correction proposé. A la ligne du while ça m'affiche un message d'erreur me disant : " 'rep' is not declared in the scope'"
Je ne sais vraiment pas ce que ça signifie
0
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101
4 juil. 2017 à 08:33
Cela signifie que la variable rep est utilisé et n'a jamais été déclarée. Il faut déclarer la variable rep.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Est ce qu'il faut déclarer la variable dans les parenthèse du "int main" ? Si oui comment ? A mes connaissances le "int" concerne les variable numérique entier mais pas les littérale comme "char".
0
Rebonjour,

Je reviens vers vous pour vous dire que je n'y arrive absolument pas. J'ai même en vain éssayer de déclarer une procédure.
Voici l'algorithme :

programme moyenne
note, cumul, nb : numérique
rep : caractere

début
cumul <--- 0
nb <--- 0
rep <--- "O"
tantque rep = "O"
afficher "entrer une note = "
saisir note
cumule <--- cumul + note
nb <--- nb + 1
afficher "Voulez vous continuer ? (O/N) "
saisir rep
fintantque
afficher cumul/nb
fin

Je bug toujours pour afficher et saisir la réponse en caractere.
Merci d'avance
0
Bonjour,

merci pour votre réponse de qualité. En faite, je ne suis pas arrivé au "std" dans le programme du BTS.

Je prends bien note de la leçon apporté, mais pour l'instant je dois me débrouillér avec "printf" et "scanf". Par contre, on a vu la déclaration de procédure et de fonction, je ne sais pas si c'est utile pour ce programme.

J'ai corrigé le programme en utilisant un " do...while".
Ça me fait la même chose. Je peux rentrer qu'une seule note et quand je saisie la reponse, que ce soit O ou N la console s'éteint. Je n'arrive pas à trouver la source du problème.
0
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101
16 juil. 2017 à 13:27
Attention, ton titre parle de C++ et tu es sur le forum C++ alors que ton code est du C. Il faut commencer par indiquer clairement le langage utilisé. Par exemple le namespace std n'existe pas en C.

Ensuite fournis ton code avec ta question dans le bon forum. Le dernier code posté ne compile pas et donc ne s'exécute pas. On ne peut pas plus t'aider avec cela.
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 18 juil. 2017 à 09:42
Je prends bien note de la leçon apporté, mais pour l'instant je dois me débrouillér avec "printf" et "scanf". Par contre, on a vu la déclaration de procédure et de fonction, je ne sais pas si c'est utile pour ce programme.

Pas de problème, même si c'est plus dans l'esprit du C, comme l'indique Dalfab, que dans celui du C++. Ceci dit tout ce que tu peux écrire en C, tu peux l'écrire en C++.

J'ai corrigé le programme en utilisant un " do...while".
Ça me fait la même chose. Je peux rentrer qu'une seule note et quand je saisie la reponse, que ce soit O ou N la console s'éteint. Je n'arrive pas à trouver la source du problème.


C'est probablement tes scanf qui sont incorrects. Sans voir le code difficile d'être catégorique mais le code que je t'ai fourni fait a priori ce qu'il faut.

Malheureusement scanf fait partie des fonctions assez pénible à utiliser correctement. En particulier ici il ne faut pas oublier l'espace devant le "%c" :
https://stackoverflow.com/questions/20164885/scanf-char-variable-in-between-scanf-integer-variable-doesnt-work

#include <cstdio>

int main() {
    typedef int note_t;
    note_t cumul = 0;
    unsigned nb = 0;
    char rep;

    do {
        note_t note;
        printf("Entrer une note:\n");
        scanf(" %d", ¬e);
        cumul += note;
        nb++;
        printf("Voulez-vous continuer? (o/n)\n");
        scanf(" %c", &rep);
    } while (rep == 'o');

    printf("Résultat : %lf", double(cumul) / nb); 
    return 0;
}


En toute rigueur il faudrait également contrôler la valeur de retour de
scanf
pour vérifier que la valeur a été effectivement correctement lue, et au besoin la redemander. Je ne sais pas si c'est attendu dans ton exercice. Malheureusement la solution "naturelle" qui consiste à écrire quelque chose du genre :

        do {
            printf("Entrer une note:\n");
        } while (scanf(" %d", &rep) != 1);


... ne se comportera pas comme il faut si tu ne saisis pas une valeur numérique, et ce même avec
fflush
... En plus
printf
et
scanf
te forcent à connaître les bonnes chaînes de formatage et qui ne sont pas intuitive si tu veux être rigoureux.

Pour toutes ces raisons je n'utilise pas à titre personnel jamais de
scanf
. Des fonctions alternatives comme
getc
ou
gets
en C peuvent aider quitte à ensuite passer par une fonction du genre
strtol
. Bref c'est très laborieux pour un truc qui devrait être très simple. En C++ je préconise évidemment l'utilisation de
std::cin
et
>>
.

Ceci dit si tu trouves comment arranger la boucle
do ... while(scanf(...))
que je mentionnais, ça m'intéresse.

Bonne chance
0
Bonjour,

Je vous tiens donc au courant de mon avancée. Après plusieurs bidouillage en suivant vos précieux conseils, j'ai enfin trouvé !

Tout simplement il faut laisser un espace juste avant le %c du scanf, ce qui n'est pas précisé dans mon cours !
Voici mon programme corrigé:

#include <stdio.h>   // printf et scanf
#include <conio.h>   // getch
#include <stdlib.h>  // system cls

// programme principal
int main () {
 
 // Ne pas oublier d'attribuer les valeur des variables
 int note, cumul = 0, nb = 0 ;
 char rep='O';  // mettre un seul "=" 
 
 // On boucle tant que la réponse est oui
 do {
  printf ("Entrer une note = ");
  scanf ("%d", ¬e);
  cumul += note;
  nb++;
  printf ("Voulez vous continuer ? (O/N)");
  scanf (" %c",&rep); // On utilise %c pour les caracteres
 }while (rep=='O');
 
 printf ("Moyenne = %f",(double)cumul/nb); 
 
 getch ();
 return 0;
}


Merci pour toutes vos infos utiles à la programmation. Mon cours est bien du C++ mais vu que je débute on dois passer peut être par le C et je n'ai toujours pas vu de "getc" ou de "std".
Je bug dans plein de programme donc je posterai aussi des topics concernant mes blocages.

Cordialement
0
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101
30 juil. 2017 à 10:17
Ceci n'est pas du C++, c'est bien du C. C'est dangereux d'utiliser les structures du C en C++, ça demande d'être expert dans les 2 langages, car le C est bourré de choses interdites en C++ et inversement! Or justement, il s'agit d'un cours; je pense que celui qui donne ce cours à bien besoin d'un cours!

Alors, pourquoi faut-il une espace préliminaire dans le format du
scanf()
? Il s'agit ici d'une "astuce". L'espace permet d'indiquer que tous les caractères de séparation dans le flux doivent être extraits. Ici le
scanf()
précédent attendait un nombre, la saisie effectuée était un nombre suivi comme toujours d'un retour chariot, quand on arrive au
scanf(" %c",...)
le nombre a été extrait, mais le retour chariot n'a pas été lu. L'espace va extraire ce retour chariot puis attendre la suite. Une fois tapé un caractère suivi de retour chariot, le caractère sera lu et il restera un nouveau retour chariot non lu.
Astuce un "plus propre" : ajouter l'espace après le
"%d "
plutôt qu'avant le
" %c"
.
En C++, ce problème existe aussi mais il a une autre forme. Il faut voir dans un cours C++ comment le gérer.
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
31 juil. 2017 à 10:32
@Dalfab : car le C est bourré de choses interdites en C++ et inversement! ...

Juste par curiosité, à quoi fais-tu allusion ?

@ikki : Tout simplement il faut laisser un espace juste avant le %c du scanf, ce qui n'est pas précisé dans mon cours !

Pour l'histoire de l'espace devant le "%c", je t'invite à bien prendre le temps de lire les réponses qu'on te donne afin que tu gagnes du temps.

Ensuite pour gérer proprement tout ça le plus simple/propre/c++ est d'utiliser les flux std::cin std::cout comme suggéré dans ce message mais c'est important d'avoir essayé au moins une fois dans sa vie
scanf
, car la première fonction avec passage de paramètre par pointeur qu'on découvre. De plus
scanf
permet de vérifier si dans une ligne vérifie un "motif" (en testant sa valeur de retour) chose que ne permettent pas les flux. Ceci dit, pour cela aussi il utilise un outil c++ plus évolué (
std::regexp
).

Bref garde à l'esprit comme dit Dalfab que cette manière de faire est plus du C dans l'esprit que du C++, mais elle reste néanmoins instructive ;-)
0