Ignorar espacios usando getline en C ++

Hola, estoy tratando de escribir un progtwig que acepte nuevas tareas de personas, lo agregue a una stack, pueda mostrar la tarea, pueda guardar esa stack en un archivo de texto y luego leer el archivo de texto. El problema surge cuando bash aceptar la entrada del usuario, siempre que ingresa una cadena con un espacio en ella, el menú para elegir qué hacer solo realiza un bucle. Necesito una manera de arreglar esto. Cualquier ayuda sería muy apreciada.

// basic file io operations #include  #include  #include  #include  using namespace std; int main () { //Declare the stack stack list; //Begin the loop for the menu string inputLine; cout << "Welcome to the to-do list!" << endl; //Trying to read the file ifstream myfile ("to-do.txt"); if(myfile.is_open()){ //read every line of the to-do list and add it to the stack while(myfile.good()){ getline(myfile,inputLine); list.push(inputLine); } myfile.close(); cout << "File read successfully!" << endl; } else { cout << "There was no file to load... creating a blank stack." << endl; } int option; //while we dont want to quit while(true){ //display the options for the program cout << endl << "What would you like to do?" << endl; cout << "1. View the current tasks on the stack." << endl; cout << "2. Remove the top task in the stack." << endl; cout << "3. Add a new task to the stack." << endl; cout << "4. Save the current task to a file." << endl; cout << "5. Exit." << endl <> option; //use the option to do the necessary task if(option  0){ if(option == 1){ //create a buffer list to display all stack buff = list; cout << endl; //print out the stack while(!buff.empty()){ cout << buff.top() << endl; buff.pop(); } }else if (option == 2){ list.pop(); }else if (option == 3){ //make a string to hold the input string task; cout << endl << "Enter the task that you would like to add:" << endl; getline(cin, task); // THIS IS WHERE THE ISSUE COMES IN cin.ignore(); //add the string list.push(task); cout << endl; }else if (option == 4){ //write the stack to the file stack buff = list; ofstream myfile ("to-do.txt"); if (myfile.is_open()){ while(!buff.empty()){ myfile << buff.top(); buff.pop(); if(!buff.empty()){ myfile << endl; } } } myfile.close(); }else{ cout << "Thank you! And Goodbye!" << endl; break; } } else { cout << "Enter a proper number!" << endl; } } } 

Tienes que agregar cin.ignore() justo después de elegir las opciones:

 //get the input from the user cin >> option; cin.ignore(); 

Y cin.ignore() no es necesario después de su línea de getline :

  getline(cin, task); // THIS IS WHERE THE ISSUE COMES IN //cin.ignore(); 

El problema está en las options : si no llamó a cin.ignore() después, las opciones contendrán el final de la línea y el bucle continuará …

Espero que esto ayude.

No hagas esto

  while(myfile.good()) { getline(myfile,inputLine); list.push(inputLine); } 

El indicador EOF no se establece hasta que intenta leer más allá del EOF. La última línea completa leída hasta (bit no pasado) el EOF. Por lo tanto, si tiene cero entradas, myfile.good () es verdadero y el bucle está enetered. Luego, intenta leer una línea y fallará, pero aún así presiona.

La forma estándar de leer todas las líneas en un archivo es:

  while(getline(myfile,inputLine)) { list.push(inputLine); } 

De esta manera, el bucle solo se ingresa si el archivo contiene datos.

Tu otro problema parece deberse al hecho de que tienes:

  std::getline(std::cin,task); // THIS is OK std::cin.ignore(); // You are ignoring the next character the user inputs. // This probably means the next command number. // This means that the next read of a number will fail // This means that std::cin will go into a bad state // This means no more input is actually read. 

Así que simplemente suelta la línea cin.ignore () y todo funcionará.

En lugar de usar “>>” directamente en su transmisión, podría considerar usar getline y luego intentar obtener su opción de eso. Sí, es menos “eficiente” pero la eficiencia no es generalmente un problema en tales situaciones.

Usted ve, el problema es que el usuario podría introducir algo tonto aquí. Por ejemplo, podrían ingresar algo como “dos”, pulsar Intro, y luego su progtwig lanzará un ajuste mientras continúa felizmente tratando de descifrar una opción vacía una y otra y otra y otra vez. El único recurso del usuario es la forma en que lo configuró (y la manera en que lo recomiendan los que recomiendan el uso de ignore() ) es matar el progtwig. Un progtwig bien educado no responde de esta manera a una mala entrada.

Por lo tanto, su mejor opción no es escribir código frágil que pueda descomponerse seriamente con el más modesto de ignorancia / malfuncionamiento del usuario, sino escribir código que pueda manejar las condiciones de error correctamente. No puedes hacer eso esperando que el usuario ingrese un número y luego una nueva línea. Invariablemente, algún día, apostarás mal.

Entonces, tienes dos opciones para leer tu opción. Primero, lea una línea completa del usuario, asegúrese de que el flujo siga siendo bueno y luego convierta la cadena que obtiene en un flujo e intente leer su número entero, asegurándose de que este otro flujo siga siendo bueno. Segunda opción, intente leer un número, verifique que la secuencia aún sea buena, lea una línea y asegúrese de que la secuencia aún sea buena y que su cadena esté vacía (o simplemente ignórela si no lo es, su elección).

@Vladimir tiene razón. Aquí está el mecanismo detrás del error:

Cuando ingresa la opción ‘3’, lo que realmente pone en transmisión es “3 \ n”. cin >> option consume “3” y deja “\ n”. getline() consume “\ n” y su llamada a ignore() después de que getline() espera la entrada del usuario.

Como puede ver, la secuencia de eventos ya no es lo que esperaba.

Ahora, mientras ignore () está esperando una entrada, escribe tu línea. Esa línea que estás escribiendo es lo que irá a la opción “cin >>.

Si solo le da un símbolo, ignore () lo eliminará por usted, y la opción se leerá correctamente. Sin embargo, si le da símbolos no numéricos, la secuencia establecerá failbit cuando intente leer la opción. A partir de ese momento, su transmisión se negará a hacer nada. Cualquier << o getline no establecerá ningún valor nuevo en las variables que se supone que deben cambiar. Mantendrás 3 en la opción y "" en la tarea, en un circuito cerrado.

Cosas para hacer:

  • Compruebe siempre cin.eof (), cin.fail () y cin.bad ().
  • siempre inicialice sus variables y declarelas en el ámbito más estrecho posible (declare option = 0 justo antes de leerlo).

Acabo de descubrir una forma de hackearlo, no la mejor, pero funciona. Cree una matriz de caracteres, y luego acepte la entrada en la matriz, y luego coloque todo en la matriz en la cadena.

 char buff[256]; cout << endl << "Enter the task that you would like to add:" << endl; cin >> task; task += " "; cin.getline(buff, 256); for(int i = 1; buff[i] != 0; i++){ task += buff[i]; }