Se pierde el primer cin.getline en un analisis de casos

Iniciado por eleon, 2 Febrero 2012, 22:41 PM

0 Miembros y 1 Visitante están viendo este tema.

eleon

Holas:

Tengo un pequeño problemilla y es que dentro de un analisis de casos (switch) no se me ejecuta el primer cin.getline(). Ejemplo:

Código (cpp) [Seleccionar]
switch (opcion)
       {
           case 1:
               while (pEA->pSiguiente != 0)
               {
                   pEA = pEA->pSiguiente;
               }

               pEA->pSiguiente = new agenda;
               pEA = pEA->pSiguiente;

               cout << "Introduzca el nombre: ";
               cin.getline (nuevoNombre, tamNombre); //Este cin.getline() no se ejecuta
               pEA->configurarNombre (&nuevoNombre[0]);
               cout << endl;

               cout << "Introduzca el correo: ";
               cin.getline (nuevoCorreo, tamCorreo);
               pEA->configurarCorreo (&nuevoCorreo[0]);
               cout << endl;

              ...


He probado quitando la parte de "Introduzca el nombre" para comprobar que no es un error sintáctico y lo que sucede es que no se ejecuta el cin.getline del correo, es decir, el primer cin.getline del "case" se omite. Lo mismo me sucede en "case 2: " etc.

Para corroborarlo he probado a poner antes del "Introduzca el nombre" un cin.getline(cadena_prueba, 30), y entonces si que se ejecuta correctamente el del nombre.

¿Alguno sabe por qué el primero siempre se omite?.

Gracias y saludos.

rir3760

En la gran mayoría de los casos el comportamiento que mencionas se debe a que, antes de la parte que se "salta", tienes una sentencia que lee un valor de la entrada estándar pero deja el '\n' en el bufer.

Por ejemplo:
Código (cpp) [Seleccionar]
string palabra;
char linea[100];

// ...

cin >> palabra;
cin.getline(linea, 100); // Esto se "salta"


Supongo es eso pero, para estar seguros, lo mejor es revisar el código fuente completo.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

eleon

#2
Gracias por responder, la única entrada que hay antes es esta:

Código (cpp) [Seleccionar]
   while (opcion != 5)
   {
       opcion = 0;
       while (opcion < 1 || opcion > 5)
       {
           F_menu();
           cin >> opcion; //Primera entrada en todo el programa
           cout << endl;
       }

       switch (opcion)
       {
           case 1:
               while (pEA->pSiguiente != 0)
               {
                   pEA = pEA->pSiguiente;
               }

               pEA->pSiguiente = new agenda;
               pEA = pEA->pSiguiente;

               cout << "Introduzca el nombre: ";
               cin.getline (nuevoNombre, tamNombre); // Entrada suprimida
               pEA->configurarNombre (&nuevoNombre[0]);
               cout << endl;

               cout << "Introduzca el correo: ";
               cin.getline (nuevoCorreo, tamCorreo);
               pEA->configurarCorreo (&nuevoCorreo[0]);
               cout << endl;
...


¿Por qué mete un "\n" automáticamente en el buffer?, ¿y cuál sería la solución para evitarlo?.

EDITO: Por si ayuda te pongo el cuerpo del programa hasta donde se produce el error:

Código (cpp) [Seleccionar]
int main ()
{
   USHORT opcion;

   agenda objeto;
   agenda *pEA = &objeto;
   USHORT numContactos = 0;

   char nuevoNombre [tamNombre];
   char nuevoCorreo [tamCorreo];
   ULONG nuevoTelefono = 0;
   ULONG nuevoMovil = 0;

   bool encontrado;
   char nombre [tamNombre];
   char correo [tamCorreo];
   char *pNombre = 0;
   char *pCorreo = 0;
   USHORT contador;

   int i, j;

   while (opcion != 5)
   {
       opcion = 0;
       while (opcion < 1 || opcion > 5)
       {
           F_menu();
           cin >> opcion;
           cout << endl;
       }

       switch (opcion)
       {
           case 1:
               while (pEA->pSiguiente != 0)
               {
                   pEA = pEA->pSiguiente;
               }

               pEA->pSiguiente = new agenda;
               pEA = pEA->pSiguiente;

               cout << "Introduzca el nombre: ";
               cin.getline (nuevoNombre, tamNombre);
               pEA->configurarNombre (&nuevoNombre[0]);
               cout << endl;

               cout << "Introduzca el correo: ";
               cin.getline (nuevoCorreo, tamCorreo);
               pEA->configurarCorreo (&nuevoCorreo[0]);
               cout << endl;
...


Una cosa en la que me acabo de fijar es en cómo inicializo las cadenas en el constructor de la clase; ¿es correcto de esta forma o quizá sea lo que produce el error?:

Código (cpp) [Seleccionar]
agenda::agenda()
{
   char nombre = {'\0'};
   char correo = {'\0'};
   telefono = 0;
   movil = 0;

   pSiguiente = 0;
}


Un saludo.

rir3760

El comportamiento es normal. Cuando se ejecuta la sentencia:
Código (cpp) [Seleccionar]
cin >> opcion;
Se toman los caracteres necesarios de la entrada estándar pero el '\n' se queda en el bufer.

A continuación se ejecuta:
Código (cpp) [Seleccionar]
cin.getline (nuevoNombre, tamNombre);
Y esa función espera "cero o mas caracteres seguidos del avance de linea", como ese ya se encuentra en el bufer se toma y procesa como un linea vacía.

Soluciones hay varias: una es descartar el resto de la linea justo después de la primera sentencia, otra opción es utilizar getline para todas las lecturas junto con la clase "stringstream" para obtener los valores (hay varios ejemplos de ello en la base de datos de los foros).

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

eleon

Gracias por tu tiempo, he optado por usar "cin.ignore(1);" después del cin.

Saludos.

rir3760

En tu caso eso funciona pero (casi) como un castillo de naipes. Para explicarlo mejor compila y ejecuta el programa. Cuando te pida la opción teclea:
123 {ENTER}
Eso es: 1, 2, 3, un espacio y la tecla {ENTER}.

Es por ello que se considera una mejor opción leer una linea almacenándola en un objeto de la clase "string" y a continuación "extraes" el numero mediante otro objeto de la clase "stringstream".

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language