cout << "Enter the number: ";
int number;
if (cin >> number)
{
// throw away the rest of the line
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
cout << "Enter names: ";
string name;
// keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
while (getline(cin, name))
...use name...
}
else
{
std::cerr << "ERROR reading number\n";
exit(EXIT_FAILURE);
}
Dans le code ci-dessus, ce bit...
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
...vérifie que le reste de la ligne d'entrée après le numéro ne contient que des espaces.
Pourquoi ne pas simplement utiliser "ignorer" ?
C'est assez verbeux, donc en utilisant ignore
sur le flux après >> x
est un moyen alternatif souvent recommandé pour supprimer le contenu jusqu'à la prochaine nouvelle ligne, mais il risque de supprimer le contenu qui n'est pas un espace blanc et, ce faisant, de négliger les données corrompues dans le fichier. Vous pouvez vous en préoccuper ou non, selon que le contenu du fichier est fiable ou non, qu'il est important d'éviter de traiter des données corrompues, etc.
Alors quand utiliseriez-vous clear et ignorez ?
Donc, std::cin.clear()
(et std::cin.ignore()
) n'est pas nécessaire pour cela, mais est utile pour supprimer l'état d'erreur. Par exemple, si vous voulez donner à l'utilisateur plusieurs chances d'entrer un nombre valide.
int x;
while (std::cout << "Enter a number: " &&
!(std::cin >> x))
{
if (std::cin.eof())
{
std::cerr << "ERROR unexpected EOF\n";
exit(EXIT_FAILURE);
}
std::cin.clear(); // clear bad/fail/eof flags
// have to ignore non-numeric character that caused cin >> x to
// fail or there's no chance of it working next time; for "cin" it's
// common to remove the entire suspect line and re-prompt the user for
// input.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}
Ne peut-on pas faire plus simple avec skipws ou autre ?
Une autre alternative simple mais peu convaincante à ignore
pour votre exigence initiale est d'utiliser std::skipws
pour sauter n'importe quelle quantité d'espace avant de lire les lignes...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
...mais s'il reçoit une entrée comme "1E6" (par exemple, un scientifique essayant d'entrer 1 000 000 mais le C++ ne supporte que cette notation pour les nombres à virgule flottante) ne l'acceptera pas, vous vous retrouverez avec number
réglé sur 1
y E6
lu comme la première valeur de name
. Par ailleurs, si un numéro valide est suivi d'une ou plusieurs lignes vides, ces lignes sont ignorées en silence.