web-dev-qa-db-fra.com

c ++ getline () n'attend pas l'entrée de la console lorsqu'il est appelé plusieurs fois

J'essaie d'obtenir quelques paramètres utilisateur de la console, deux chaînes, deux ints et un double. Le code que j'essaie d'utiliser est le suivant:

#include <string>
#include <iostream>
using namespace std;

// ...

string inputString;
unsigned int inputUInt;
double inputDouble;

// ...

cout << "Title: "; 
getline(cin, inputString);
tempDVD.setTitle(inputString);

cout << "Category: "; 
getline(cin, inputString);
tempDVD.setCategory(inputString);

cout << "Duration (minutes): "; 
cin >> inputUInt; 
tempDVD.setDuration(inputUInt);

cout << "Year: "; 
cin >> inputUInt; 
tempDVD.setYear(inputUInt);

cout << "Price: $"; 
cin >> inputDouble; 
tempDVD.setPrice(inputDouble);

Cependant, lors de l'exécution du programme, au lieu d'attendre la première entrée inputString, le code ne s'arrête pas avant le deuxième appel à getline (). Ainsi, la sortie de la console ressemble à ceci:

Titre: Catégorie:

avec le curseur apparaissant après la catégorie. Si je saisis maintenant, le programme passe alors en avance à la saisie de l'année, ne me permettant pas d'entrer plus d'une chaîne. Qu'est-ce qu'il se passe ici?

18
user754852

Le problème est que vous mélangez des appels à getline () avec l'utilisation de l'opérateur >>.

Rappelez-vous que l'opérateur >> a ignoré les espaces blancs de début et qu'il continuera donc correctement à travers les limites des lignes. Mais arrête la lecture une fois l’entrée récupérée avec succès et n’avalera donc pas les caractères '\ n' suivants. Ainsi, si vous utilisez getline () après un >>, vous obtenez généralement la mauvaise chose, à moins que vous ne soyez prudent (supprimez d'abord le caractère '\ n' qui n'a pas été lu).

L'astuce consiste à ne pas utiliser les deux types d'entrée. Choisissez celui qui convient et respectez-le.

S'il s'agit de tous les nombres (ou des objets qui jouent Nice avec l'opérateur >>), il suffit d'utiliser l'opérateur >> (La chaîne de note est le seul type fondamental qui n'est pas symétrique avec entrée/sortie (c'est-à-dire qui ne joue pas correctement)).

Si l'entrée contient des chaînes ou une combinaison d'éléments nécessitant getline (), utilisez uniquement getline () et analysez le nombre dans la chaîne.

std::getline(std::cin, line);
std::stringstream  linestream(line);

int  value;
linestream >> value;

// Or if you have boost:
std::getline(std::cin, line);
int  value = boost::lexical_cast<int>(line);
18
Martin York

Vous devez vider le tampon d'entrée. Cela peut être fait avec cin.clear(); cin.sync();.

11
Marc Plano-Lesay

Vous pouvez utiliser 

cin.ignore();

ou comme @kernald a mentionné l'utilisation 

cin.clear();
cin.sync();

avant d'utiliser getline ()

8
Breeze

Utilisez cin.clear() comme indiqué et utilisez un traitement des erreurs approprié:

    cin.clear();
    cin.sync();

    cout << "Title: "; 
    if (!getline(cin, inputString))  exit 255;
    tempDVD.setTitle(inputString);

    cout << "Category: "; 
    if (!getline(cin, inputString))  exit 255;
    tempDVD.setCategory(inputString);

    cout << "Duration (minutes): "; 
    if (!(cin >> inputUInt)) exit 255; 
    tempDVD.setDuration(inputUInt);

    cout << "Year: "; 
    if (!(cin >> inputUInt)) exit 255; 
    tempDVD.setYear(inputUInt);

    cout << "Price: $"; 
    if (!(cin >> inputDouble)) exit 255; 
    tempDVD.setPrice(inputDouble);
3
sehe

cin.sync (); utilise ceci à la place de cin.ignore ( fonctionne mieux.

0
Gurudev

Le mélange de getline () avec des flux d'entrée est généralement une mauvaise chose à faire. Il est théoriquement possible de gérer manuellement les tampons sales laissés en utilisant des flux, mais c'est une douleur inutile qui doit absolument être évitée.

Vous feriez mieux d’utiliser une bibliothèque de console pour saisir votre entrée, de cette façon, le sale boulot peut être extrait pour vous.

Jetez un coup d'oeil à TinyCon. Vous pouvez simplement utiliser la méthode statique tinyConsole :: getLine () en remplacement de vos appels getline et stream, et vous pouvez l'utiliser autant de fois que vous le souhaitez.

Vous pouvez trouver des informations ici: https://sourceforge.net/projects/tinycon/

0
Unix-Ninja