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.

33
demandé sur Michael Currie 2011-04-21 09:29:21

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 number1 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.

9
répondu Tony Delroy 2016-05-16 04:04:38
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);
16
répondu Cristiano Miranda 2012-07-08 19:11:47

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.

15
répondu jonsca 2011-04-21 05:53:23

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);
9
répondu Martin York 2011-04-21 08:47:58

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);
5
répondu Rajeev Atmakuri 2015-04-16 17:50:21

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);
1
répondu Pzy64 2016-09-12 13:23:43
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.

1
répondu Aditya Gullapalli 2018-03-19 17:11:05
cppreference.

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 avec cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); avant de passer à l'entrée orientée ligne.

0
répondu shuaihanhungry 2016-08-20 02:17:39

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;
}
0
répondu lopezdp 2016-09-16 18:49:15

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.

0
répondu 1911 Soldier 2016-10-27 17:25:31

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!

0
répondu ngọcminh.oss 2017-11-09 12:56:45
#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 cinmémoire tampon interne. Si oui: l'ignorer (essentiellement l'ignorer)

-1
répondu max 2015-02-03 09:55:03