Utilisation de getline (cin, s) après cin
j'ai besoin de le programme suivant pour prendre la totalité de la ligne de saisie de l'utilisateur et de le mettre dans des noms de chaîne:
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);
cin >> number
commande avant le getline()
commande cependant (qui je suppose est la question), il ne me permet pas d'entrer des noms. Pourquoi?
j'ai entendu parler d'un cin.clear()
commande, mais je n'ai aucune idée de comment cela fonctionne, ou pourquoi c'est même nécessaire.
12 réponses
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 le reste de la ligne d'entrée après le nombre ne contient que des espaces.
pourquoi ne pas simplement utiliser ignorer?
C'est assez verbeux, donc, à l'aide de ignore
sur le cours d'eau après >> x
est une alternative souvent recommandée pour rejeter du contenu vers la nouvelle ligne suivante, mais elle risque de jeter du contenu non-espace et, ce faisant, d'ignorer les données corrompues dans le fichier. Vous pouvez ou peut ne pas se soucier, selon que le contenu du fichier est fiable, combien il est important d'éviter le traitement des données corrompues, etc..
alors quand utiliseriez-vous clear et ignore?
Donc, std::cin.clear()
(et std::cin.igore()
) n'est pas nécessaire pour cela, mais est utile pour supprimer l'état d'erreur. Par exemple, si vous voulez donner à l'utilisateur de nombreuses 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-il pas être plus simple avec des putois ou similaires?
un autre simple mais mi-cuit alternative à l' ignore
car votre exigence initiale est d'utiliser std::skipws
pour sauter n'importe quelle quantité de blanc avant de lire les lignes...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
...mais s'il reçoit des entrées comme " 1E6 " (par exemple un scientifique essayant d'entrer 1.000.000 mais C++ supporte seulement cette notation pour les nombres à virgule flottante) ne l'acceptera pas, vous finirez avec number
1
et E6
lire que la première valeur de name
. Séparément, si vous aviez un numéro valide, suivi par un ou plusieurs les lignes vides, ces lignes seraient silencieusement ignorées.
cout << "Enter the number: ";
int number;
cin >> number;
cin.ignore(256, '\n'); // remaining input characters up to the next newline character
// are ignored
cout << "Enter names: ";
string names;
getline(cin, names);
une Autre façon de le faire est de mettre un
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
après cin>>number;
vider le tampon d'entrée complètement (rejeter tous les caractères supplémentaires jusqu'à ce qu'un saut de ligne). Vous devez vous #include <limits>
pour obtenir l' max()
méthode.
Essaie:
int number;
cin >> number;
char firstCharacterOfNames;
cin >> firstCharacterOfNames; // This will discard all leading white space.
// including new-line if there happen to be any.
cin.unget(); // Put back the first character of the name.
std::string names;
std::getline(cin, names); // Read the names;
Alternativement. Si vous savez que le nombre et les noms seront toujours sur des lignes différentes.
cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(cin, names);
Vous pouvez utiliser std::ws pour extraire n'importe quel caractère d'espace dans le tampon d'entrée avant d'utiliser getline. L'en-tête pour le std::ws est succession.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
Ou vous pouvez vider le tampon d'entrée pour lire la chaîne de caractères
fflush (stdin)
il est défini dans l'en-tête stdio.h.
Ce code fonctionne..
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
fflush(stdin); //FLUSHING STDIN
getline(cin, names);
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);//works on the \n left behind
getline(cin, names);//continues and rewrites names
son assez auto explicatif, il ya un \n laissé derrière dans le flux que cin >> number
utilisations, qui se voit attribuer des noms la première fois qu'il est utilisé. Réutiliser le getline écrit la bonne valeur maintenant.
lorsqu'il est utilisé immédiatement après une entrée délimitée par des espaces, p.ex. après
int n; std::cin >> n;
, getline consomme le caractère de fin de ligne laissé sur le flux d'entrée par l'opérateur>>, et retourne immédiatement. Une solution courante est d'ignorer tous les caractères restants sur la ligne d'entrée aveccin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
avant de passer à l'entrée orientée ligne.
vous voulez utiliser cin.ignorez () après vos instructions cin parce que vous voulez ignorer le "\N" laissé dans le tampon après avoir pris votre variable int avec cin.
j'ai un programme similaire, je l'ai utilisé avec un problème similaire:
#include <iostream>
#include <iomanip>
#include <limits>
using namespace std;
int main() {
int i = 4;
double d = 4.0;
string s = "HackerRank ";
// Declare second integer, double, and String variables.
int n;
double d2;
string str;
// Read and save an integer, double, and String to your variables.
cin >> n;
cin >> d2;
cin.ignore();
getline(cin, str);
// Print the sum of both integer variables on a new line.
cout << i + n << endl;
// Print the sum of the double variables on a new line.
cout << d + d2 << endl;
// Concatenate and print the String variables on a new line
cout << s << str << endl;
// The 's' variable above should be printed first.
return 0;
}
j'ai simplement utilisé
getline(cin >> ws,lard.i_npute);
avec la norme
#include <iostream>
en-tête dans les cas où j'avais des problèmes avec les retours de chariot et le manipulateur ws fonctionnait. Je vais probablement commencer à intégrer des fonctions de bouclage en tant que classes et en utilisant des appels de constructeur et de destructeur au moins.
Sur le plan conceptuel, je pense que vous voulez que chaque réponse soit clairement une ligne. Alors pourquoi ne pas essayer ça?
cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);
cout << "Enter names: ";
string names;
getline(cin, names);
le code consomme correctement le premier caractère newline, vous donne le nombre si la ligne est correcte ou lance une exception si elle ne l'est pas. Le tout gratuitement!
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
// USE peek() TO SOLVE IT! ;)
if (cin.peek() == '\n') {
cin.ignore(1 /*numeric_limits<streamsize>::max()*/, '\n');
}
getline(cin, names);
return 0;
}
il suffit de regarder en avant en utilisant cin.peek()
et voir si a '\n'
reste cin
mémoire tampon interne. Si oui: l'ignorer (essentiellement l'ignorer)