
Originariamente inviata da
ing82
Ne segue quindi di evitare come la peste cin>>... (cosa che avevi già detto, però che non viene detta ai neofiti da nessuna parte, almeno dove ho guardato io...).
In realtà l'input è sempre stato una rogna in ogni linguaggio e C++ non fa eccezione. In genere viene sempre insegnato l'uso di operator >> per comodità/ facilità di apprendimento, ma appena si esce dall'ambito scolastico le cose cambiano drasticamente.
In realtà operator >> va evitato come la peste se il tipo di dato da acquisire è un char, int, double etc; ossia i tipi di dato nativo (tra i quali, e solo in questo singolo caso, si deve porre anche std::string in quanto operator >> tronca l'acquisizione al primo spazio).
operator >> in realtà è comodissimo se posto in overload con una classe per acquisire input, ma tale classe poi finirà per inserire i dati dentro int, char, float etc, pertanto si torna nel caso precedente.
Pertanto per evitare di incasinare l'input (cin) è preferibile acquisire l'input come stringa (std::string preferibilmente) e poi effettuare la validazione dell'input su tale stringa (con istringstream o altri metodi più o meno sofisticati).
Resta il problema di come segnalare un errore di conversione, ma presumo tu sappia come fare
Stando cosi' le cose la funzione pause potrebbe diventare
Meglio
codice:
void pause()
{
cout << "messaggio" << endl;
int c;
do {
c = cin.get();
} while (c != '\n' && c != EOF);
};
Per quanto riguarda il resto, non capisco perchè mi consigli di usare ostringstream e non istringstream.
Errore mio dovuto al post al volo.
Ad esempio, per l'input degli int potrebbe essere una cosa del genere (?):
Così è più flessibile. Tuttavia se chiedi un int e immetti un float, la funzione non fallisce ma fa un cast tra float e int, ossia 3.56 diventa 3, mentre se chiedi un float e inserisci un int il cast e da int a float, ossia 3 diventa 3.000000.
E' una validazione dell'input un pò blanda, ma evita che inserendo o.004 invalidi cin.
Se hai bisogno di qualcosa di più sofisticato, istringstream non basta più e serve scriversi la validazione dell'input a "mano".
p.s. ho messo sia il throw, sia la booleana. Decidi tu cosa lasciare.
codice:
template <typename T>
T read(std::istream& is, bool& valid ) {
// be optimistic
valid = true;
std::string line;
do {
getline(is, line);
} while (line.empty());
T data;
istringstream iss(line);
iss >> data;
if (!iss) {
valid = false;
// throw std::logic_error("invalid input");
}
return data;
}
// per simmetria
template <>
std::string read(std::istream& is, bool& valid) {
valid = true;
std::string line;
do {
getline(is, line);
} while (line.empty());
return line;
}