12
votes

cin.eof () fonctionnalité

Je comprends que cin.eof () code> teste le format de flux. Et tout en donnant une entrée, la fin du caractère em> n'est pas atteint lorsqu'il est faux dans l'entrée. J'ai testé cela sur mon MSV C ++ 2010 Strong> et je ne comprends pas les résultats étranges. Peu importe ce que je donne la saisie, je reçois un message Erreur de format Strong> présent dans le programme.

#include <iostream>
using namespace std;

int main()
{
    int i;
    cin>> i;

    if(!cin.eof())
    {
        cout<< "\n Format Error \n";
    }
    else
    {
        cout<< "\n Correct Input \n";
    }

    getchar();
    return 0;
}


8 Réponses :


20
votes

std :: cin.eof () tests pour fin de fichier (donc eof), pas pour les erreurs. Pour la vérification des erreurs, utilisez ! Std :: cin.good () , l'opérateur de conversion intégré ( if (STD :: CIN) ) ou l'opérateur de négation booléen (< Code> Si (! STD :: CIN) ).


9 commentaires

Pour l'entrée 12a à un int , je reçois le message Entrée correcte lorsqu'il est utilisé ! Std :: cin.good ()


@MAHESCH: Oui, c'est parce que cela lit le "12" à partir de l'entrée et laisse le "A" dans la mémoire tampon d'entrée pour les autres opérations d'entrée pour les autres opérations de saisie.


Alors, comment restreindre l'utilisateur à saisir le type correct? Toute fonction prédéfinie? Et dans ce cas ! Std :: cin.good () ne servait pas mon but.


N'utilisez pas bon (), cela peut échouer exactement de la même manière EOF ()! Utilisez le flux lui-même (si (s), si (! S)) ou la méthode d'échec (les trois sont équivalents, sauf "si (s)" "est inversé).


@Fred: bon n'a pas échoué dans la manière dont eof fait. EOF sera défini à la fin du flux. bon sera faux chaque fois que toute opération se produit lorsque l'opérateur d'extraction de flux n'a pas pu être terminé. opérateur! , opérateur vide * , négativement bon () ou test échoue () fonctionnera tous correctement ici.


@Billyonéal: bon sera faux chaque fois que Eofbit est défini, même si l'extraction a été complétée avec succès. Le test bien () est pas la même chose que les tests! Échouer ().


@Billyonéal: qui ne va pas. extraction peut compléter avec succès et définir eofbit.


@Fred il peut, mais n'est pas garanti à même lorsque le fichier se termine au bon endroit. Voir parasht.com/c++-faq-lite/input -Output.html # FAQ-15.5 . La bonne façon de tester consiste à utiliser les opérations de lecture réelles, comme dans (par exemple, la réponse de Wilx.


@Karlknechtel: C'est pourquoi mon premier commentaire ici dit de ne pas utiliser bon () ou EOF (), mais dit-il à tester le flux lui-même après tentative d'extraction (car c'est le contexte ici). C'est exactement ce que je fais dans ma réponse et aussi ce que la réponse ultérieure de Wilx fait; Avez-vous manqué ce premier commentaire?



1
votes

Ajout à la réponse précédente: Après avoir lu votre entrée (comme 10), vous n'êtes pas à la fin de fichier, car vous pouvez facilement en taper plus. Comment le système est-il de savoir que vous n'aurez pas?

Lorsque vous lisez votre deuxième entrée (12A), il lit correctement tous les chiffres pouvant faire partie d'un entier. La lettre 'A' ne peut donc pas, il est donc laissé pour une contribution ultérieure possible. Par exemple, vous pouvez lire toutes les parties de 12a avec ce code

int i; char c;

CIN >> I >> C;


0 commentaires

2
votes
$ your-program
12  # input
Extracted an int, but it is unknown if more input exists.
More input exists.
But this was at the end of this line.

$ your-program
12a  # input
Extracted an int, but it is unknown if more input exists.
More input exists.

$ echo -n 12 | your-program
Extracted an int, but it is unknown if more input exists.
No more input exists.

$ your-program
a  # input
Format error.

15 commentaires

D'accord avec Downvoter: vous devez d'abord tester votre code. Il y a toujours au moins une nouvelle ligne de fin à consommer.


@Unclebens: Si vous voulez ignorer WhitSpace, utilisez CIN >> C, comme je l'ai dit. Mais il n'y a pas toujours une nouvelle ligne de fin: echo -n 12 | votre programme


@Unclebens: alors que la réponse manque d'explication de ce qui se passe, je ne peux pas vraiment être d'accord avec cette déclaration. Compilez ceci dans une boîte Linux / OSX et exécutez $ echo -n 10 | ./Test_app . Vous pouvez probablement obtenir la même chose dans un terminal Windows (ou en tuyau dans un fichier via le programme). Il y a pas toujours une nouvelle ligne de fuite à consommer.


Il n'est pas rare d'utiliser des strestreams ou des iostreams attachés à d'autres périphériques (tels que le réseau), mais ECHO -N est le moyen le plus clair de le montrer.


@David: L'explication de ce qui se passe est dans la sortie envoyée à Cout.


Donc, vous voulez dire que la production devrait être redirigée vers STDIN pour que cela fonctionne? Mais dans ce cas, le code de l'OP ne fonctionnerait-il pas déjà? - Je ne vois pas comment cela fonctionnerait si je tape la valeur lorsque le programme le demande.


@Unclebens: Non, cela n'aurait pas besoin. Vous pouvez signaler EOF dans un terminal lors de la frappe de manière interactive. Le code de l'OP échoue avec une entrée de "A \ N", que ce soit soit redirigé ou non, et si cette nouvelle ligne est présente ou non.


Vous dites que le seul "format correct" serait 12 [EOF]? C'est exactement ce que OP teste déjà.


@Unclebens: Non. Seule l'OP sait ce que signifie "format correct", j'aurais dû modifier ma sortie pour dire "extraire un INT fonctionnant" plutôt que de copier cette chaîne de l'OP. Pour le point "correct" pourrait signifier ou mais exclure , et ainsi de suite.


@Unclebens: Mise à jour de la question afin que vous puissiez voir comment cela fonctionne si vous tapez des valeurs car le programme leur demande.


C'est beaucoup mieux maintenant. Cependant, pendant que nous sommes de nitpicking: pourquoi accepte-t-il [espace] 12 comme entrée mais pas 12 [espace] ? :)


@Unclebens: Comment ça va beaucoup mieux? Il est inchangé, sauf pour ajouter un léger modification qui fournit plus d'informations.


@Unclebens: ce code n'accepte aucune entrée (et c'est pourquoi j'ai changé "correct" sur "extrait"); Il rejette (certaines?) Entrée non valide et montre comment déterminer diverses conditions qui affectent si un cas particulier d'extraction d'une intégration doit être accepté ou non.


La version précédente du code vous a toujours dit qu'il y avait plus d'informations à lire, à moins que le numéro soit suivi de l'EOF, qui est à peu près des informations inutiles.


@Unclebens: N'avez-vous pas fait que l'OP n'a pas fourni suffisamment d'informations pour décider de ce qui est et n'est pas correct? Comment savons-nous ce qui est inutile et ce qui n'est pas sans savoir le premier?



2
votes

En supposant que votre entrée est basée sur la ligne, je vous suggère de lire toute la ligne en utilisant std :: getline () code>. Une fois que vous avez la ligne, vous pouvez l'analyser et décider s'il contient une entrée correcte ou incorrecte. Mettre la ligne dans std :: istringingstream code> et faire quelque chose comme ce qui suit:

edit: strong> modifié !! ISS code> à static_cast (ISS) code> pour la compatibilité avec C ++ 0x. P>

std::istringstream iss (line);
char ch;
long lval;
// read the input
iss >> lval;
// result variable will contain true if the input was correct and false otherwise
result
    // check that we have read a number of at least one digit length
    = static_cast<bool>(iss)
    // check that we cannot read anything beyond the value read above
    && ! (iss >> ch);


12 commentaires

+1 Pour une façon appropriée et robuste de faire ce que le PO veut effectivement faire.


Je suis désolé, mais je ne peux rien uplifier quoi que ce soit qui utilise !! . C'est ce que ! = 0 est pour.


@Billyonéal: la comparaison d'un flux à 0 n'a aucun sens. Je n'aime pas aussi !!, mais! = 0 serait pire. @WILX: BOOL (ISS).


@Fred: le problème avec la coulée à BOOL est-ce que cela lancera des avertissements sur plusieurs compilateurs. Si vous n'aimez pas ! = 0 , utilisez ensuite échec () explicitement. N'utilisez pas !! .


La description ", vérifie que nous ne pouvons rien lire au-delà de la valeur lue ci-dessus", ne correspond pas au code, car le code ne parvient pas à distinguer entre la ligne étant "12" (ONR ou plus) et exactement "12".


@Billyonéal: De plus,! = 0 échouera sur 0x, car la conversion de Bool est explicite là-bas (et la conversion de Void * est supprimée).


@Fred: Utilisez ensuite échoue explicitement. !! devrait jamais être utilisé.


@Billyonéal: ai-je dit d'utiliser !!? Vous m'avez dit deux fois de ne pas l'utiliser et je ne sais pas pourquoi.


@Fred: Désolé - me suis un peu confus. Cherchait une question à ce sujet et ne paie pas vraiment autant d'attention que je devrais avoir.


@Tall: J'aime ça parce que c'est court et à mes yeux évidents. Mais je pensais ne pas l'utiliser pour l'exemple ici exactement parce que certaines personnes ne l'aiment pas. :)


@Fred Nurk: Je pense que cet espace blanc supplémentaire ne devrait pas être un problème dans la plupart des cas. De toute évidence, je ne peux pas vraiment lire les pensées de l'OPS, mais quelle utilisation est-elle de lire exactement un numéro de l'entrée?


@WILX: Je ne sais pas si c'est un problème non plus, mais je connais les commentaires et le code en désaccord.



1
votes

Cin.eof () code> Test Si le flux a atteint la fin du fichier qui se produit si vous tapez quelque chose comme CTRL + C (sous Windows) ou si une entrée a été redirigée vers un fichier, etc.

Testez si l'entrée contient un entier et rien qu'un entier, vous pouvez entrer d'abord l'entrée dans une chaîne, puis convertir cela avec un stringtream. Un StringStream atteint en effet EOF s'il n'ya plus d'extraire de celui-ci. P>

#include <iostream>
#include <sstream>
#include <string>

int main() {
    using namespace std;
    int i;
    string input;
    cin >> input; //or getline(cin, input)
    stringstream ss(input);
    if (ss >> i && ss.eof()) {  //if conversion succeeds and there's no more to get
        cout<< "\n Correct Input \n";
    }
    else {
        cout<< "\n Format Error \n";
    }

  return 0;
}


0 commentaires

-1
votes

EOF signifie e ND o f f ile. STD :: CIN est l'entrée standard. L'entrée standard, dans des circonstances normales, n'atteint jamais la fin: vous pouvez toujours simplement taper plus.

En outre, .eof () ne renvoie que TRUE si une opération d'entrée a déjà échoué en raison de la lutte contre la fin du fichier . Le programme ne peut pas dire que c'est "à la fin du fichier"; C'est-à-dire que la seule façon de savoir que la prochaine tentative de lecture de données échouera en faisant la tentative.


3 commentaires

Fermer, mais faux: EOF () est liée à la lecture de la fin du fichier, mais de ne pas avoir échoué à une opération d'entrée. (Je l'ai déjà expliqué cela à Billy dans commentaires , donc je vais le pointer plutôt que Allez-y à nouveau ici.) Ainsi, si! échouez () mais EOF (), vous savez que vous êtes chez EOF sans lire à nouveau. (Même si,! Échoue () et! EOF () ne vous dis pas si la prochaine lecture échouera à cause de la FEO, qui correspond à votre réponse.)


@Fred Veuillez expliquer comment une opération de lecture de fichier peut lire après la fin du fichier, mais réussir.


Je lie à un exemple sur CodePad.org qui fait exactement que dans les commentaires liés à mon commentaire ci-dessus. Puisque vous dites spécifiquement "Opération de lecture de fichiers", voici un autre exemple: GetLine de la dernière ligne d'un fichier où la ligne manque sa ligne de terminaison.



4
votes

Pour un flux d'entrée Pour entrer dans l'état EOF, vous devez essayer de tenter de lire après la fin du flux . C'est à dire. Il ne suffit pas d'atteindre l'emplacement de fin de flux dans le flux, il est nécessaire d'essayer de lire un personnage passé à la fin. Cette tentative entraînera l'activation de l'état EOF, ce qui fera à son tour que cin.eof () retourne vrai.

Cependant, dans votre cas, vous ne le faites pas seulement, vous ne pouvez même pas atteindre la fin du flux. Si vous entrez votre 10 dans le clavier, vous avez probablement terminé l'entrée en appuyant sur la touche [ENTER]. Cela a abouti à un nouveau caractère de ligne ajouté au flux d'entrée. Donc, ce que vous analysez réellement avec >> dans ce cas est en réalité une séquence 10 \ n . Depuis que vous avez demandé une valeur int à partir du flux, il ne lit que les caractères numériques du flux, c'est-à-dire qu'il lit 1 et 0 , mais il arrête à \ n . Que \ n reste dans le flux. Vous ne le lisez jamais. Donc, évidemment, votre code n'atteint jamais la position de fin de fichier dans le flux. Vous devez vous attendre à vous attendre à cin.eof () pour devenir vrai dans ce cas.


0 commentaires

13
votes

Utilisez un test direct de l'état du flux avec: xxx


2 commentaires

Bienvenue dans le débordement de pile. Votre question a été marquée comme une «qualité médiocre» en raison de sa brièveté extrême. Bien que précis, il est judicieux de fournir une explication de la raison pour laquelle votre réponse est correcte, en particulier lorsque la question a été posée il y a longtemps (il y a environ un an) et il y a plusieurs réponses. Notez également l'icône {} au-dessus de la zone d'édition; qui peut être utilisé pour indenter les extraits de code.


@Jonathanleffler merci pour le conseil. Prendra soin de cela des réponses futures.