web-dev-qa-db-fra.com

Utiliser getline (cin, s) après cin

J'ai besoin du programme suivant pour prendre toute la ligne de saisie de l'utilisateur et la mettre dans des noms de chaîne:

cout << "Enter the number: ";
int number;
cin >> number;

cout << "Enter names: ";
string names;

getline(cin, names);

Cependant, avec la commande cin >> number avant la commande getline() (ce qui, je suppose, est le problème), cela ne me permet pas de saisir des noms. Pourquoi?

J'ai entendu parler d'une commande cin.clear(), mais je n'ai aucune idée de la façon dont cela fonctionne ni pourquoi cela est même nécessaire.

34
pauliwago
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 que le numéro ne contient plus que des espaces.

Pourquoi ne pas simplement utiliser ignorer?

C'est assez bavard, donc utiliser ignore sur le flux après >> x est une alternative souvent recommandée pour ignorer le contenu jusqu'à la nouvelle ligne, mais cela risquerait de jeter le contenu non-blanc et, ce faisant, d'ignorer les données corrompues du fichier. Selon que le contenu du fichier est fiable ou non, il est important d’éviter le traitement de données corrompues, etc. 

Alors, quand utiliseriez-vous effacer et ignorer?

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());
}

Cela ne peut-il pas être plus simple avec skipws ou similaire?

Une autre alternative simple mais à moitié cuite à ignore pour votre besoin initial utilise std::skipws pour ignorer toute quantité d’espace avant de lire des lignes ...

if (std::cin >> number >> std::skipws)
{
    while (getline(std::cin, name))
        ...

... mais s'il reçoit une entrée telle que "1E6" (par exemple, un scientifique essayant de saisir 1 000 000 mais C++ ne supporte que cette notation pour les nombres à virgule flottante) n'acceptera pas cela, vous obtiendrez number défini sur 1 et E6 lu comme première valeur de name. Séparément, si vous aviez un numéro valide suivi d'une ou de plusieurs lignes vides, ces lignes seraient ignorées en silence.

9
Tony Delroy
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
Cristiano Miranda

Une autre façon de le faire est de mettre un 

cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' ); 

après votre cin>>number; pour vider complètement le tampon d’entrée (rejeter tous les caractères supplémentaires jusqu’à ce qu’une nouvelle ligne soit trouvée). Vous devez #include <limits> pour obtenir la méthode max().

15
jonsca

Essayer:

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 connaissez ce 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
Martin York

Vous pouvez utiliser std :: ws pour extraire tous les caractères d'espacement du tampon d'entrée avant d'utiliser getline. En-tête pour std :: ws est sstream.

cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
5
Rajeev Atmakuri
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

c’est assez explicite, il reste un\n dans le flux utilisé par cin >> number, qui est assigné aux noms lors de sa première utilisation. La réutilisation de la ligne get écrit maintenant la valeur correcte.

1
Aditya Gullapalli

Ou vous pouvez vider le tampon d'entrée pour lire la chaîne

fflush (stdin)

il est défini dans l'entê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
pz64_

Vous pouvez trouver la réponse souhaitée dans cppreference .

Lorsqu'il est utilisé immédiatement après une entrée délimitée par des espaces, par ex. après int n; std::cin >> n;, getline utilise le caractère de fin de ligne laissé par l'opérateur >> dans le flux d'entrée, et retourne immédiatement. Une solution courante consiste à ignorer tous les caractères restants de la ligne d'entrée avec cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); avant de passer à une entrée orientée ligne.

0
shuaihanhungry
cout << "Enter the number: ";

int number;
cin >> number;

getc(stdin);  //you need add this line 

cout << "Enter names: ";

string names;

getline(cin, names);
0
H R shuvo

Sur le plan conceptuel, je pense que vous voulez que chaque réponse soit parfaitement une ligne. Alors pourquoi n'essayez-vous pas cela?

cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);

cout << "Enter names: ";
string names;
getline(cin, names);

Le code utilise correctement le premier caractère de nouvelle ligne, vous donne le numéro si la ligne est correcte ou lève une exception s'il ne l'est pas Tout est gratuit!

0
ngọcminh.oss

vous voulez utiliser cin.ignore () après vos instructions cin car vous voulez ignorer le "\ n" restant dans le tampon après avoir pris votre variable int avec cin.

j'ai un programme similaire que j'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
lopezdp

je viens d'utiliser 

getline(cin >> ws,lard.i_npute);

avec le standard

#include <iostream>

en-tête dans les cas où j’avais des problèmes avec les retours à la ligne et le manipulateur ws fonctionnait. Je vais probablement commencer à intégrer des fonctions en boucle sous forme de classes et à utiliser au moins des appels de constructeur et de destructeur.

0
1911 Soldier

Essayez cin.ignore () lorsque vous utilisez cin avant la fonction getline ()

void inputstu(){
    cout << "Enter roll Number:";
    cin >> roll_no;
    cin.ignore(); //ignore the withspace and enter key
    cout << "Enter name:";
    getline(cin, stu_name);
}
0
Vishal Rai