elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: (TUTORIAL) Aprende a emular Sentinel Dongle By Yapis


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  PROBLEMA con la funcion miembro getline() e ignore()
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: PROBLEMA con la funcion miembro getline() e ignore()  (Leído 7,417 veces)
.:BlackCoder:.


Desconectado Desconectado

Mensajes: 388


Cada dia C++!!


Ver Perfil
PROBLEMA con la funcion miembro getline() e ignore()
« en: 26 Julio 2010, 06:07 am »

Wenas... no se si es por el tiempo sin programar o wtf pero tengo problemas con getline() Lo explico en el codigo:

Código
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <fstream>
  4.  
  5. using namespace std;
  6.  
  7. int main(int argc, char *argv[])
  8. {
  9.    ofstream sal("Agenda.txt");
  10.    sal<<"Pedro Perez                  :"<<18<<endl;//Agrego un nombre y espacios
  11.    sal<<"Maria Rodriguez              :"<<56<<endl;//para completar 29 caracteres
  12.    sal.close();                                                     //mas el ':'
  13.  
  14.    ifstream ent("Agenda.txt");
  15.    int c=2;
  16.    char reg[c][30];
  17.    int edad[c];
  18.    for (int i=0;ent;i++){
  19.        ent.getline(reg[i],30);//Aca deberia extraer los 29 caracteres y agregar a reg un '\0'
  20.        ent.ignore();//Aca ignorar el ':'
  21.        ent>>edad[i];//Pes leer la edad
  22.        ent.ignore();//Ignorar el fin de linea...
  23.    }
  24.  
  25.    cout<<reg[0]<<"T"<<edad[0]<<endl;//Mostrar tal cual como esta en el archivo
  26.    cout<<reg[1]<<"T"<<edad[1]<<endl;//La T era un ':', pero lo use para ver
  27.                                    //si conseguia el error
  28.  
  29.    ent.close();
  30.  
  31.    system("PAUSE");
  32.    return EXIT_SUCCESS;
  33. }
  34.  

Me imagino el error esta en getline()... La use pasandole como delimitador ':' y funciono pero igual me quedo la duda de porque no funciona...

Gracias a quien pueda aclarar la duda...

Saludos...


Asi es como "funciona" bueno mas o menos porque el for da una vuelta de mas... como que si no consigue el EOF, pero no se porque el ejemplo de arriba no lo hace =.=

Código
  1.    ofstream sal("Agenda.txt");
  2.    sal<<"Pedro Perez                  :"<<18<<endl;
  3.    sal<<"Maria Rodriguez              :"<<34<<endl;
  4.  
  5.    sal.close();
  6.    ifstream ent("Agenda.txt");
  7.    char name[2][30];
  8.    int age[2];
  9.    for (int i=0;ent;i++){
  10.        ent.getline(name[i],31,':');
  11.        cout<<name[i];
  12.        ent>>age[i];
  13.        cout<<age[i]<<endl;
  14.        ent.ignore();
  15.        cout<<i<<endl;
  16.    }
  17.  
  18.    ent.close();
  19.  
Por favor alguien que me aclare porque no funciona el code del mensaje anterior y porque este da una vuelta de mas...


Saludos...


« Última modificación: 26 Julio 2010, 22:33 pm por Littlehorse » En línea

"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja



Littlehorse
All the world's a stage
Moderador
***
Desconectado Desconectado

Mensajes: 2.714


Nie Dam Sie


Ver Perfil WWW
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #1 en: 27 Julio 2010, 01:19 am »

Código
  1.    for (int i=0;ent;i++){
  2.        ent.getline(name[i],31,':');
  3.        cout<<name[i];
  4.        ent>>age[i];
  5.        cout<<age[i]<<endl;
  6.        ent.ignore();
  7.        cout<<i<<endl;
  8.    }


El problema es que en este tipo de lecturas es que encontras el final cuando intentas leer en el, y no cuando leíste el ultimo elemento. Por eso mismo en este tipo de casos se comprueba o bien el valor exitoso del método utilizado en la lectura u métodos similares a ::eof. De lo contrario, imprimis ya pasado el EOF del archivo y por esa razon el ciclo tiene iteraciones de mas.

En cuanto al primer código, getline es bastante particular y setea failbit por varias razones. En el caso que se extraigan n-1 caracteres y no se encuentre el delimitador, failbit se setea por tanto las siguientes operaciones pueden fallar.

Código
  1.    for (int i=0;ent;i++){
  2.        ent.getline(reg[i],30);//Aca deberia extraer los 29 caracteres y agregar a reg un '\0'
  3.       //logic error. failbit set
  4.        if(ent.fail())//if failbit set
  5.        ent.clear();//all flags set to default =goodbit
  6.        ent.ignore();//Aca ignorar el ':'
  7.        ent>>edad[i];//Pes leer la edad
  8.        ent.ignore();//Ignorar el fin de linea...
  9.    }

Obviamente esa no es la solución ya que es ignorar el error, pero es simplemente para que veas que por ahí van los tiros.

Lo ideal es parsear el archivo correctamente sin dejar nada al azar, pero igualmente la segunda solucion que pusiste puede funcionar correctamente siempre que se chequeen los flags de error y el final del archivo. También ten en cuenta que ignore tiene parámetros que puedes utilizar para sacarle mas provecho y evitar que ignore posibles datos necesarios.

::fail
::bad
::eof

Me dijiste antes que tenias otras dudas así que cualquier cosa ya sabes.

Saludos!


En línea

An expert is a man who has made all the mistakes which can be made, in a very narrow field.
.:BlackCoder:.


Desconectado Desconectado

Mensajes: 388


Cada dia C++!!


Ver Perfil
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #2 en: 27 Julio 2010, 01:50 am »

Jumm ahora me doy cuenta que toy grave  :xD cuando getline setea el failbit las operaciones siguientes fallan? Eso no lo tengo claro, crei q setear el failbit no tenia importancia, que solo era para cuando uno quiera verificar errores y todo eso...

Weno lo que viene es un code larguito  :xD pero pes como siempre quise hacer algo mas complejo, Agregar y quitar "registros" (Noten las comillas) a un archivo, pero de TEXTO, y ya se que lo ideal segun casi todos es que sea binario, pero pes lo quiero hacer en forma texto... en el fichero se deben ver mas o menos asi los registros:

Pedro Perez                  :18
Maria Rodriguez              :34
Ana Vergara                  :55

Un nombre completado con espacios para conseguir 29 caracteres mas ':' para... ni se para que digamos que para complicarme mas  :xD y un entero que segun yo es la edad... mas su respectivo fin de linea...

Tengo este code, con una funcion contar() que cuenta los "registros", una funcion extraer() que los extrae e ingresa  en un vector de estructuras, otra ordenar() que ordena el vector de registros y otra agregaralfi() que pes agregar los registros al ficheros: El code funciona mas o menos xD: el problema es que despues de agregar a una persona me aparecio:

Pedro Perez                  :18
Maria Rodriguez              :34
Ana Vergara                  :55
Ð>:0
:0
:0
Antonio Mendoza              :10

 :xD Pero hace alguito el pobre code, esta muy feo y obviamente se puede mejorar pero quiero empezar por reparar esos simbolos extraños.... Aca lo dejo:

Código
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <fstream>
  4.  
  5. using namespace std;
  6.  
  7. struct person{
  8.    char name[30];
  9.    int age;
  10. };
  11.  
  12. void extraer(person* Persona);
  13. int contar();
  14. void ordenar(person* Persona);
  15. void agregaralfi(person *Persona);
  16.  
  17. int main(int argc, char *argv[])
  18. {
  19.    int op;
  20.    do{
  21.        cout<<"1.Ingresar una persona al archivo"<<endl;
  22.        cout<<"2.Ver todas las personas del archivo"<<endl;
  23.        cout<<"3.Salir"<<endl;
  24.        cin>>op;
  25.  
  26.        if (op == 1){
  27.            person *Persona, aux;
  28.            Persona= new person [contar()+1];
  29.            cin.ignore();
  30.            cout<<"Ingrese el nombre: ";
  31.            cin.getline(aux.name,30);
  32.            cout<<"Ingrese la edad: ";
  33.            cin>>aux.age;
  34.            Persona[contar()]= aux;
  35.            agregaralfi(Persona);
  36.            delete[] Persona;
  37.        }
  38.        else if (op == 2){
  39.            person *Persona;
  40.            Persona= new person [contar()];
  41.            extraer(Persona);
  42.            for (int i=0;i<contar();i++)
  43.                cout<<Persona[i].name<<Persona[i].age<<endl;
  44.            delete[] Persona;
  45.        }
  46.        cout<<"\n\n\n";
  47.    }while (op != 3);
  48.  
  49.  
  50.  
  51.    cin.get();
  52.    return EXIT_SUCCESS;
  53. }
  54.  
  55. void extraer(person* Persona){
  56.    ifstream ent("Agenda.txt");
  57.    int c=contar();
  58.  
  59.    for (int i=0;i<c;i++){
  60.        ent.getline(Persona[i].name,31,':');
  61.        ent>>Persona[i].age;
  62.        ent.ignore();
  63.    }
  64.  
  65.    ent.close();
  66. }
  67.  
  68. int contar(){
  69.    ifstream ent("Agenda.txt");
  70.    int c=0;
  71.    while (ent) if (ent.get() == '\n') c++;
  72.    ent.close();
  73.    return c;
  74. }
  75.  
  76. void ordenar(person* Persona){
  77.    int c=contar();
  78.    for (int i=0;i<c-1;i++)
  79.        for (int j=i+1;j<c;j++)
  80.        if (Persona[i].name > Persona[j].name){
  81.            person AUX=Persona[i];
  82.            Persona[i]=Persona[j];
  83.            Persona[j]=AUX;
  84.        }
  85. }
  86.  
  87. void agregaralfi(person *Persona){
  88.    int c=contar()+1;
  89.    ofstream sal("Agenda.txt",ios::app);
  90.    for (int i=0;i<c;i++)
  91.        sal<<Persona[i].name<<':'<<Persona[i].age<<endl;
  92.    sal.close();
  93. }
  94.  

Muchas gracias littlehorse, disculpa la molestia y pes espero tu ayuda para luego si fortalecer el code...

Saludos...
En línea

"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja



Littlehorse
All the world's a stage
Moderador
***
Desconectado Desconectado

Mensajes: 2.714


Nie Dam Sie


Ver Perfil WWW
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #3 en: 27 Julio 2010, 02:28 am »

Citar
Jumm ahora me doy cuenta que toy grave  :xD  cuando getline setea el failbit las operaciones siguientes fallan? Eso no lo tengo claro, crei q setear el failbit no tenia importancia, que solo era para cuando uno quiera verificar errores y todo eso...

Si, tiene importancia. Las operaciones siguientes realizadas en ese stream fallaran hasta que se vuelva al estado normal de ese stream.

En cuanto al código, lo depuraste? tienes idea de mas o menos donde se produce el error? si sabes donde se produce la falla, especifica las lineas.
Si no encontraste la falla en la logica, prueba revisando los valores de los datos paso por paso hasta encontrar el problema.
Mañana lo miro atentamente a ver que encuentro, pero mientras prueba depurando.

Saludos!

En línea

An expert is a man who has made all the mistakes which can be made, in a very narrow field.
.:BlackCoder:.


Desconectado Desconectado

Mensajes: 388


Cada dia C++!!


Ver Perfil
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #4 en: 27 Julio 2010, 02:31 am »

Me imagino que el pedu esta en agregaralfi()... Estoy casi seguro, horita voy a comer, luego le doy y le doy otra vez  :xD ya estuve toda la tarde en eso, que me ciente otro rato no quiere decir nada... :laugh:

EDITO:

Mmmm el problema era una tonteria aca esta el code, lo hire editando poco a poco, se esperan criticas, consejos, ordenes  :xD lo que sirva:

Código
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <fstream>
  4. #include <iomanip>
  5.  
  6. using namespace std;
  7.  
  8. struct person{
  9.    char name[30];
  10.    int age;
  11. };
  12.  
  13. void extraer(person* Persona);
  14. int contar();
  15. void ordenar(person* Persona);
  16. void agregaralfi(person *Persona);
  17.  
  18. int main()
  19. {
  20.    int op;
  21.    do{
  22.        cout<<"1.Ingresar una persona al archivo"<<endl;
  23.        cout<<"2.Ver todas las personas del archivo"<<endl;
  24.        cout<<"3.Salir"<<endl;
  25.        cin>>op;
  26.  
  27.        if (op == 1){
  28.            person *Persona, aux;
  29.            Persona= new person [contar()+1];
  30.            cin.ignore();
  31.            cout<<"Ingrese el nombre: ";
  32.            cin.getline(aux.name,30);  //Aca lee los 30-1 caracteres y no hay problemas...
  33.            cout<<"Ingrese la edad: ";
  34.            cin>>aux.age;                  //con esta lectura con cin, no dices que al leer los 30-1 caracteres habran errores?
  35.            extraer(Persona);      //Me faltaba esto por eso mostraba esas loqueras
  36.            Persona[contar()]= aux;
  37.            agregaralfi(Persona);
  38.            delete[] Persona;
  39.        }
  40.        else if (op == 2){
  41.            person *Persona;
  42.            Persona= new person [contar()];
  43.            extraer(Persona);
  44.            for (int i=0;i<contar();i++){
  45.                cout<<Persona[i].name<<Persona[i].age<<endl;
  46.                cout<<strlen(Persona[i].name)<<endl;}
  47.            delete[] Persona;
  48.        }
  49.        cout<<"\n\n\n";
  50.    }while (op != 3);
  51.  
  52.  
  53.  
  54.    system("PAUSE");
  55.    return EXIT_SUCCESS;
  56. }
  57.  
  58. void extraer(person* Persona){
  59.    ifstream ent("Agenda.txt");
  60.    int c=contar();
  61.  
  62.    for (int i=0;i<c;i++){
  63.        ent.getline(Persona[i].name,30,':');
  64.        ent>>Persona[i].age;
  65.        ent.ignore();
  66.    }
  67.  
  68.    ent.close();
  69. }
  70.  
  71. int contar(){
  72.    ifstream ent("Agenda.txt");
  73.    int c=0;
  74.    while (ent) if (ent.get() == '\n') c++;
  75.    ent.close();
  76.    return c;
  77. }
  78.  
  79. void ordenar(person* Persona){
  80.    int c=contar();
  81.    for (int i=0;i<c-1;i++)
  82.        for (int j=i+1;j<c;j++)
  83.        if (Persona[i].name > Persona[j].name){
  84.            person AUX=Persona[i];
  85.            Persona[i]=Persona[j];
  86.            Persona[j]=AUX;
  87.        }
  88. }
  89.  
  90. void agregaralfi(person *Persona){
  91.    int c=contar()+1;
  92.    ofstream sal("Agenda.txt",ios::app);
  93.    for (int i=0;i<c;i++)
  94.        sal<<setiosflags(ios::left)<<setw(29)<<Persona[i].name<<':'<<Persona[i].age<<endl;
  95.    sal.close();
  96. }
  97.  

Saludos...
« Última modificación: 27 Julio 2010, 03:58 am por .:BlackCoder:. » En línea

"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja



leogtz
. . .. ... ..... ........ ............. .....................
Colaborador
***
Desconectado Desconectado

Mensajes: 3.069


/^$/


Ver Perfil WWW
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #5 en: 27 Julio 2010, 03:54 am »

Si tu programa no va a tener soporte para línea de comandos no tiene caso que utilices (argc y argv), es como declarar variables y no usarlas.
En línea

Código
  1. (( 1 / 0 )) &> /dev/null || {
  2. echo -e "stderrrrrrrrrrrrrrrrrrr";
  3. }
  4.  
http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com
.:BlackCoder:.


Desconectado Desconectado

Mensajes: 388


Cada dia C++!!


Ver Perfil
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #6 en: 27 Julio 2010, 03:59 am »

Ok... Algo mas? Ya modifique un par de cosas, como por ejemplo le agregue un manipulador para darle formato sin tener que precionar espacios  :xD Luego le agrego un par de funciones...

Saludos...
En línea

"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja



leogtz
. . .. ... ..... ........ ............. .....................
Colaborador
***
Desconectado Desconectado

Mensajes: 3.069


/^$/


Ver Perfil WWW
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #7 en: 27 Julio 2010, 04:16 am »

No uses system(), y menos para una tarea irrelevante como pausar el programa, utiliza algo como cin.get()

Un buen hábito de programación es declarar las clases o estructuras empezando con mayúscula.

Estás usando C++ pero de manera estructurada, podrías usar un poco de POO y las funciones que usas hacerlas funciones miembro de la clase.
« Última modificación: 27 Julio 2010, 04:21 am por Leo Gutiérrez. » En línea

Código
  1. (( 1 / 0 )) &> /dev/null || {
  2. echo -e "stderrrrrrrrrrrrrrrrrrr";
  3. }
  4.  
http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com
.:BlackCoder:.


Desconectado Desconectado

Mensajes: 388


Cada dia C++!!


Ver Perfil
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #8 en: 27 Julio 2010, 04:26 am »

La verdad que aunque me gusta C++ no soy bueno con la POO  :xD pero voy a intentarlo... y lo de los nombre ya lo sabia pero todo empezo desde una cadena person  :xD Ya voy a ver si hago algo orientado a objetos... aunque como es que vas a meter esas funciones como miembros? tu pensaste en que person sea una struct miembro de una clase? o que la clase sea person?...

Saludos
En línea

"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja



leogtz
. . .. ... ..... ........ ............. .....................
Colaborador
***
Desconectado Desconectado

Mensajes: 3.069


/^$/


Ver Perfil WWW
Re: PROBLEMA con la funcion miembro getline() e ignore()
« Respuesta #9 en: 27 Julio 2010, 04:29 am »

No, no me di a entender.

Yo crearía una clase llamada Agenda, y apartir de ahí agregar sus funciones miembro como:

extraer
contar
ordenar

Etc, etc.
En línea

Código
  1. (( 1 / 0 )) &> /dev/null || {
  2. echo -e "stderrrrrrrrrrrrrrrrrrr";
  3. }
  4.  
http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines