Autor
|
Tema: PROBLEMA con la funcion miembro getline() e ignore() (Leído 7,792 veces)
|
.:BlackCoder:.
Desconectado
Mensajes: 388
Cada dia C++!!
|
Wenas... no se si es por el tiempo sin programar o wtf pero tengo problemas con getline() Lo explico en el codigo: #include <cstdlib> #include <iostream> #include <fstream> using namespace std; int main(int argc, char *argv[]) { ofstream sal("Agenda.txt"); sal<<"Pedro Perez :"<<18<<endl;//Agrego un nombre y espacios sal<<"Maria Rodriguez :"<<56<<endl;//para completar 29 caracteres sal.close(); //mas el ':' ifstream ent("Agenda.txt"); int c=2; char reg[c][30]; int edad[c]; for (int i=0;ent;i++){ ent.getline(reg[i],30);//Aca deberia extraer los 29 caracteres y agregar a reg un '\0' ent.ignore();//Aca ignorar el ':' ent>>edad[i];//Pes leer la edad ent.ignore();//Ignorar el fin de linea... } cout<<reg[0]<<"T"<<edad[0]<<endl;//Mostrar tal cual como esta en el archivo cout<<reg[1]<<"T"<<edad[1]<<endl;//La T era un ':', pero lo use para ver //si conseguia el error ent.close(); system("PAUSE"); return EXIT_SUCCESS; }
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 =.= ofstream sal("Agenda.txt"); sal<<"Pedro Perez :"<<18<<endl; sal<<"Maria Rodriguez :"<<34<<endl; sal.close(); ifstream ent("Agenda.txt"); char name[2][30]; int age[2]; for (int i=0;ent;i++){ ent.getline(name[i],31,':'); cout<<name[i]; ent>>age[i]; cout<<age[i]<<endl; ent.ignore(); cout<<i<<endl; } ent.close();
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
Mensajes: 2.714
Nie Dam Sie
|
for (int i=0;ent;i++){ ent.getline(name[i],31,':'); cout<<name[i]; ent>>age[i]; cout<<age[i]<<endl; ent.ignore(); cout<<i<<endl; }
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. for (int i=0;ent;i++){ ent.getline(reg[i],30);//Aca deberia extraer los 29 caracteres y agregar a reg un '\0' //logic error. failbit set if(ent.fail())//if failbit set ent.clear();//all flags set to default =goodbit ent.ignore();//Aca ignorar el ':' ent>>edad[i];//Pes leer la edad ent.ignore();//Ignorar el fin de linea... }
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::eofMe 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
Mensajes: 388
Cada dia C++!!
|
Jumm ahora me doy cuenta que toy grave 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 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 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 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: #include <cstdlib> #include <iostream> #include <fstream> using namespace std; struct person{ char name[30]; int age; }; void extraer(person* Persona); int contar(); void ordenar(person* Persona); void agregaralfi(person *Persona); int main(int argc, char *argv[]) { int op; do{ cout<<"1.Ingresar una persona al archivo"<<endl; cout<<"2.Ver todas las personas del archivo"<<endl; cout<<"3.Salir"<<endl; cin>>op; if (op == 1){ person *Persona, aux; Persona= new person [contar()+1]; cin.ignore(); cout<<"Ingrese el nombre: "; cin.getline(aux.name,30); cout<<"Ingrese la edad: "; cin>>aux.age; Persona[contar()]= aux; agregaralfi(Persona); delete[] Persona; } else if (op == 2){ person *Persona; Persona= new person [contar()]; extraer(Persona); for (int i=0;i<contar();i++) cout<<Persona[i].name<<Persona[i].age<<endl; delete[] Persona; } cout<<"\n\n\n"; }while (op != 3); cin.get(); return EXIT_SUCCESS; } void extraer(person* Persona){ ifstream ent("Agenda.txt"); int c=contar(); for (int i=0;i<c;i++){ ent.getline(Persona[i].name,31,':'); ent>>Persona[i].age; ent.ignore(); } ent.close(); } int contar(){ ifstream ent("Agenda.txt"); int c=0; while (ent) if (ent.get() == '\n') c++; ent.close(); return c; } void ordenar(person* Persona){ int c=contar(); for (int i=0;i<c-1;i++) for (int j=i+1;j<c;j++) if (Persona[i].name > Persona[j].name){ person AUX=Persona[i]; Persona[i]=Persona[j]; Persona[j]=AUX; } } void agregaralfi(person *Persona){ int c=contar()+1; ofstream sal("Agenda.txt",ios::app); for (int i=0;i<c;i++) sal<<Persona[i].name<<':'<<Persona[i].age<<endl; sal.close(); }
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
Mensajes: 2.714
Nie Dam Sie
|
Jumm ahora me doy cuenta que toy grave 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
Mensajes: 388
Cada dia C++!!
|
Me imagino que el pedu esta en agregaralfi()... Estoy casi seguro, horita voy a comer, luego le doy y le doy otra vez ya estuve toda la tarde en eso, que me ciente otro rato no quiere decir nada... EDITO: Mmmm el problema era una tonteria aca esta el code, lo hire editando poco a poco, se esperan criticas, consejos, ordenes lo que sirva: #include <cstdlib> #include <iostream> #include <fstream> #include <iomanip> using namespace std; struct person{ char name[30]; int age; }; void extraer(person* Persona); int contar(); void ordenar(person* Persona); void agregaralfi(person *Persona); int main() { int op; do{ cout<<"1.Ingresar una persona al archivo"<<endl; cout<<"2.Ver todas las personas del archivo"<<endl; cout<<"3.Salir"<<endl; cin>>op; if (op == 1){ person *Persona, aux; Persona= new person [contar()+1]; cin.ignore(); cout<<"Ingrese el nombre: "; cin.getline(aux.name,30); //Aca lee los 30-1 caracteres y no hay problemas... cout<<"Ingrese la edad: "; cin>>aux.age; //con esta lectura con cin, no dices que al leer los 30-1 caracteres habran errores? extraer(Persona); //Me faltaba esto por eso mostraba esas loqueras Persona[contar()]= aux; agregaralfi(Persona); delete[] Persona; } else if (op == 2){ person *Persona; Persona= new person [contar()]; extraer(Persona); for (int i=0;i<contar();i++){ cout<<Persona[i].name<<Persona[i].age<<endl; cout<<strlen(Persona[i].name)<<endl;} delete[] Persona; } cout<<"\n\n\n"; }while (op != 3); system("PAUSE"); return EXIT_SUCCESS; } void extraer(person* Persona){ ifstream ent("Agenda.txt"); int c=contar(); for (int i=0;i<c;i++){ ent.getline(Persona[i].name,30,':'); ent>>Persona[i].age; ent.ignore(); } ent.close(); } int contar(){ ifstream ent("Agenda.txt"); int c=0; while (ent) if (ent.get() == '\n') c++; ent.close(); return c; } void ordenar(person* Persona){ int c=contar(); for (int i=0;i<c-1;i++) for (int j=i+1;j<c;j++) if (Persona[i].name > Persona[j].name){ person AUX=Persona[i]; Persona[i]=Persona[j]; Persona[j]=AUX; } } void agregaralfi(person *Persona){ int c=contar()+1; ofstream sal("Agenda.txt",ios::app); for (int i=0;i<c;i++) sal<<setiosflags(ios::left)<<setw(29)<<Persona[i].name<<':'<<Persona[i].age<<endl; sal.close(); }
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
Mensajes: 3.069
/^$/
|
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
|
|
|
|
.:BlackCoder:.
Desconectado
Mensajes: 388
Cada dia C++!!
|
Ok... Algo mas? Ya modifique un par de cosas, como por ejemplo le agregue un manipulador para darle formato sin tener que precionar espacios 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
Mensajes: 3.069
/^$/
|
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
|
|
|
|
.:BlackCoder:.
Desconectado
Mensajes: 388
Cada dia C++!!
|
La verdad que aunque me gusta C++ no soy bueno con la POO pero voy a intentarlo... y lo de los nombre ya lo sabia pero todo empezo desde una cadena person 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
Mensajes: 3.069
/^$/
|
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
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Ayuda! Por favor. Tengo problema con memoria dinámica en c++ y función getline
Programación C/C++
|
DeathStar92
|
0
|
2,279
|
25 Noviembre 2012, 19:56 pm
por DeathStar92
|
|
|
Problema con el delimitador de getline [SOLUCIONADO]
Programación C/C++
|
anonimo12121
|
3
|
5,416
|
1 Abril 2013, 18:13 pm
por anonimo12121
|
|
|
Necesito ayuda con Puntero a función miembro.(Solucionado)
Programación C/C++
|
anonimo12121
|
0
|
1,900
|
24 Junio 2013, 18:01 pm
por anonimo12121
|
|
|
¿Duda sobre la sobreescritura de una función miembro en una clase derivada?
Programación C/C++
|
theluigy13etv
|
3
|
4,352
|
21 Julio 2013, 19:19 pm
por theluigy13etv
|
|
|
alguna forma de pasar una funcion miembro como argumento a otro miembro de clase?
Programación C/C++
|
digimikeh
|
4
|
6,849
|
18 Abril 2022, 04:47 am
por Loretz
|
|