Question

    

Cette question a déjà une réponse ici:

         

J'apprends le C ++ et j'écris de petits programmes au fur et à mesure. Voici un de ces programmes:

// This program is intended to take any integer and convert to the
// corresponding signed char.

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(true){
    std::cin >> n;
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

Lorsque je lance ce programme et que je garde les entrées à des valeurs absolues relativement petites, il se comporte comme prévu. Mais lorsque j'entre des entrées plus grandes, par exemple, 10000000000, le programme crache de manière répétitive le même résultat. Certaines combinaisons d'entrées provoquent un comportement erratique. Par exemple:

#: ./int2ch
10
10 --> 

10000000000
10 -->

10 -->

10 -->

10 -->

Le programme recrache " 10 - > " jusqu'à ce qu'il soit tué. (Avec cette séquence d'entrées particulière, la sortie du programme change de manière irrégulière.) J'ai aussi remarqué que la sortie de grandes valeurs est déterminée par l'entrée légale précédente ainsi que par la valeur de l'entrée illégale actuelle.

Qu'est-ce qui se passe? (Je me fiche de la correction du programme, c'est facile. Je veux le comprendre.)

Était-ce utile?

La solution

En gros, votre flux cin est en état d'échec et revient donc immédiatement lorsque vous essayez de le lire. Réécrivez votre exemple comme ceci:

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(std::cin >> n){
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

cin > > n renverra une référence à cin , que vous pouvez tester pour "good-ness". dans un conditionnel. Donc, en gros, le " while (std :: cin > > n) " dit "alors que je pouvais toujours lire correctement à partir de l'entrée standard, procédez comme suit"

EDIT: si la dernière valeur correcte entrée est répétée parce que c’est la dernière valeur lue avec succès dans n, les lectures ayant échoué ne changeront pas la valeur de n

EDIT: comme indiqué dans un commentaire, vous pouvez effacer l’état de l’erreur et réessayer quelque chose comme ceci fonctionnerait probablement et ignorerait simplement les mauvais nombres:

#include <iostream>
#include <climits>

int main() {
    signed char sch = 0;
    int n = 0;
    while(true) {
        if(std::cin >> n) {
            sch = n;
            std::cout << n << " --> " << sch << std::endl;
        } else {
            std::cin.clear(); // clear error state
            std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it
        }
    }
}

Autres conseils

Oui, Evan Teran a déjà souligné la plupart des choses. Une chose que je veux ajouter (car je ne peux pas commenter son commentaire pour l'instant :)) est que vous devez passer l'appel à istream :: clear avant l'appel à istream :: ignore. La raison en est que istream :: ignore refuse également de faire quoi que ce soit si le flux est toujours en état d'échec.

Étant donné que vous êtes sur une machine 32 bits, 10000000000 est un nombre trop important pour être représenté par un int. De plus, convertir un int en un caractère ne vous donnera que de 0..255 ou -128..127 selon le compilateur.

Un problème ici est qu'un char a une taille d'un octet et ne peut donc contenir qu'un nombre compris entre -127 et 128. Un int , en revanche. est typiquement 4 octets et peut prendre des valeurs beaucoup plus grandes. Le deuxième problème est que vous entrez une valeur trop grande, même pour un int .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top