Usando getline(cin, s) después de cin [duplicado]
Necesito el siguiente programa para tomar la línea completa 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);
Sin embargo , con el cin >> number
comando antes del getline()
comando (que supongo que es el problema), no me permite ingresar nombres. ¿Por qué?
Escuché algo sobre un cin.clear()
comando, pero no tengo idea de cómo funciona o por qué es necesario.
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' );
después cin>>number;
de vaciar el búfer de entrada por completo (rechazando todos los caracteres adicionales hasta que se encuentre una nueva línea). Necesitas #include <limits>
obtener el max()
método.
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 utilizar simplemente ignorar?
Esto es bastante detallado, por lo que usarlo ignore
en la secuencia posterior >> x
es una forma alternativa muy recomendada de 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 datos corruptos en el archivo. Puede que le importe o no, dependiendo de si el contenido del archivo es confiable, de qué tan importante es evitar el procesamiento de datos corruptos, etc.
Entonces, ¿cuándo usarías borrar e ignorar?
Por lo tanto, 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 similar?
Otra alternativa simple pero a medias ignore
para su requisito original es usar std::skipws
para omitir cualquier cantidad de espacios 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, un científico que intenta ingresar 1.000.000 pero C++ solo admite esa notación para números de coma flotante) no acepta eso, terminaría con number
set to 1
y E6
se leería como primer valor de name
. Por otra parte, si tuviera un número válido seguido de una o más líneas en blanco, esas líneas se ignorarían silenciosamente.