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

 

 


Tema destacado: Recuerda que debes registrarte en el foro para poder participar (preguntar y responder)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema con manejo de archivos en C++
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con manejo de archivos en C++  (Leído 3,072 veces)
placa4

Desconectado Desconectado

Mensajes: 11


Ver Perfil
Problema con manejo de archivos en C++
« en: 12 Marzo 2013, 07:39 am »

Hola, resulta que estaba creando un programa que lea de un archivo de texto con el siguiente formato:
Código:
<pregunta> esta es la pregunta </pregunta> <respuesta> esta es la respuesta a la pregunta </respuesta>

Así pudiera guardar la pregunta en una cadena, y luego la respuesta en otra. De esta manera el programa iría haciendo las preguntas aleatoriamente y luego mostrando las respuestas, pero tengo un problema. La clase ifstream no la sé usar y siempre me trata una entrada más de la que quiero, lo que me hace tener que usar de forma rara el número de preguntas (restándole uno porque si no usa una entrada vacía de los arrays), ¿alguien me puede decir a qué se debe? Pongo el code completo:

main.cpp
Código
  1. #include <iostream>
  2. #include <fstream>
  3. #include "pregunta.h"
  4.  
  5. using namespace std;
  6.  
  7. int main()
  8. {
  9.    Pregunta p;
  10.    p.comenzar();
  11.  
  12.    return 0;
  13. }
  14.  
pregunta.h
Código
  1. #include <iostream>
  2. #include <fstream>
  3.  
  4. #define MAX_LETRAS 5000
  5. #define MAX_PREGUNTAS 200
  6.  
  7. class Pregunta{
  8.    private:
  9.        char pregunta[MAX_PREGUNTAS][MAX_LETRAS];
  10.        char respuesta[MAX_PREGUNTAS][MAX_LETRAS];
  11.        int nPreguntas;
  12.    public:
  13.        Pregunta();
  14.        void comenzar();
  15.        void auxMuestra();
  16. };
  17.  
pregunta.cpp
Código
  1. #include "pregunta.h"
  2. #include <stdlib.h> //Pseudorandomizado y limpiar la pantalla
  3. #include <time.h> //Para la semilla de randomizacion
  4.  
  5. using namespace std;
  6.  
  7. //Constructor
  8. Pregunta::Pregunta(){
  9.    char aux[MAX_LETRAS];
  10.    nPreguntas = 0;
  11.    ifstream archivo;
  12.    archivo.open("preguntas.txt",ifstream::in);
  13.  
  14.    while(!archivo.eof()){
  15.        //PREGUNTA
  16.        //Comida de etiqueta <pregunta>
  17.        archivo.getline(aux, MAX_LETRAS, '>');
  18.        //Adquirir el texto de la pregunta
  19.        archivo.getline(pregunta[nPreguntas], MAX_LETRAS, '<');
  20.        //Comida de etiqueta </pregunta>
  21.        archivo.getline(aux, MAX_LETRAS, '>');
  22.        //RESPUESTA
  23.        //Comida de etiqueta <respuesta>
  24.        archivo.getline(aux, MAX_LETRAS, '>');
  25.        //Adquirir el texto de la respuesta
  26.        archivo.getline(respuesta[nPreguntas], MAX_LETRAS, '<');
  27.        //Comida de etiqueta </respuesta>
  28.        archivo.getline(aux, MAX_LETRAS, '>');
  29.        nPreguntas++;
  30.    }
  31.  
  32.    archivo.close();
  33. }
  34.  
  35. void Pregunta::comenzar(){
  36.    srand (time(NULL));
  37.    while(true){
  38.        int aleatorio = rand() % (nPreguntas-1);
  39.        cout << "PREGUNTA: " << endl;
  40.        cout << pregunta[aleatorio];
  41.        cout << endl;
  42.        cin.get();
  43.        cout << "RESPUESTA: " << endl;
  44.        cout << respuesta[aleatorio];
  45.        cin.get();
  46.        system("cls");
  47.    }
  48. }
  49.  
  50. void Pregunta::auxMuestra(){
  51.    for(int i=0; i < nPreguntas; i++){
  52.        cout << "PREGUNTA" << endl << pregunta[i];
  53.        cout << endl << "RESPUESTA" << endl << respuesta[i] << endl;
  54.    }
  55. }
  56.  

El problema está en el constructor de la clase Pregunta, donde se inicializa el array con preguntas y respuestas. Antes hice una traza de la variable nPreguntas y siempre coge una más de la que debe, lo que me cabrea bastante y es la razón por la que pregunto esto. Es decir, si el texto tiene 2 preguntas, nPreguntas vale 3,y así, en comenzar() fijaros que tengo que hacer módulo de nPreguntas-1 y no de nPreguntas, para que funcione correctamente.

Muchas gracias de antemano y un saludo.


« Última modificación: 13 Marzo 2013, 07:11 am por placa4 » En línea

amchacon


Desconectado Desconectado

Mensajes: 1.211



Ver Perfil
Re: Problema con manejo de archivos en C++
« Respuesta #1 en: 12 Marzo 2013, 15:57 pm »

Oh, es un pequeño fallo de concepto que tiene iostream.

Veras, la bandera eof se activa cuando se accede fuera del archivo. Si tu tienes 4 preguntas, leera las 4 preguntas y hará otra vuelta más porque aún no has sobrepasado el final de archivo

Hay dos soluciones:

- La chapucera, consiste en disminuir en 1 el numero de preguntas.
- Obtener el tamaño del archivo.txt y leer dicha cantidad de bytes.

La segunda se podría implementar de la siguiente forma:

Código
  1. const unsigned int MAXIMO_BUFFER = 1048576; // Tamanyo máximo que podemos cargar en la RAM, he puesto aproximadamente 1 MB pero podríamos poner más
  2.  
  3. ifstream archivo;
  4. archivo.open("preguntas.txt",ifstream::in); // Desconozco si funciona en este modo, supongo que sí
  5. archivo.seekg(0,ios::end); // Nos vamos al final del archivo
  6. unsigned int Tamanyo = Lectura.tellg(); // Lee la posicion actual
  7. Lectura.seekg(0,ios::beg); // Volvemos al principio
  8.  
  9. if (Tamanyo <= MAXIMO_BUFFER)
  10. {
  11.     char* Buffer = new char[Tamanyo];
  12.     archivo.read(Buffer,Tamanyo); // Leemos el archivo del tiron
  13.  
  14.     // Tenemos el archivo ya entero cargado, solo tendremos que acceder a la cadena Buffer y sacar las preguntas.
  15.  
  16. }
  17. else // El tamanyo es excesivo, lo leeremos poco a poco
  18.      {
  19.         while(archivo.tellg() < tamanyo) // Mientras la posicion del archivo no llegue al tamanyo maximo
  20.          {
  21.  
  22.        archivo.getline(aux, MAX_LETRAS, '>');
  23.        archivo.getline(pregunta[nPreguntas], MAX_LETRAS, '<');
  24.        archivo.getline(aux, MAX_LETRAS, '>');
  25.        archivo.getline(aux, MAX_LETRAS, '>');
  26.        archivo.getline(respuesta[nPreguntas], MAX_LETRAS, '<');
  27.        archivo.getline(aux, MAX_LETRAS, '>');
  28.        nPreguntas++;
  29.         }
  30.       }
  31.  

El if es opcional, solo sería para que los archivos pequeños cargasen más rápido. Se podría dejar solo con el else.

Por cierto si usas la clase string combinada con la clase vector, podrás leer cualquier numero de preguntas con cualquier numero de letras:

Código
  1. #include <iostream>
  2. #include <fstream>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. class Pregunta{
  8.    private:
  9.        vector<string> preguntas;
  10.        vector<string> respuestas;
  11.        int nPreguntas;
  12.    public:
  13.        Pregunta();
  14.        void comenzar();
  15.        void auxMuestra();
  16. };

Código
  1.         while(archivo.tellg() < tamanyo) // Mientras la posicion del archivo no llegue al tamanyo maximo
  2.          {
  3.       preguntas.push_back(0); // Creamos un nuevo elemento vacio en el vector
  4.       respuestas.push_back(0);
  5.        archivo.getline(aux, MAX_LETRAS, '>');
  6.        archivo.getline(pregunta[nPreguntas], MAX_LETRAS, '<');
  7.        archivo.getline(aux, MAX_LETRAS, '>');
  8.        archivo.getline(aux, MAX_LETRAS, '>');
  9.        archivo.getline(respuesta[nPreguntas], MAX_LETRAS, '<');
  10.        archivo.getline(aux, MAX_LETRAS, '>');
  11.        nPreguntas++;
  12.         }
  13.  
  14.  

Para más información sobre las clases string y vector:
http://www.cplusplus.com/reference/string/string/
http://www.cplusplus.com/reference/vector/vector/


« Última modificación: 12 Marzo 2013, 16:00 pm por amchacon » En línea

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar
rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Problema con manejo de archivos en C++
« Respuesta #2 en: 12 Marzo 2013, 16:33 pm »

Ya que piensa usar etiquetas en lugar de lineas para separar las preguntas y respuestas me parece mas sencillo utilizar solo un objeto de la clase string para almacenar todo el contenido del archivo. Mas o menos así:
Código
  1. ifstream in("Entrada.txt", ifstream::in);
  2. string texto;
  3. string linea;
  4.  
  5. while (getline(in, linea))
  6.   texto += linea + '\n';
  7.  
  8. cout << texto;
  9. in.close();

Y para encontrar las etiquetas de apertura y cierre puede utilizar la función miembro std::string::find.

Un saludo
En línea

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
placa4

Desconectado Desconectado

Mensajes: 11


Ver Perfil
Re: Problema con manejo de archivos en C++
« Respuesta #3 en: 13 Marzo 2013, 07:08 am »

Aaah bonitas ideas amchacon. Claro usando vector es cierto podría hacerlo sin límite de antemano, no lo había pensado.

Y muchas gracias por aclarármelo ^_^, claro vigilando a mano el tamaño de los bytes es algo análogo a si eof (si es que funcionara como a mí me gustaría ¬¬) devolviera true al llegar al final del archivo y no al sobrepasarlo, perfecto =)

Y en cuanto a rir3760 muchas gracias, es también una buena idea, pero no uso etiquetas por capricho, verás yo lo hice con la idea de que las preguntas y respuestas pudieran tener por dentro saltos de línea, párrafos etc. no fueran simples preguntas de un renglón, solo fue por eso, pero muchas gracias =)

Un saludo a los dos.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
problema con el manejo de archivos
PHP
darkxxx 2 1,925 Último mensaje 9 Octubre 2007, 23:44 pm
por Ertai
Manejo de Archivos duda! « 1 2 3 »
Programación C/C++
Mr.Blue 20 9,276 Último mensaje 13 Mayo 2010, 05:03 am
por leogtz
Manejo de Archivos - PROBLEMA!!!
Programación C/C++
clodan 3 2,796 Último mensaje 14 Octubre 2010, 18:34 pm
por Horricreu
Manejo de archivos (SetAttr)
Programación Visual Basic
CAR3S? 3 2,450 Último mensaje 5 Febrero 2011, 20:16 pm
por BlackZeroX
problema con manejo de nodos en linux
Programación C/C++
abaadoon 2 1,462 Último mensaje 12 Febrero 2016, 04:19 am
por abaadoon
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines