Estás en: Inicio >> Foros >> Informática >> Programación
Programación /

Haciendo un menu, problema con matriz dinamica bidimencional

Participa en el tema Haciendo un menu, problema con matriz dinamica bidimencional en el foro Programación.
Hola gente, me estaba haciendo un menu, queria que el menu este recibiera 2 cadenas, ...

Buscar en este tema:
 
  •  
    #1 Haciendo un menu, problema con matriz dinamica bidimencional
    Hola gente, me estaba haciendo un menu, queria que el menu este recibiera 2 cadenas, una con el titulo y otra con als opciones, como siempre hago muchos ejercicios de pruebas que usan menus, queria hacer un menu simple y generico, cosa de que luego lo hago header, lo incluyo, mando menu y opciones y listo.

    El tema esta en que, tengo un problema con la matriz dinamica o en la forma en que guardo los datos en ella, es que luego de tanto tiempo sin programar, estas vacaciones largas me hisieron mal, ya nose en donde estoy cometiendo el error.

    La cosa es media complicada, xq recibe una cadena larga con las opciones y debo cartarla y guardar las opciones en una matriz dinamica de caracteres. No se asusten si ven un error grosero.

    Código:
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int menu(char[],char[]);
    
    void main()
    {
    int i;
    char reso[51];
    i=menu("M E N U BETA\0","Generar archivo binario|Efectuar mantenimiento|Listar dados de baja|Listar los N mayores o menores|Listarlos en orden|Estadistica de ingresos|Actualizacion automatica|Depuracion|Salir\0");
    clrscr();
    printf("La opcion selecionada fue la %d",i);
    getch();
    }
    
    int menu(char id[],char cadena[])
        {
       int i,n,sel=1,cap,cant=0;
       char **opciones=NULL,*aux;
    
       opciones=(char **)malloc(30*sizeof(char *));  //NC
       *opciones=(char *)malloc(1*sizeof(char)); //NF
    
       aux=strchr(cadena,'\0');
       while(cadena)
       {
           aux=strrchr(cadena,'|');
           sscanf(aux,"|%s",&(*opciones));
          opciones++;
          *opciones=(char *)malloc(1*sizeof(char)); //NF
            *aux='\0';
          cant++;
          printf("%s",--opciones); getch();  //prueba
          opciones++;
       }
       return sel;
       }
    
    Corte bastante codigo que lo tenia comentado xq no importa ahora, la cosa es que no logro guardar bien las opciones en la matriz, siempre la matrices dinamicas bidimencionales me dieron dramas... la condicion de fin de ese while tb me persigue...
    Editado por Shivan - 13.08.2009 04:39 hs.
    +
     
    0
    Me gusta
     
    | Más
  • #2 Re: Haciendo un menu, problema con matriz dinamica bidimencional

    Estuve viendo algunas cosas que creo que no andan en tu código, pero no tengo tiempo de probar...
    Te paso una función que hice yo, que hace lo mismo. Adapté las variables para que sean iguales a las q usaste vos.
    Fijate como reservé la memoria.
    La función recibe la cadena como parámetro y la divide mediante el separador. Cada "subcadena" la guarda en una fila de la matriz. Fijate que la cantidad de filas de la matriz depende de la cantidad de opciones que reciba por parámetro.
    Igualmente talvez necesites "sacar" las opciones del menú para trabajarlas mas adelante, por eso es necesario definir afuera la matriz opciones y pasarsela como parámetro a la función (eso no está implementado).
    Sin mas, ahi va la función:
    Código:
    int iMenu(char* cadena, char cSeparador , **opciones, int cantopciones)
    {
       int i=0;
       int k=0;
       int iCont=0;
       opciones=(char**)malloc(cantopciones*sizeof(char*));
       for(i=0;i<cantopciones;i++)
       {
          opciones[i]=(char*)malloc(30);
       }
       /*opciones quedaria como la matriz opciones[cantopciones][30]*/
     
       for(i=0;i<=strlen(cadena);i++)
       {
          /*La variable cSeparador sería igual a '|'*/
          if(cadena[i]!=cSeparador && cadena[i]!='\0')
          {
             opciones[iCont][k]=cadena[i];
             k++;
          }
          if(cadena[i]==cSeparador)
          {
             iCont++;
             k=0;
          }
       }
       return 0;
    }
    
    Editado por elcordoba - 13.08.2009 08:51 hs.
    Me gusta este mensaje
  • #3 Re: Haciendo un menu, problema con matriz dinamica bidimencional

    Tiene que ser en C, o puedo mostrarte un codigo en C++?
    Me gusta este mensaje
  • #4 Re: Haciendo un menu, problema con matriz dinamica bidimencional

    Recien estaba medio de gusto y aprobeche el minuto que tenia libre y te arme esto re basico. Si queres que le ponga mas opciones me mandas un MP.

    ReyMenu.h
    Código PHP:
    #include <iostream>
    #include <string>
    #include <vector>

    using namespace std;

    class 
    ReyMenu
    {
    public:
        
    ReyMenucharTitulo )
        {
            
    this->Titulo.assign(Titulo);
        }

        ~
    ReyMenu()
        {
            for( 
    size_t i 0Elementos.size(); i++)
            {
                
    delete Elementos[i];
            }
            
    Elementos.clear();
        }

        
    size_t agregarElemento( const charNombre )
        {
            
    stringszElemento = new string(Nombre);
            
    Elementos.push_back(szElemento);

            return 
    Elementos.size();
        }

        
    size_t cantidadElementos()
        {
            return 
    Elementos.size();
        }

        
    void mostrarMenu()
        {
            if( 
    Titulo.length() )
            {
                
    printf("%s\n"Titulo.c_str());
            }

            for( 
    size_t i 0Elementos.size(); i++)
            {
                
    printf("%d) %s\n"1Elementos[i]->c_str() );
            }
        }

    private:
        
    string Titulo;
        
    vector<string *> Elementos;
    }; 
    ReyMenu.cpp // Solo Ejemplo
    Código PHP:
    #include "ReyMenu.h"

    int main()
    {
        
    ReyMenu Prueba("Mi Titulo");

        
    Prueba.agregarElemento"Primero" );
        
    Prueba.agregarElemento"Segundo" );
        
    Prueba.agregarElemento"Tercero" );

        
    Prueba.mostrarMenu();
        return 
    0;

    Me gusta este mensaje
  • #5 Re: Haciendo un menu, problema con matriz dinamica bidimencional

    Gracias pude lograr algo, no puedo usar C++ xq se muy poco de C++, entonces no se editarlo, ademas por el momento todo lo que hago es el C, asi que no.

    Bueno hise el menu pero tengo un problema, la 1era vez que corre anda bien pero a la 2da vez que se lo llama, ya hace desborde... hise un for infinito para probarlo...

    Estoy tratando de ver en donde esta el error, pero no lo encuentro, quisas tengo algo mal en la liberacion de memoria?

    Código:
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int menu(char[],int,char *,char *,char[]);
    
    void main()
    {
    int i;
    for(;;)
        {
            i=menu("M E N U BETA",5,"|","%","Opcion%1|Opcion%2|Opcion%3|Opcion%4|Opcion%5");
            clrscr();
            printf("La opcion selecionada fue la %d",i);
            getch();
        }
    }
    /*
    menu(titulo,cantidad de opciones, char separador de opciones, char indicador de blanco, cadena de opciones)
    menu("M E N U",2,"|","%","Opcion%1|Opcion%2");
    desearia que existiera un sgets...
    */
    int menu(char *titulo,int cantopciones,char *charsep,char *blanco,char *cadena)
        {
       int i,n,sel=1,cap;
       char **opciones,*aux;
    
       opciones=(char**)malloc(cantopciones*sizeof(char*)); //NC
       for(i=0;i<cantopciones;i++)
           {
              opciones[i]=(char*)malloc(50*sizeof(char)); //NF
            }
    
       //Procedo a separar y guardar
       aux=strchr(cadena,*charsep); 
       for(i=cantopciones-1;i>=0;i--)
           {
                if(i>0)
             {
                 aux=strrchr(cadena,*charsep);
                   sscanf(aux,"|%s",&(*opciones[i])
                while(aux=strchr(opciones[i],*blanco))
                        *aux=' ';
                //
                  aux=strrchr(cadena,*charsep);
                    *aux='\0';
             }
             else
             {
             strcpy(opciones[i],cadena);
             while(aux=strchr(opciones[i],*blanco))
                     *aux=' ';
             }
            }
    
       do{
          clrscr();
          textcolor(YELLOW);
          n=i=0;
          cprintf("          %s\r\n\n      Selecione una opcion\n",titulo);
             for(i=0;i<cantopciones;i++)
               {
                     printf("\n\n");
                 textbackground(BLINK);
                 if(++n==sel)
                   {
                   textcolor(WHITE);
                     cprintf("  > > >  ");
                   textbackground(CYAN);
                   cprintf("%s",opciones[i]);
                   textbackground(BLINK);
                   cprintf("  < < <  ");
                   }
                   else
                   {
                   textcolor(LIGHTGRAY);
                   cprintf("         ");
                   textbackground(BLINK);
                   cprintf("%s",opciones[i]);
                   }
              }
          cap=getch();
          textbackground(BLINK);
          if( cap==80 && sel<n )
              sel++;
          else
              if( cap==72 && sel>1 )
             sel--;
          }while(cap!='\r');
    
       for(i=0;i<cantopciones;i++)
           {
              free(opciones[i]);
            }
       free(opciones);
       
       return sel;
    }
    
    Me gusta este mensaje
  • #6 Re: Haciendo un menu, problema con matriz dinamica bidimencional

    Acá tenés un menú, con comentarios para que trates de entenderlo.
    Seguramente tendrás que debuguearlo un poco. Funciona en Turbo C.
    Código:
    #include <stdlib.h>
    #include <conio.h>
    
    /* devuelve 0 si se aprieta ESC,
       si no, el número de ítem, empezando desde 1 */
    int menu (const char *titulo, char *items,
              int attr_titulo, int attr_item, int attr_realzado,
    	  int attr_seleccion)
    {
      int y, n, i, len, itemlen, maslargo, sel, prevsel, ch,
          sale;
      char **ptrs, *msjs, *p, *q;
      int *realzadas;
    
      /* del string items cuento:
           cuántos caracteres tiene    => len
           cuántos ítems tiene         => n
           cuántos chars tiene el
             ítem más largo            => maslargo
      */
      for (n=1, len=0, itemlen=maslargo=0, p=items; *p; p++) {
        if (*p == '&') continue;
        len++;
        itemlen++;
        if (*p == '|') {
          n++;
          if (itemlen > maslargo) maslargo = itemlen;
          itemlen = 0;
        }
      }
      /* creo un arreglo de n punteros a strings (los items) */
      ptrs = (char **)malloc(n * sizeof(char *));
      /* en msjs voy a guardar los n ítems del menu */
      msjs = (char *)malloc(len+1);
      /* en realzadas, la posición del caracter realzado de c/ ítem */
      realzadas = (int *)malloc(n * sizeof(int));
    
      for (i=0; i<n; i++) realzadas[i] = -1;
    
      ptrs[0] = msjs;
      for (i=0, p=items, q=msjs; *p; p++, q++) {
        if (*p == '&') {
          realzadas[i] = q - ptrs[i];
          q--;
        }
        else if (*p == '|') {
          *q = '\0';
          ptrs[++i] = q+1;
        }
        else *q = *p;
      }
      *q = '\0';
      /* msjs quedó igual que items, pero con los '|' reemplazados
         por '\0' y sin '&'. ptrs tiene punteros a c/u de las "substrings"
         dentro de msjs */
    
      /* hago lugar en la pantalla para el menú */
      for (i=0; i<n+2; i++) {
        puts(""); clreol();
      }
      y = wherey()-1;
      /* dibujo el menú de abajo para arriba
         (es lo mismo, pero ya que tengo el cursor ahí...) */
      for (i = n-1; i >= 0; i--) {
        textattr(attr_item);
        gotoxy(2, y); cprintf("  %-*s  ", maslargo, ptrs[i]);
        if (realzadas[i] != -1) {
          textattr(attr_realzado);
          gotoxy(2 + 2 + realzadas[i], y);
          cprintf("%c", ptrs[i][realzadas[i]]);
        }
        y--;
      }
      textattr(attr_titulo); gotoxy(2, y); cprintf("%s", titulo);
    
      /* empieza la parte interactiva */
      sel = prevsel = 1;
      sale = 0;
      for (;;) {
        for (i=0; i<2; i++) {
          /* la primera vuelta (i==0) dibujo
    	 el seleccionado; la segunda, el
    	 ex-seleccionado */
          int posy;
          int nitem = (i==0 ? sel : prevsel) - 1;
          if (i==0 && sel < 1) continue;
          if (i==1 && prevsel == sel) continue;
          posy = y + nitem + 1;
          textattr( i==0 ? attr_seleccion : attr_item );
          gotoxy(2, posy); cprintf("  %-*s  ", maslargo, ptrs[nitem]);
          if (i==1 && realzadas[nitem] != -1) {
            textattr(attr_realzado);
    	gotoxy(2 + 2 + realzadas[nitem], posy);
    	cprintf("%c", ptrs[nitem][realzadas[nitem]]);
          }
        }
    
        /* corte de control acá */
        if (sale) break;
    
        prevsel = sel;
        ch = getch();
        if (ch == 0) {
          ch = getch();
          switch (ch) {
            case 72:
              if (sel > 1) sel--;
              break;
            case 80:
              if (sel < n) sel++;
              break;
          }
        }
        else {
          switch (ch) {
            case 13: /* enter */
              sale = 1;
              break;
            case 27: /* escape */
              sale = 1;
              sel = 0;
              break;
            default: /* busco a ver si ch está entre
                        las letras realzadas */
    	  for (i=0; i<n; i++) {
                if (realzadas[i] == -1) continue;
    	    if (toupper(ch) == toupper(ptrs[i][realzadas[i]])) {
                  sel = i+1;
                  sale = 1;
                  break;
                }
    	  }
          }
        }
      }
      /* antes de salir, pongo el cursor al final del menú... */
      gotoxy(1, y+n+1);
      textattr(attr_item);
    
      free(msjs); free(ptrs); free(realzadas);
    
      return sel;
    }
    
    int main(void)
    {
      int n=menu("EL MENU", "&Agarramela|&con|la|&mano",
    	    BLACK<<4 | YELLOW, BLACK<<4 | LIGHTGRAY,
    	    BLACK<<4 | WHITE, LIGHTGRAY<<4 | BLACK);
      printf("el elegido es %d\n", n);
      return 0;
    }
    
    Editado por pangus - 20.08.2009 10:48 hs.
    Me gusta este mensaje
  • #7 Re: Haciendo un menu, problema con matriz dinamica bidimencional

    Encontre la falla y si alguno me la explica lo agradeceria xq NO LO ENTIENDO...

    Bueno, la cosa es que pasaba a la funcion la cadena, pero escribiendola directamente en los argumentos, ya que yo queria no declarar variables en el programa para este menu...

    entonces cuando llamaba a la funcion el programa quedaba asi...

    Código:
    void main()
    {
    unsigned short i;
    for(;;)
        {
            i=menu("M E N U BETA",5,"|","%","Opcion%1|Opcion%2|Opcion%3|Opcion%4|Opcion%5");
            clrscr();
            printf("La opcion selecionada fue la %d",i);
            getch();
        }
    }
    
    La cosa es que, la funcion trabaja con un puntero a esa cadena, para que no la copie, cuando la funcion terminaba de separar las opciones en la cadena quedaria "Opcion%1\0" solamente, esto esta bien, la funcion termina, el for da otra vuelta, vuelve a llamar a la funcion con los mismos argumentos, PERO esta vez, en vez de recibir "Opcion%1|Opcion%2|Opcion%3|Opcion%4|Opcion%5" , recibia "Opcion%1\0"... OK WTF?!!!! si usaba otra variable para la 2da vez, las opciones se mantenian bien, es como si guardara un "cache" de los argumentos y la funcion modificaria ese cache, y a la 2da vez vuelve a leer el cache sin darse cuenta de que se modifico...

    Al final me encontre con 2 soluciones, usar una variable cadena y escribir las opciones con sprintf antes de llamar a la funcion.

    Código:
    void main()
    {
    unsigned short i;
    char cad[100];
    for(;;)
        {
           sprintf(cad,"Opcion%1|Opcion%2|Opcion%3|Opcion%4|Opcion%5");
            i=menu("M E N U BETA",5,"|","%",cad);
            clrscr();
            printf("La opcion selecionada fue la %d",i);
            getch();
        }
    }
    
    La otra era usar una copia en vez de un puntero.
    Me gusta este mensaje
Estás en: Inicio >> Foros >> Informática >> Programación


Estadísticas del tema
  • 6 RESPUESTAS
  • 813 VISTAS
  • 4 USUARIOS RESPONDIERON
 
Ir arriba
Contacto | Acerca de | Ayuda | Términos Legales | privacidad | Pautas de convivencia | Mapa de los foros | TrabajÁ con nosotros
©2008 Psicofxp.com S.A. - Todos los derechos reservados
Certifica IAB