Usar getline(cin, s) después de cin [duplicate]

7 minutos de lectura

Usar getlinecin s despues de cin duplicate
pauliwago

Necesito el siguiente programa para tomar toda la línea de entrada del usuario y ponerla en nombres de cadena:

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

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

getline(cin, names);

Con el cin >> number comando ante el getline() Sin embargo, el comando (que supongo que es el problema), no me permitirá ingresar nombres. ¿Por qué?

Escuché algo sobre un cin.clear() comando, pero no tengo idea de cómo funciona esto o por qué es necesario.

  • Asumiendo que escribiste: 5<enter>John<enter>. Luego cin >> number lee SÓLO 5. dejando el carácter de nueva línea (ingresar) en la transmisión. Por lo tanto, cuando intenta leer el nombre con getline(cin,name) se lee hasta el final de la línea. PERO NOTA hay un carácter de nueva línea listo para ser leído (por lo tanto, los nombres estarán vacíos (porque no leyó el carácter de nueva línea después del 5). Si desea cambiar entre >> y getline(), necesita tenga cuidado con el final final de las líneas en su entrada.

    – Martín York

    21 de abril de 2011 a las 8:41

  • @LokiAstari: Eso es mejor responder que cualquiera de los publicados a continuación. ¿Podrías publicarlo como tal?

    – Carreras de ligereza en órbita

    29 mayo 2015 a las 18:39

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

Otra forma de hacerlo es poner un

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

despues de ti cin>>number; para vaciar el búfer de entrada por completo (rechazando todos los caracteres adicionales hasta que se encuentre una nueva línea). Necesitas #include <limits> para obtener el max() método.

  • @jonsca: “rechazar todos los caracteres adicionales” es dudoso en la mayoría de los sistemas de producción … está bien comer espacios en blanco, pero descartar datos desconocidos puede conducir fácil y silenciosamente a resultados incorrectos.

    – Tony Delroy

    21 de abril de 2011 a las 6:03

  • @cnicutar varía de implementación a implementación

    – jonsca

    21 de abril de 2011 a las 6:08

  • @Tony ¿Qué tal, en lugar de una línea de obtención, si tiene un ciclo que toma caracteres colocados después de la declaración cin? Seguramente los personajes adicionales arrojarán una llave inglesa en eso. ¿Estás hablando más de agujeros de seguridad?

    – jonsca

    21 de abril de 2011 a las 6:10


  • “bucle tomando caracteres”… si te refieres while (isspace(cin.peek())) cin.ignore()… me parece bien. Re arriba, estaba pensando más en un usuario que malinterpreta los requisitos de formato de entrada, o en algún script que genera las interrupciones de entrada, pero la entrada rota parece procesarse correctamente porque se ignora; pueden terminar confiando en los resultados rotos. Si la entrada no cumple con las especificaciones, es mejor que su programa genere un error.

    – Tony Delroy

    21 de abril de 2011 a las 6:26

  • @Tony Ah, está bien, malinterpreté lo que intentabas decir. Buen punto sobre la validación.

    – jonsca

    21 de abril de 2011 a las 6:39

1647560771 595 Usar getlinecin s despues de cin duplicate
tony delroy

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

En el código anterior, este bit…

    char c;
    while (cin.get(c) && c != '\n')
        if (!std::isspace(c))
        {
            std::cerr << "ERROR unexpected character '" << c << "' found\n";
            exit(EXIT_FAILURE);
        }

…comprueba el resto de la línea de entrada después de que el número contenga solo espacios en blanco.

¿Por qué no simplemente usar ignorar?

Eso es bastante detallado, por lo que usar ignore en la corriente después >> x es una forma alternativa recomendada con frecuencia para descartar contenido hasta la siguiente nueva línea, pero corre el riesgo de descartar contenido que no sea un espacio en blanco y, al hacerlo, pasar por alto los datos corruptos en el archivo. Puede que le importe o no, dependiendo de si el contenido del archivo es confiable, qué tan importante es evitar el procesamiento de datos corruptos, etc.

Entonces, ¿cuándo usarías borrar e ignorar?

Entonces, std::cin.clear() (y std::cin.ignore()) no es necesario para esto, pero es útil para eliminar el estado de error. Por ejemplo, si desea darle al usuario muchas oportunidades para ingresar un número válido.

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

¿No puede ser más sencillo con skipws o similares?

Otra alternativa simple pero a medias para ignore para su requisito original está utilizando std::skipws para omitir cualquier cantidad de espacio en blanco antes de leer las líneas…

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

… pero si recibe una entrada como “1E6” (por ejemplo, algún científico que intenta ingresar 1,000,000 pero C ++ solo admite esa notación para números de coma flotante) no aceptará eso, terminaría con number ajustado a 1y E6 se lee como el primer valor de name. Por separado, si tuviera un número válido seguido de una o más líneas en blanco, esas líneas se ignorarían en silencio.

  • Erm, esto no responde la pregunta ni soluciona el problema. -1

    – Carreras de ligereza en órbita

    11 de septiembre de 2015 a las 0:19

  • @LightnessRacesinOrbit: ¿cómo “no soluciona el problema”? La primera llamada a getline consume la nueva línea después del número y realiza un bucle hasta que encuentra una línea que no está vacía … me parece arreglado. La pregunta del OP no preguntó “¿por qué?” ocurrió el problema, pero comentó que no estaba seguro de por qué clear podría ser necesario: alguien más editó la pregunta de 5 años hace 2 días para agregar eso, cambiando sustancialmente la esencia.

    – Tony Delroy

    13 de septiembre de 2015 a las 14:01


  • Ahora has editado en [someone else’s] responde es mejor

    – Carreras de ligereza en órbita

    13/09/2015 a las 15:33

  • @LightnessRacesinOrbit: edité la esencia de mi comentario sobre la respuesta de jonsca, de 2011, nada nuevo.

    – Tony Delroy

    14 de septiembre de 2015 a las 0:24


Tratar:

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;

Alternativamente. Si sabe que número y nombres siempre estarán en líneas diferentes.

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

Puede usar std::ws para extraer cualquier carácter de espacio en blanco en el búfer de entrada antes de usar getline. El encabezado para std::ws es sstream.

cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);

1647560771 801 Usar getlinecin s despues de cin duplicate
Zoe apoya a Ucrania

Pruebe cin.ignore() cuando use cin antes de la función 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);
}

O puede vaciar el búfer de entrada para leer la cadena

fflush(entrada estándar)

se define en el encabezado stdio.h.

Este código funciona..

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

cout << "Enter names: ";
string names;
fflush(stdin);  //FLUSHING STDIN
getline(cin, names);

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad