| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
Neodivert
Registrado: 20 Ago 2004 Mensajes: 60
| Publicado: 31/08/2007 4:53 am | | | Título: Punteros char y archivos |
| Lenguaje: C++ Compilador: Dev-C++
Buenas, estaba haciendo un programa para hacer cuestionarios tipo test y otro para leerlos, y al leerlos y ver las preguntas siempre se cortaban a la mitad y con caracteres extraños. Intente hacer una prueba con un programa pequeño.
Si lo hago con cadenas "normales" funciona perfectamente:
Escribe.cpp
| Código: | #include<cstring> #include<fstream> #include<iostream> using namespace std;
int main(){ char Pregunta[10][31]; for(int i=0; i<10; i++){ strcpy(Pregunta[i], "HOLA CAPULLO"); } ofstream Archivo( "Archivo.tc", ios::binary ); for(int i=0; i<10; i++){ Archivo.write( Pregunta[i], sizeof(Pregunta[i]) ); Archivo.clear(); } Archivo.clear(); Archivo.close(); } |
Lee.cpp
| Código: | #include<cstring> #include<fstream> #include<iostream> using namespace std;
int main(){ char Pregunta[10][31]; ifstream Archivo( "Archivo.tc", ios::binary ); for(int i=0; i<10; i++){ Archivo.clear(); Archivo.read( Pregunta[i], sizeof(Pregunta[i]) ); cout << "Pregunta[" << i << "]: " << Pregunta[i] << endl; } Archivo.clear(); Archivo.close(); cin.get(); } |
De esta forma los lee perfectamente, pero a la hora de hacerlo con punteros y reservando memoria para las cadenas, parece que los escribe bien pero luego al leer arroja otros resultados.
Escribe.cpp
| Código: | #include<cstring> #include<fstream> #include<iostream> using namespace std;
int main(){ char **Pregunta = new char *[10]; for(int i=0; i<10; i++){ Pregunta[i] = new char [31]; strcpy(Pregunta[i], "HOLA CAPULLO"); } ofstream Archivo( "Archivo.tc", ios::binary ); for(int i=0; i<10; i++){ Archivo.write( Pregunta[i], sizeof(Pregunta[i]) ); Archivo.clear(); } Archivo.clear(); Archivo.close(); for(int i=0; i<10; i++) delete Pregunta[i]; delete Pregunta; }
|
Lee.cpp
| Código: | #include<cstring> #include<fstream> #include<iostream> using namespace std;
int main(){ char **Pregunta = new char *[10]; ifstream Archivo( "Archivo.tc", ios::binary ); for(int i=0; i<10; i++){ Pregunta[i] = new char [31]; Archivo.clear(); Archivo.read( Pregunta[i], sizeof(Pregunta[i]) ); cout << "Pregunta[" << i << "]: " << Pregunta[i] << endl; } Archivo.clear(); Archivo.close(); for(int i=0; i<10; i++) delete Pregunta[i]; delete Pregunta; cin.get(); } |
Los resultados son más o menos así:
| Código: | HOLAX(Carita sonriente)= HOLAX(Carita sonriente)= HOLAX(Carita sonriente)= HOLAX(Carita sonriente)= HOLAP(Figurita)= HOLAH(Figurita)= HOLA (Figurita)=
|
Y no entiendo por que puede ser. ¿No se supone que al guardar el puntero guardo toda la cadena por la equivalencia puntero = array? :S
P.D. Ésto no tiene nada que ver con el problema del post, pero en el mismo Dev-C++ puedo usar las funciones de la libreria "cstring" sin linkearla y no me dice nada (Aunque siempre la pongo por si acaso), ¿es algo que tengo que configurar en alguna parte? |
| | Volver arriba | |  | rir3760

Registrado: 01 Oct 2004 Mensajes: 3657 Ubicación: Mexico
| Publicado: 31/08/2007 7:22 am | | | Título: Re: Punteros char y archivos |
| | Neodivert escribió: | | pero a la hora de hacerlo con punteros y reservando memoria para las cadenas, parece que los escribe bien pero luego al leer arroja otros resultados. |
El problema es la forma en que manejas el operador sizeof, este devuelve el tamaño en caracteres de un objeto, en el caso de un array no hay problema pero si, como es el caso con tu programa, intentas utilizarlo con un puntero te devolvera el tamaño del objeto (en este caso el puntero) sin importar a donde apunte este.
| Neodivert escribió: | | P.D. Ésto no tiene nada que ver con el problema del post, pero en el mismo Dev-C++ puedo usar las funciones de la libreria "cstring" sin linkearla y no me dice nada (Aunque siempre la pongo por si acaso), ¿es algo que tengo que configurar en alguna parte? |
La vinculacion depende del compilador que se utilize, por ejemplo en el caso de GCC este requiere que la biblioteca math (C estandar) se vincule explicitamente mediante una opcion de linea de comandos.
Un saludo _________________ The capacity to learn is a gift; The ability to learn is a skill; The willingness to learn is a choice. -- Rebec of Ginaz |
| | Volver arriba | |  | Neodivert
Registrado: 20 Ago 2004 Mensajes: 60
| | | Volver arriba | |  | | rir3760

Registrado: 01 Oct 2004 Mensajes: 3657 Ubicación: Mexico
| Publicado: 31/08/2007 6:34 pm | | | Título: |
| Respuesta corta: si estas aprendiendo C++ utiliza las caracteristicas que este ofrece como las clases string y vector.
Respuesta larga: el tamaño del puntero no importa, en realidad si utilizas un valor fijo (un "magic number") como 4 tu programa no funcionaria correctamente en sistemas donde el tamaño de un "char *" es menor.
Y si lo piensas un poco no es necesario incluir una division cuyo resultado sea uno ya que toda multiplicacion por ese numero arroja como resultado ...
Un saludo _________________ The capacity to learn is a gift; The ability to learn is a skill; The willingness to learn is a choice. -- Rebec of Ginaz |
| | Volver arriba | |  | Neodivert
Registrado: 20 Ago 2004 Mensajes: 60
| Publicado: 02/09/2007 3:31 am | | | Título: |
| | rir3760 escribió: | Respuesta corta: si estas aprendiendo C++ utiliza las caracteristicas que este ofrece como las clases string y vector.
Respuesta larga: el tamaño del puntero no importa, en realidad si utilizas un valor fijo (un "magic number") como 4 tu programa no funcionaria correctamente en sistemas donde el tamaño de un "char *" es menor.
Y si lo piensas un poco no es necesario incluir una division cuyo resultado sea uno ya que toda multiplicacion por ese numero arroja como resultado ...
Un saludo |
owned! 
Entonces usaré.
| Código: | Archivo.read( Pregunta[i], sizeof(char)*31 ); |
Estudiaré mejor la clase string para mis próximos programas, aunque (Y esto es un poco pijada xD ), he estado viendo que no se puede definir de un tamaño concreto sin tener que declararlo, tipo
| Código: | string Cadena(30); |
sino
| Código: | string Cadena(30, '\000'); |
xD Bueno, lo dicho, muchas gracias rir3760, salvador de los novatos.  |
| | Volver arriba | |  | rir3760

Registrado: 01 Oct 2004 Mensajes: 3657 Ubicación: Mexico
| Publicado: 05/09/2007 9:46 am | | | Título: |
| | Neodivert escribió: | Entonces usaré.
| Código: | Archivo.read( Pregunta[i], sizeof(char)*31 ); |
|
Tanto en C como en C++ el resultado de sizeof(char) siempre es uno asi que puedes reducir esa sentencia a:
| Código: | Archivo.read( Pregunta[i], 31); |
Como te comente antes utilizar "magic numbers" como 31 no es una buena idea, en C++ lo apropiado es declarar constantes utilizando la palabra reservada const.
| Neodivert escribió: | Estudiaré mejor la clase string para mis próximos programas, aunque (Y esto es un poco pijada xD ), he estado viendo que no se puede definir de un tamaño concreto sin tener que declararlo, tipo
| Código: | string Cadena(30); |
sino
| Código: | string Cadena(30, '\000'); |
|
No te entiendo muy bien, el objeto de tipo string lo puedes declarar sin indicar el tamaño y su contenido:
| Código: | std::string Cadena; |
Y a partir de ese momento te olvidas de ciertas tareas engorrosas que uno debe tener siempre en cuenta en C como es la capacidad del bloque y tener (mediante realloc) que reajustarlo cuando sea necesario.
Un saludo _________________ The capacity to learn is a gift; The ability to learn is a skill; The willingness to learn is a choice. -- Rebec of Ginaz |
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |