Da dieses Problem unter Anfänger ziemlich oft vorkommt, hier mal meine kleine Funktion, die ich nur privat ab und an mal benutze:
Code:
#include <iostream>
#include <string>
namespace io_funcs
{
template <typename T>
T read_from_stdin(const std::string& prompt, int attempt_count)
{
int attempts = 0;
T value = T();
do
{
std::cout << prompt;
if(std::cin >> value)
{
break;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
++attempts;
}
while(attempts < attempt_count);
return value;
}
template <typename T>
T read_from_stdin(const std::string& prompt, int attempt_count, bool& success)
{
int attempts = 0;
T value = T();
success = false;
do
{
std::cout << prompt;
if(std::cin >> value)
{
success = true;
break;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
++attempts;
}
while(attempts < attempt_count);
return value;
}
template <typename T>
T read_from_stdin(const std::string& prompt)
{
T value = T();
std::cout << prompt;
if(!(std::cin >> value))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
template <>
std::string read_from_stdin<std::string>(const std::string& prompt, int attempt_count)
{
int attempts = 0;
std::string line;
do
{
std::cout << prompt;
if(std::getline(std::cin, line))
{
break;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
++attempts;
}
while(attempts < attempt_count);
return line;
}
template <>
std::string read_from_stdin<std::string>(const std::string& prompt, int attempt_count, bool& success)
{
int attempts = 0;
std::string line;
success = false;
do
{
std::cout << prompt;
if(std::getline(std::cin, line))
{
success = true;
break;
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
++attempts;
}
while(attempts < attempt_count);
return line;
}
template <>
std::string read_from_stdin<std::string>(const std::string& prompt)
{
std::string line;
std::cout << prompt;
if(!std::getline(std::cin, line))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return line;
}
};
Das template ist für std::string spezialisiert, da ich oft komlette Zeilen (inklusive Leerzeichen) einlesen musste.
Beispiel für Benutzung:
Code:
int main()
{
auto str = IOFuncs::read_from_stdin<std::string>("Tell me a story: ");
int tel = IOFuncs::read_from_stdin<int>("Telephone: ");
std::cout << "Your amazing story: " << str << std::endl;
std::cout << "Telephone: " << tel << std::endl;
}
Weiterhin kann man optional die Anzahl der Versuche festlegen. Falls gewünscht kann man über den Parameter success herausfinden, ob eine korrekte Eingabe nach der definierten Anzahl an Versuchen geklappt hat. In jedem Fall wird der Defaultwert zurückgegeben, falls die Eingabe nicht korrekt war.
Standardmäßig hat man nur den einen Versuch (siehe oben).
Code:
int main()
{
bool success = false;
const int attempts = 3;
double money = io_funcs::read_from_stdin<double>("Money: ", attempts, success);
if(success)
{
std::cout << "Input succeeded: " << money << std::endl;
}
else
{
std::cout << "No input after " << attempts << " attempts" << std::endl;
std::cout << "Default value: " << money << std::endl;
}
}
Gruß