Problema guardando 2d arrays en binarios

Iniciado por julianbesso1, 5 Agosto 2014, 05:08 AM

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

julianbesso1

Hola a todos. Nuevamente con un problema. Me pidieron que realice una sopa de letras que brinde la posibilidad de guardar la partida para retomar en otro momento. Es aquí donde fallo. No estoy muy seguro del código correspondiente a write y read (líneas 203 y 251 respectivamente)

Código (cpp) [Seleccionar]
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <conio2.h>
#include <ctime>
#include <stdlib.h>
#include <windows.h>
#include <ctype.h>

using namespace std;

void imprimir_sopa(char x[20][20]);
void imprimir_indices();
void imprimir_encontradas(int x[5][4], char y[5][21]);
void marcar_palabra(int x[5][4], char y[5][21]);
void victoria(char w[20][20], int x[5][4], char y[5][21]);

int main(int argc, char *argv[]) {
   
   int cont=0;   
   char c;
   
   int lista_found=0;
   char lista[5][21];
   bool s;
   
   char sopa[20][20];  //declaración e inicialización los elementos de la sopa con '?'
   
   int sopa_found=0, posx, posy, dir1, registro[5][3];  //contador de palabras encontradas, posiciones X e Y de las iniciales, dir1=hor/ver/diag, 
   bool t;                                      //registro de TODAS las palabras de la lista
   
   char alphabet[27]={"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
   
   int found[5][4];  //declaración e inicialización del registro de las palabras que son encontradas (posx, posy, dir1, strlen)
   
   int d, dir2, palabras_found=0;
   int posx2, posy2;
   
   char g;   
   
   while(g!='3'){
     
      textcolor(LIGHTRED);
      cout<<"BIENVENIDO A LA SOPA DE LETRAS"<<endl<<endl;
      textcolor(WHITE);
      cout<<"Elija una opci\242n"<<endl<<endl;
      cout<<"1) Partida nueva"<<endl;
      cout<<"2) Continuar con la \243ltima partida guardada"<<endl;
      cout<<"3) Salir"<<endl<<endl;
     
      g=getch();
     
      if(g=='1'){         
         
         ifstream entrada("listado de palabras.txt", ios::in);
         
         while (entrada.good()){  //leer cantidad de veces que aparece '\n' en el txt     
            c = entrada.get();
            if (c=='\n')cont++;
         }     
         entrada.close(); //si se accede manualmente al archivo .txt se debe ingresar la última palabra de la lista acompañado de \n.
         //caso contrario el código detectará una palabra de menos
         char** q=new char*[cont];
         
         for(int f=0; f<cont; f++){
            q[f]=new char[21];     
         }
         
         entrada.open("listado de palabras.txt", ios::in);
         
         for(int g=0; g<cont; g++){
            entrada.getline(q[g], 20);
            strupr(q[g]);
         }
         
         entrada.close();         
         
         srand(time(NULL));
         
         while(lista_found<5){  //asignación de las palabras aleatorias (5)
            s=true;
            int a=rand()%cont;
            for(int j=0; j<5; j++){
               if(strcmp(q[a],lista[j])==0){
                  s=false;
                  break;
               }
            }     
            if(s==true){
               strcpy(lista[lista_found],q[a]);
               lista_found++;
            }
            Sleep(1000);
         }
         
         for(int r=0; r<cont; r++){
            delete[] q[r];   
         }
         
         delete[] q;         
         
         for(int k=0; k<20; k++){
            for(int l=0; l<20; l++){
               sopa[k][l]='?';
            }   
         }         
         
         while(sopa_found<5){  //inserción de palabras
           
            posx=rand()%20;
            posy=rand()%20;
            dir1=rand()%3+1;
           
            if(dir1==1){  //horizontal
               if(posy+strlen(lista[sopa_found])<=20){
                  t=true;
                  for(int m=posy; m<posy+strlen(lista[sopa_found]); m++){
                     if(sopa[posx][m]!='?'){
                        t=false;
                        break;
                     }               
                  }
                  if(t==true){
                     registro[sopa_found][0]=posy+1;
                     registro[sopa_found][1]=posx+1;
                     registro[sopa_found][2]=dir1;
                     for(int n=0; n<strlen(lista[sopa_found]); n++){
                        sopa[posx][posy]=lista[sopa_found][n];
                        posy++;
                     }           
                     sopa_found++;
                  }
               }
            }
            if(dir1==2){  //vertical
               if(posx+strlen(lista[sopa_found])<=20){
                  t=true;
                  for(int o=posx; o<posx+strlen(lista[sopa_found]); o++){
                     if(sopa

    [posy]!='?'){

                        t=false;
                        break;
                     }               
                  }
                  if(t==true){
                     registro[sopa_found][0]=posy+1;
                     registro[sopa_found][1]=posx+1;
                     registro[sopa_found][2]=dir1;
                     for(int p=0; p<strlen(lista[sopa_found]); p++){
                        sopa[posx][posy]=lista[sopa_found][p];
                        posx++;
                     }
                     sopa_found++;
                  }
               }         
            }
            if(dir1==3){  //diagonal
               if(posx+strlen(lista[sopa_found])<=20&&posy+strlen(lista[sopa_found])<=20){
                  t=true;
                  for(int q=posx, r=posy; q<posx+strlen(lista[sopa_found]); q++, r++){
                     if(sopa[q][r]!='?'){
                        t=false;
                        break;
                     }               
                  }
                  if(t==true){
                     registro[sopa_found][0]=posy+1;
                     registro[sopa_found][1]=posx+1;
                     registro[sopa_found][2]=dir1;
                     for(int s=posx, t=posy, u=0; s<posx+strlen(lista[sopa_found]); s++, t++, u++){
                        sopa[t]=lista[sopa_found];
                     }
                     sopa_found++;
                  }
               }
            }
         }         
         
         for(int v=0; v<20; v++){  //relleno de los elementos restantes
            for(int w=0; w<20; w++){
               if(sopa[v][w]=='?'){
                  int a=rand()%26;
                  sopa[v][w] = alphabet[a];
               }
            }
         }     
         
         for(int x=0; x<5; x++){
            for(int y=0; y<4; y++){
               if(y!=3)found

    [y]=100;

               else found

    [y]=strlen(lista
    );

            }
         }
         
      }
     
      if(g=='1'||g=='2'){
         
         fstream arch;
         
         if(g=='2'){
           
            arch.open("sopa saved.dat", ios::binary);
           
            arch.read(sopa[0], 20*20*sizeof(sopa));
           
            arch.read((char *)found[0], 5*4*sizeof(found));
           
            arch.read(lista[0], 5*21*sizeof(lista));
           
            arch.read((char *)palabras_found,sizeof(palabras_found));
           
            arch.close();
           
         }
         
         clrscr();   
         
         while(palabras_found<5){
           
            int w;
           
            clrscr();
           
            textcolor(LIGHTRED);
            gotoxy(6,1);
            cout<<"BIENVENIDO A LA SOPA DE LETRAS"<<endl<<endl;
           
            imprimir_sopa(sopa);
            imprimir_indices();
            imprimir_encontradas(found, lista);
            marcar_palabra(found, lista);
           
            gotoxy(1,26);
            cout<<"Tienes que encontrar las siguientes palabras:"<<endl<<endl;
           
            for(int i=0; i<5; i++){
               cout<<i+1<<" - ";
               puts(lista);
            }
           
            cout<<"\n(Nota: Las dimensiones de la sopa son 20x20)"<<endl<<endl;     
            cout<<"Buscar palabra No.: ";
            textcolor(YELLOW);
            cout<<"(Save

    Exit [6]) ";

            textcolor(WHITE);
            cin>>d;
           
            if(d==0){
               
               arch.open("sopa saved.dat", ios::binary);
               
               arch.write(sopa[0], 20*20*sizeof(sopa));
               
               arch.write((char *)found[0], 5*4*sizeof(found));
               
               arch.write(lista[0], 5*21*sizeof(lista));
               
               arch.write((char *)palabras_found,sizeof(palabras_found));
               
               arch.close();
               
               gotoxy(1,36);
               textcolor(LIGHTMAGENTA);
               cout<<"(Partida guardada)                       ";
               //textcolor(WHITE);
               Sleep(2000);
               clrscr();     
               
            }   
            if(d!=0){
               
               if(d==6){
                  clrscr();
                  break;
               }
               
               else{
                  cout<<endl;
                  cout<<"Coordenada 'X' de la inicial: ";
                  cin>>posx2;;
                  cout<<"Coordenada 'Y' de la inicial: ";
                  cin>>posy2;
                  cout<<"Horizontal [1] Vertical [2] Diagonal [3] ? ";
                  cin>>dir2;
                 
                  w=d-1;     
                 
                  if(posx2==registro[w][0]&&posy2==registro[w][1]&&dir2==registro[w][2]){
                     textcolor(LIGHTGREEN);
                     cout<<"\nExcelente! La has adivinado";
                     for(int i=0; i<3; i++){
                        found[w]=registro[w];
                     }
                     Sleep(2000);
                     marcar_palabra(found, lista);
                     palabras_found++;
                     textcolor(WHITE);
                  }
                  else {
                     textcolor(LIGHTRED);
                     cout<<"\nIncorrecto... Intenta otra vez!";
                     Sleep(2000);
                     textcolor(WHITE);
                  }
                 
               }
            }
         }
         
         if(palabras_found==4) victoria(sopa, found, lista);           
         
      }     
     
   }
   
   clrscr();
   cout<<"FIN";
   
   return 0;
   
   
}

void imprimir_sopa(char x[20][20]){
   
   textcolor(WHITE);
   
   for(int i=0; i<20; i++){
      for(int j=0; j<20; j++){
         cout<<" ";
         cout<<x[j];
         if(j==19) cout<<endl;
      }   
   }
}

void imprimir_indices(){
   
   textcolor(YELLOW);
   
   gotoxy(2,24);  //eje X
   for(int i=0; i<20; i++){
      cout<<i+1;
      if(i<9) cout<<" ";
   }
   gotoxy(43,3);  //eje Y (puede omitirse)
   int h=0;
   for(int j=0; j<20; j++){
      gotoxy(43,3+h);
      cout<<j+1;
      cout<<endl;     
      h++;
   }
   
   textcolor(WHITE);
   
}

void imprimir_encontradas(int x[5][4], char y[5][21]){
   
   textcolor(LIGHTMAGENTA);
   
   for(int i=0; i<5; i++){
     
      if(x

    !=100){

         
         gotoxy((x

    )*2,x[1]+2);

         
         if(x[2]==1){  //horizontal
            for(int t=0; t<x[3]; t++){
               cout<<y[t];
               cout<<" ";
            }     
         }
         if(x[2]==2){  //vertical
            int h=1;
            for(int t=0; t<x[3]; t++){
               cout<<y[t];
               gotoxy((x

    )*2,x[1]+2+h);

               h++;
            }     
         }
         if(x[2]==3){  //diagonal
            int h=1, k=2;
            for(int t=0; t<x[3]; t++){
               cout<<y[t];
               gotoxy((x

    )*2+k,x[1]+2+h);

               h++; k+=2;
               
            }     
         }
         
      }
   }
   
   textcolor(WHITE);
}

void marcar_palabra(int x[5][4], char y[5][21]){ 
   
   textcolor(LIGHTMAGENTA);
   
   for(int i=0; i<5; i++){
      if(x

    !=100){

         gotoxy(6+x[3],28+i);
         cout<<"X";
      }
   }
   
   textcolor(WHITE);
}

void victoria(char w[20][20], int x[5][4], char y[5][21]){
   
   clrscr();
   
   gotoxy(6,1);
   textcolor(LIGHTRED);
   cout<<"BIENVENIDO A LA SOPA DE LETRAS"<<endl<<endl;
   
   imprimir_sopa(w);
   imprimir_encontradas(x, y);
   
   gotoxy(3,24);
   textcolor(LIGHTGREEN);
   cout<<"Felicitaciones! Has adivinado todas!"<<endl;
   textcolor(WHITE);
   
}


No entiendo por qué aparecen lineas horizontales dentro del código... Qué debo hacer para hacerlo visible? Gracias de antemano. Saludos!




Ahora si :)

eferion

Cita de: julianbesso1 en  5 Agosto 2014, 05:08 AM
No entiendo por qué aparecen lineas horizontales dentro del código... Qué debo hacer para hacerlo visible?

Para que el código aparezca "correcto" tienes que añadirle a la etiqueta "code" el lenguaje empleado:

code=cpp -> C++
code=c -> C
...

Si la etiquetas la dejas como "code" a secas al código se le da una interpretación que puede no ser la correcta... en tu caso [ s ] se está interpretando como texto tachado, por lo que te tacha todo lo que se encuentra entre esa etiqueta y la de cierre... que como no hay te tacha hasta el final del código.

Cita de: julianbesso1 en  5 Agosto 2014, 05:08 AM
No estoy muy seguro del código correspondiente a write y read

Código (cpp) [Seleccionar]

char sopa[20][20];
arch.read(sopa[0], 20*20*sizeof(sopa));


Si sopa es un array bidimiensional... tu quieres sobreescribir dicho array al completo... ¿por qué accedes a sopa[0]? Si pretendes modificar "sopa"... el puntero que debes pasar es "sopa"... no "sopa[0]". Además, "20*20*sizeof(sopa)"... si sopa es un array de 20*20... entonces esa expresión es equivalente a "20*20*20*20*sizeof(char)"... y creo que no es tu intención leer semejante cantidad de información. Tienes que tener en cuenta que de la forma en la que has declarado el array, el compilador sabe en todo momento el tamaño de esa variable... que serán 400 bytes.

Dicho esto aquí tienes dos opciones:

Opción 1:

Código (cpp) [Seleccionar]
arch.read(sopa, sizeof(sopa));

Opción 2:

Código (cpp) [Seleccionar]
arch.read(sopa, 20*20*sizeof(char));

Yo, personalmente, prefiero la primera opción ya que si te da por cambiar el tamaño del array y te olvides de cambiar esta otra línea vas a tener errores en el código.

El resto de lecturas y escrituras presentan los mismos problemas.

Un saludo.

julianbesso1

#2
Todavía estoy con problemas. Eferion, respecto a tus respuestas:

1)
Código (cpp) [Seleccionar]
arch.read(sopa, sizeof(sopa));
2)
Código (cpp) [Seleccionar]
arch.read(sopa, 20*20*sizeof(char));

Ambas devuelven el mismo error:

no matching function for call to 'std::basic_fstream<char>::read(char[20][20], unsigned int)'

Intenté agregar (char *) de modo que quede de la siguiente manera:

Código (cpp) [Seleccionar]
arch.read((char *)sopa, sizeof(sopa));
Código (cpp) [Seleccionar]
arch.read((char *)sopa, 20*20*sizeof(char));

Lo cual "funciona", pero cuando quiero acceder al binario, me imprime en pantalla caracteres extraños...

Voy a seguir probando. Gracias!








Lo conseguí agregando la bandera ios::in y ios::out respectivamente. No sabía que eran cruciales para que pudiera escribirse o leerse un archivo.

Quedó de la siguiente manera:

Código (cpp) [Seleccionar]
arch.open("sopa saved.dat", ios::binary | ios::out);

arch.write((char *)sopa, 20*20*sizeof(char));

arch.write((char *)found, 5*4*sizeof(int));

arch.write((char *)lista, 5*21*sizeof(char));

arch.write((char *)palabras_found,sizeof(int));

arch.close();


El guardado sale perfecto, pero cuando ejecuto la opción de guardar dentro del programa este se detiene y me tira el cuadro de diálogo "sopa.exe ha dejado de funcionar" y tengo que cerrar...

Alguna solución para eso? Ya casi estoy :)

Gracias!!!


Swain

Solo por comentar, es necesario usar in, out cuando no especificas a la hora de crear el puntero

para leer ifstream para guardar ofstream, si lo creas fstream necesitas especificar a la hora de hacer el open si vas a guardar o leer.

No te serviria guardar TODO dentro de una estructura y pasarla como binario al archivo y despues leerla??


algo como



Código (cpp) [Seleccionar]


#define dir_work "archivo.dat"

struct MyFile{
         char name[80];
         char semilla[20][20];
         int random;
         bool pUp;
}dd;

bool readInfo(){
    ifstream inf(dir_work, ios::in | ios::binary);
    if(!inf){
        cout << "Archivo no existe" << endl;
        return false;
    }
    inf.read((char *)&dd,sizeof(struct MyFile));
    inf.close();
    return true;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
void saveInfo(){
    ofstream outf(dir_work, ios::out | ios::binary);
    outf.write((char *)&dd,sizeof(struct MyFile));
    outf.close();
}

int main(){

dd.random = rand() %100;

memcpy (dd.name,"Swain");

saveInfo(); // salvadira todos los datos que tengas en dd;
readInfo(); // cargaria todos los datos que tengas en el archivo a dd;




...
No me sigas.

eferion

Código (cpp) [Seleccionar]

int palabras_found=0;

// ...

arch.write((char *)palabras_found,sizeof(int));


¿por qué motivo tratas palabras_found como si fuese un puntero? Me da que no terminas de entender el significado y funcionamiento de los punteros.

En este caso concreto, "palabras_found" no es puntero, y dado que la función "write" necesita un puntero, lo que tienes que facilitarle a la función es la posición de memoria donde se encuentra "palabras_found", es decir:

Código (cpp) [Seleccionar]
arch.write((char *)&palabras_found,sizeof(int));

Lo que tu estabas almacenando antes en el fichero era guarrería... además le estabas dando al sistema operativo motivos más que suficientes para que matase tu programa por acceder a memoria que no le corresponde.