Pourquoi devrions-nous appeler cin.clear() et cin.ignore() après la lecture de l'entrée?
Code Google Université du tutoriel C++ utilisé pour avoir ce code:
//Description: Illustrate the use of cin to get input
//and how to recover from errors.
#include <iostream>
using namespace std;
int main()
{
int input_var = 0;
//Enter the do while loop and stay there until either
//a non-numeric is entered, or -1 is entered. Note that
//cin will accept any integer, 4, 40, 400, etc.
do {
cout << "Enter a number (-1 = quit): ";
//The following line accepts input from the keyboard into
//variable input_var.
//cin returns false if an input operation fails, that is, if
//something other than an int (the type of input_var) is entered.
if (!(cin >> input_var)) {
cout << "Please enter numbers only." << endl;
cin.clear();
cin.ignore(10000,'\n');
}
if (input_var != -1) {
cout << "You entered " << input_var << endl;
}
}
while (input_var != -1);
cout << "All done." << endl;
return 0;
}
Quelle est la signification de cin.clear()
et cin.ignore()
? Pourquoi les 10000
et \n
paramètres nécessaires?
Vous devez vous connecter pour publier un commentaire.
La
cin.clear()
efface l'indicateur d'erreur surcin
(de sorte que les futures opérations d'e/S fonctionne correctement), puiscin.ignore(10000, '\n')
saute au prochain retour à la ligne, à ignorer tout le reste sur la même ligne que le non-nombre de sorte qu'il ne cause pas un autre analyser l'échec). Il ne sautez jusqu'à 10000 caractères, de sorte que le code est en supposant que l'utilisateur ne sera pas mis dans une très longue ligne non valide.cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
.std::numeric_limits
, assurez-vous de#include <limits>
.std::numeric_limits<std::streamsize>::max()
?numeric_limits
est un modèle de la classe dans laquellemax()
est défini pour lestreamsize
classe de la manière que vous a décrit?Vous entrez dans le
instruction si une erreur se produit lors de la prise de l'entrée de la cin. Si une erreur se produit alors un indicateur d'erreur est défini et les futures tentatives pour obtenir l'entrée sera un échec. C'est pourquoi vous avez besoin de
pour se débarrasser de l'indicateur d'erreur. Aussi, l'entrée qui a échoué seront assis dans ce que je suppose est une sorte de mémoire tampon. Lorsque vous essayez d'obtenir l'entrée à nouveau, il va lire la même entrée dans la mémoire tampon et il échouera de nouveau. C'est pourquoi vous avez besoin de
Il prend 10000 caractères à partir de la mémoire tampon, mais s'arrête lorsqu'il rencontre un caractère de nouvelle ligne (\n). Les 10000 est juste un générique de grande valeur.
Pourquoi utilisons-nous:
1) cin.ignorer
2) cin.claire
?
Simplement:
1) Pour les ignorer (extraction et de jeter) des valeurs que nous ne voulons pas que sur le stream
2) Pour effacer l'état interne de flux. Après l'utilisation de la cin.claire interne de l'état est de nouveau de retour à goodbit, ce qui signifie qu'il n'y a pas "erreurs".
Version longue:
Si quelque chose est mis sur "stream" (cin), alors il doit être pris à partir de là. Par "prise", nous entendons "utilisé", 'supprimé', 'extraits' a partir de flux de données. Flux est un flux. Les données circulant sur cin comme de l'eau sur le ruisseau. Vous ne peut tout simplement pas arrêter l'écoulement de l'eau 😉
Regardez l'exemple:
Ce qui se passe si l'utilisateur répond: "Arkadiusz Wlodarczyk" pour la première question?
Exécutez le programme pour voir par vous-même.
Vous verrez sur console "Arkadiusz" mais le programme ne vous demandons pas de "âge". Il vient de terminer immédiatement à droite après l'impression de "Arkadiusz".
Et "Wlodarczyk" n'est pas affiché. Il semble comme si il avait disparu (?)*
Ce qui s'est passé? 😉
Car il y a un espace entre "Arkadiusz" et "Wlodarczyk".
le caractère"espace" entre le nom et le prénom est un signe pour ordinateur qu'il y a deux variables d'attente pour être extraites sur 'entrée' stream.
L'ordinateur pense que vous liant à envoyer à la saisie de plus d'une variable. Que "l'espace" est un signe pour lui d'interpréter de la sorte.
Donc ordinateur attribue "Arkadiusz" à " nom " (2) et parce que vous mettez plus d'une corde sur un flux de données (input) de l'ordinateur va essayer d'attribuer la valeur "Wlodarczyk" pour la variable "âge" (!). L'utilisateur n'aura pas la possibilité de mettre n'importe quoi sur le 'cin' à la ligne 6, parce que l'instruction a été déjà exécuté(!). Pourquoi? Parce qu'il y avait encore quelque chose à gauche sur le stream. Et comme je l'ai dit plus tôt flux est un flux, donc tout doit être retiré dès que possible. Et la possibilité est venu lorsque l'ordinateur a vu l'instruction cin >> age;
Ordinateur ne sait pas que vous avez créé une variable qui stocke l'âge de quelqu'un (ligne 4). 'l'âge' n'est qu'une étiquette. Pour ordinateur " âge " peut être ainsi appelé: 'afsfasgfsagasggas' et ce serait le même. Pour lui, c'est juste une variable qui il va essayer d'attribuer "Wlodarczyk" parce que vous avez commandé/instructions de l'ordinateur pour le faire en ligne (6).
C'est mal de le faire, mais bon c'est toi qui l'a fait! C'est de ta faute! Eh bien, peut-être de l'utilisateur, mais quand même...
Tout droit tout droit. Mais comment résoudre le problème?!
Nous allons essayer de jouer avec cet exemple un peu avant de nous fixer correctement pour en apprendre un peu plus de choses intéressantes 🙂
Je préfère faire une démarche dans laquelle nous comprendre bien des choses. La fixation de quelque chose sans savoir comment nous avons fait, il ne donne pas satisfaction, vous ne pensez pas? 🙂
Après invoquant le code ci-dessus, vous remarquerez que votre état de flux (cin) est égale à 4 (ligne 7). Ce qui signifie son état interne n'est plus égal à goodbit. Quelque chose qui est foiré. C'est assez évident, n'est-ce pas? Vous avez essayé d'assigner valeur de type chaîne ("Wlodarczyk") de type int variable "âge". Les Types ne correspondent pas. Il est temps de vous informer que quelque chose est faux. Et l'ordinateur est-il en changeant interne de l'état du cours d'eau. C'est comme: "Vous f**** l'homme, corrigez-moi s'il vous plaît. Je vous informe "gentiment"; -)"
Vous ne peut tout simplement pas utiliser 'cin' (stream) plus. Il est coincé. Comme si vous aviez mis de grosses bûches sur le flux de l'eau. Vous devez résoudre avant de pouvoir l'utiliser. De données (de l'eau) ne peuvent pas être obtenus à partir de ce flux(cin) de plus, parce que rondin de bois (état interne) ne vous permettra pas de le faire.
Oh si si il y a un obstacle (bûches) il nous suffit de les enlever à l'aide d'outils qui est fait pour le faire?
Oui!
état interne de la cin est fixé à 4, c'est comme une alarme qui est en hurlant et en faisant du bruit.
cin.clear efface l'état de retour à la normale (goodbit). C'est comme si vous étiez venu et a fait taire l'alarme. Il vous suffit de mettre hors tension. Vous savez que quelque chose s'est passé si vous dites: "C'est OK pour arrêter de faire du bruit, je sais que quelque chose est mal déjà, shut up (clair)".
Tous les droits nous allons le faire! Nous allons utiliser la cin.clear().
Appeler ci-dessous le code à l'aide de "Arkadiusz Wlodarczyk" en tant que première entrée:
Nous pouvons certainement voir, après l'exécution de code ci-dessus que l'état est égal à goodbit.
Grandes, donc le problème est résolu?
Appeler ci-dessous le code à l'aide de "Arkadiusz Wlodarczyk" en tant que première entrée:
Même quand l'état est défini à goodbit après la ligne 9, l'utilisateur n'est pas demandé de "l'âge". Le programme s'arrête.
POURQUOI?!
Oh man... que Vous venez de mettre hors d'alarme, ce sujet de la bûche de bois à l'intérieur de l'eau?* Aller retour au texte où nous avons parlé de "Wlodarczyk" comment il est censé s'en était allé.
Vous devez supprimer "Wlodarczyk" ce morceau de bois à partir de flux de données. Désactivation des alarmes ne résout pas le problème. Vous avez juste disparaisse et vous pensez que le problème a disparu? 😉
Alors il est temps pour un autre outil:
cin.l'ignorer peut être comparé à un camion spécial avec des cordes qui vient et enlève le bois qui a obtenu le flux coincé. Il efface le problème de l'utilisateur de votre programme créé.
Donc, pourrait-on l'utiliser avant même l'alarme se déclenche?
Oui:
La "Wlodarczyk" va être supprimée avant de faire du bruit dans la ligne 7.
Quel est 10000 et '\n'?
Il dit de supprimer 10 000 caractères (au cas où) jusqu'à ce que '\n' est rencontré (ENTRÉE). BTW, Il peut être mieux fait à l'aide de numeric_limits mais il n'est pas le sujet de cette réponse.
Donc la principale cause de problème a disparu avant de bruit a été fait...
Pourquoi avons-nous besoin de "clair" alors?
Ce que si quelqu'un avait demandé "donnez-moi votre âge" question à la ligne 6 par exemple: "vingt ans" au lieu d'écrire 20?
Types ne correspondent pas à nouveau. L'ordinateur tente d'assigner string en int. Et le début de l'alarme. Vous n'avez pas une chance à même de réagir sur la situation comme ça. cin.l'ignorer ne vous aidera pas dans des cas comme ça.
Donc, nous devons utiliser au cas ou comme ça:
Mais si vous êtes claire de l'état "au cas où"?
Bien sûr que non.
Si quelque chose va mal (cin >> age;) l'instruction va vous informer à ce sujet en renvoyant false.
Nous pouvons donc utiliser l'instruction conditionnelle pour vérifier si l'utilisateur de mettre le mauvais type sur le stream
Tout à droite, de sorte que nous pouvons résoudre notre problème initial, comme par exemple:
Bien sûr, cela peut être améliorée, par exemple en faisant ce que vous avez en question à l'aide de la boucle while.
BONUS:
Vous demandez peut-être. Mais si je voulais obtenir le nom et le prénom dans la même ligne de l'utilisateur? Est-il possible, à l'aide de cin si cin interprète chaque valeur séparées par "espace" comme variable différente?
Sûr, vous pouvez le faire de deux façons:
1)
2) ou en utilisant la fonction getline.
et c'est la façon de le faire:
Le deuxième option pourrait se retourner contre vous dans le cas où vous l'utilisez après l'utilisation de 'cin' avant le getline.
De nous renseigner:
a)
Si vous mettez "20" que l'âge ne vous sera pas demandé pour nameAndSurname.
Mais si vous le faites de cette façon:
b)
tout va bien.
QUOI?!
Chaque fois que vous mettez quelque chose sur l'entrée de flux (stream) vous quitter à la fin le caractère blanc qui est ENTRÉE ('\n'), Vous devez en quelque sorte entrer des valeurs de la console. Donc, il doit se produire si les données proviennent de l'utilisateur.
b) cin caractéristiques est qu'il ignore les espaces, de sorte que lorsque vous êtes à la lecture de l'information de cin, le caractère de saut de ligne '\n' n'a pas d'importance. Il est ignorée.
a) getline fonction obtient l'ensemble de la ligne pour le caractère de fin de ligne ('\n'), et lorsque le saut de ligne char est la première chose que la fonction getline obtient '\n', et c'est tout pour l'obtenir. Vous avez extrait le caractère de saut de ligne qui a été laissé sur le stream par l'utilisateur qui a mis "20" sur le courant dans la ligne 3.
Afin de fixer c'est de toujours invoquer la cin.ignore(); chaque fois que vous utilisez cin pour obtenir toute valeur si vous allez jamais à utiliser getline() à l'intérieur de votre programme.
Donc le bon code serait:
J'espère que les flux sont de plus en plus clair pour vous savez.
Hah silence moi s'il vous plaît! 🙂
utilisation
cin.ignore(1000,'\n')
pour effacer tous les caractères de la précédentecin.get()
dans la mémoire tampon, et il choisira de s'arrêter quand il répondre '\n' ou1000 chars
premier.