Problema accediendo a puntero de matriz bidimensional, ¿Como hago esto....?

Iniciado por Xajorkith, 25 Abril 2016, 16:10 PM

0 Miembros y 2 Visitantes están viendo este tema.

Xajorkith

Hola, he retomado la programación en C, y se me ocurrio usar punteros por lo del ahorro de memoria.

Lo primero que he hecho es intentar pasar la función de impresión que tenía, hasta ahora usaba una matriz de 256x16 para caracteres de hasta 16x16 pixels, y lo intenté mejorar creando la siguiente matriz global para poder tener hasta 20 tipos de letra disponibles:

typedef struct {unsigned short letra[256][16];} Acaracteres;
typedef struct {int ancho; int alto; unsigned char nombre[20]; int codigo;
                           Acaracteres *caracteres;} Tiposdeletra;
Tiposdeletra Sletras[20];

No creo que llegue a usar mas de dos o tres, pero como la matriz ocupa poco y ofrece mucho, compensa. Luego llamo a la función que carga el primer tipo de letra para que haya al menos una disponible para el sistema, lo que hace es esto:

void IniLetra8x8()
{ int sigcar, cuenta;
 
  Sletras[0].ancho=8;
  Sletras[0].alto=8;
//  Sletras[0].nombre=(unsigned char[20])"ZXSpectrum 8x8";
  Sletras[0].codigo=1;
 
  Sletras[0].caracteres=(Acaracteres *)malloc(sizeof(Acaracteres));
 
  for (cuenta=0; cuenta<256; cuenta++)
  { for (sigcar=0; sigcar<16; sigcar++)
    { Sletras[0].caracteres[cuenta][sigcar]=0; }
  }

Y luego cambiaré en el resto de la función Acaracteres[sigcar][0] por Sletras[0].caracteres[sigcar][0]

  sigcar=2;
  Acaracteres[sigcar][0]=0xE600; Acaracteres[sigcar][1]=0x8900; Acaracteres[sigcar][2]=0x8900; Acaracteres[sigcar][3]=0xE900;
  Acaracteres[sigcar][4]=0x8900; Acaracteres[sigcar][5]=0x8900; Acaracteres[sigcar][6]=0x8900; Acaracteres[sigcar][7]=0x8600;
  sigcar++;
  Acaracteres[sigcar][0]=0xE200; Acaracteres[sigcar][1]=0x8600; Acaracteres[sigcar][2]=0x8A00; Acaracteres[sigcar][3]=0xE200;
  Acaracteres[sigcar][4]=0x8200; Acaracteres[sigcar][5]=0x8200; Acaracteres[sigcar][6]=0x8200; Acaracteres[sigcar][7]=0x8700;

y así seguiría generando los demás caracteres, pero al compilar me muestra el siguiente error:

no match for 'operator[]' in '*(Sletras[0].Tiposdeletra::caracteres + (+(((unsigned int)cuenta) * 8192u)))[sigcar]'

Mensaje que no entiendo en absoluto.

¿como accedo al contenido del array creado? Si es que lo estoy creando correctamente, que lo de los punetros siempre es un poco lio. La línea de

Sletras[0].nombre=(unsigned char[20])"ZXSpectrum 8x8";

también da error, pero ese no me preocupa demasiado.

Gracias.


HardForo

Para no caer en un "problema XY", dinos mejor QUE QUIERES LOGRAR con IniLetra8x8()

Te aclaro que si hay una matriz de tamaño fijo (8x8) no tiene sentido que la crees con punteros, no hay el "ahorro" (que existe cuando haces una matriz mas grande por si las dudas)

Por otro lado si IniLetra8x8() maneja una matriz de tamaño variable en filas o columnas, no deberia llamarse asi.



EDIT: no sabia lo que querias hacer...... lo siento
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

Xajorkith

Cita de: boctulus en 25 Abril 2016, 16:18 PM
Para no caer en un "problema XY", dinos mejor QUE QUIERES LOGRAR con IniLetra8x8()

Te aclaro que si hay una matriz de tamaño fijo (8x8) no tiene sentido que la crees con punteros, no hay el "ahorro" (que existe cuando haces una matriz mas grande por si las dudas)

Por otro lado si IniLetra8x8() maneja una matriz de tamaño variable en filas o columnas, no deberia llamarse asi.

La definición de las estructuras va antes del main, la he puesto para que veaís como está definida.
Lo que hago es crear una matriz de 20 tipos de letra, en cada uno de sus elementos hay un puntero a una matriz  de 256 x 16 de tipo unsigned short para cada tipo de letra. El nombre de la función es por que el tipo de letra qur voy usar para empezar es de 8x8 pixels, reservo 8192 bytes en total para cada tipo de letra con malloc, pero solo cuando los creo, en principio solo habrá uno cargado. Los demás ya irán llegando.
El primer bucle anidado de FOR es para iniclizar a cero todos los valores, y luego para cada caracter voy poniendo los que varían.
Cuando esta función vaya bien, tenga creado el primer tipo de letra y pueda volver a imprimir en pantalla como hacía con el original, haré otra genérica para cargar tipos de letra desde un archivo y entonces generaré con malloc otro bloque de 8192 bytes y lo rellenaré con el contenido del fichero indicado.

Xajorkith

#3
Antes de main creo lo siguiente:

typedef struct {unsigned short letra[256][16];} Acaracteres;  //Una matriz para guardar los datos de los caracteres.
typedef struct {int ancho;
                      int alto;
                      unsigned char nombre[20];
                      int codigo;
                     Acaracteres *caracteres;} Tiposdeletra;  // Otro tipo para los datos de cada tipo de letra.

Tiposdeletra Sletras[20];   // la matriz, o array o arreglo, no se cual es el término mas correcto. :)

Ahora tengo una matriz llamada Sletras, sin ningún tipo de letra cargado.

Luego, para que que haya al menos un tipo de letra disponible llamo a IniLetra8x8(), que se llama así simplemente por que el primer tipo de letra tiene un ancho y un alto de 8x8 pixels, y le pongo el código 1, con las siguientes líneas de la función:

void IniLetra8x8()
{ int sigcar, cuenta;

 Sletras[0].ancho=8;
 Sletras[0].alto=8;
//  Sletras[0].nombre="ZXSpectrum 8x8";
 Sletras[0].codigo=1;

Después reservo la memoria para los datos de los caracteres, de los 256 caracteres que tiene la matriz (caracteres, que en realidad es el puntero) que va dentro de la matriz Sletras, y asigno la dirección a Sletras[0].caracteres
 
 Sletras[0].caracteres=(Acaracteres *)malloc(sizeof(Acaracteres));

Si no me estoy equivocando (que me da que si me estoy equivocando, si no, no habría error al compilar), ahora

Sletras[0].caracteres

es la dirección del primer valor de la matriz de caracteres, a la que yo pensaba que se accedía usando

Sletras[0].caracteres[0][0]    hasta llegar al final en   Sletras[0].caracteres[255][15]

pero al intentar hacer eso en la función dentro del bucle con

 for (cuenta=0; cuenta<256; cuenta++)
 { for (sigcar=0; sigcar<16; sigcar++)
   { Sletras[0].caracteres[cuenta][sigcar]=0; }
 }

al compilar me muestra el error:

no match for 'operator[]' in '*(Sletras[0].Tiposdeletra::caracteres + (+(((unsigned int)cuenta) * 8192u)))[sigcar]'

¿Como accedo al área de memoria reservado con malloc y guardado en Sletras[0].caracteres teniendo en cuenta que los 8192 bytes son una matriz de "unsigned short letra[256][16]"? ¿O tengo que usar otro formato al llamar a malloc?

Ese es mi problema.

HardForo

Bueno amigo con malloc() estas reservando espacio para un puntero simple pero luego lo quieres acceder como si tuviera mas dimensiones:

Código (cpp) [Seleccionar]
Sletras[0].caracteres[cuenta][sigcar]=0;

Sino me equivoco, estas usando un indice de mas ([sigcar]) y justamente por eso te dice esto:

Citar
no match for 'operator[]' in

HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

Xajorkith

Cita de: boctulus en 25 Abril 2016, 17:33 PM
Bueno amigo con malloc() estas reservando espacio para un puntero simple pero luego lo quieres acceder como si tuviera mas dimensiones:

Código (cpp) [Seleccionar]
Sletras[0].caracteres[cuenta][sigcar]=0;

Sino me equivoco, estas usando un indice de mas ([sigcar]) y justamente por eso te dice esto:



¿Y cómo reservo memoria para una matriz de tipo " Acaracteres ", (la unsigned short letra[256][16]) y accedo luego a sus elementos?

HardForo

Reservas espacio para solo una instancia del struct:

Sletras[0].caracteres=(Acaracteres *)malloc(sizeof(Acaracteres));

cuando si N contiene la cantidad que quieres reservar en un comienzo, debes hacer:

Sletras[0].caracteres=(Acaracteres *)malloc( N * sizeof(Acaracteres));


Obviamente queda pendiente arregles el como accedes al interior de tu struct pero la sintaxis no es la correcta porque se te olvida que Acaracteres tiene letra y debes acceder a ese miembro ya sea como:  (*puntero_a_struct).letra ó puntero_a_struct->letra


PD: con el programa completo podria ver si logro que compile
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

Xajorkith

Cita de: boctulus en 25 Abril 2016, 18:11 PM
Reservas espacio para solo una instancia del struct:

Sletras[0].caracteres=(Acaracteres *)malloc(sizeof(Acaracteres));

cuando si N contiene la cantidad que quieres reservar en un comienzo, debes hacer:

Sletras[0].caracteres=(Acaracteres *)malloc( N * sizeof(Acaracteres));


Obviamente queda pendiente arregles el como accedes al interior de tu struct pero la sintaxis no es la correcta porque se te olvida que Acaracteres tiene letra y debes acceder a ese miembro ya sea como:  (*puntero_a_struct).letra ó puntero_a_struct->letra


PD: con el programa completo podria ver si logro que compile

Bueno, de momento he puesto

   { Sletras[0].caracteres->letra[cuenta][sigcar]=0; }

y ha pasado bien la línea al compilar, cuando termine de renombrar las variables (unos días entre una cosa y otra....) te mando una mini demo a er que te parece. Gracias por todo.

HardForo

HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

MAFUS

Y digo yo: y si en vez de usar malloc y después un for para recorrer la tabla y ponerla a 0, ¿porqué no usas calloc y haces todo el trabajo de una tacada?