2009-12-11 14 views
5

Estoy trabajando con una matriz bidimensional de estructuras que es parte de otra estructura. No es algo con lo que he hecho mucho, así que estoy teniendo un problema. Esta función termina fallando después de llegar al ciclo de "prueba" para el final. Imprime una línea correctamente antes de seg seg.Problema de codificación usando una matriz de 2 d construcciones dentro de otra estructura en C

Las partes de mi código que leen datos en una matriz ficticia de 2 d construcciones funciona muy bien, por lo que debe ser mi matriz de asignación para ser parte de otra estructura (la imageStruct).

Cualquier ayuda sería muy apreciada!

/*the structure of each pixel*/ 
typedef struct 
{ 
int R,G,B; 
}pixelStruct; 

/*data for each image*/ 
typedef struct 
{ 
int height; 
int width; 
pixelStruct *arr; /*pointer to 2-d array of pixels*/ 
} imageStruct; 


imageStruct ReadImage(char * filename) 
{ 
FILE *image=fopen(filename,"r"); 
imageStruct thisImage; 

     /*get header data from image*/ 

     /*make a 2-d array of of pixels*/ 
pixelStruct imageArr[thisImage.height][thisImage.width]; 

     /*Read in the image. */ 

     /*I know this works because I after storing the image data in the 
      imageArr array, I printed each element from the array to the 
      screen.*/ 

/*so now I want to take the array called imageArr and put it in the 
    imageStruct called thisImage*/ 

    thisImage.arr = malloc(sizeof(imageArr)); 
    //allocate enough space in struct for the image array. 

*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/ 

//test to see if assignment worked: (this is where it fails) 

for (i = 0; i < thisImage.height; i++) 
{ 
    for (j = 0; j < thisImage.width; j++) 
    { 
    printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R, 
      thisImage.arr[i][j].G, thisImage.arr[i][j].B); 
    } 
} 

return thisImage; 
} 

(En caso de que usted se está preguntando por qué estoy usando una matriz ficticia, en primer lugar, así que es porque cuando empecé a escribir este código, no podía encontrar la manera de hacer lo que estoy tratando de hacer ahora.)

EDITAR: Una persona sugirió que no inicialicé mi matriz de 2-d correctamente en el typedef para la imageStruct. ¿Alguien puede ayudarme a corregir esto si es realmente el problema?

+0

Un lado: si trabaja con píxeles, es posible que desee considerar un búfer lineal plano, luego el punto índice (x, y) con búfer [y * ancho + x]. Eso se hace con bastante frecuencia, y podría ser beneficioso si alguna vez tiene que pasar ese búfer al código de otra persona que podría asumir ese formato. – asveikau

+0

¡Gracias por el consejo! Lo consideraré. ¡Entonces podría olvidar este lío con las matrices en 2d! – KMM

+0

He llegado a la conclusión de que no hay ninguna esperanza en tratar de hacer una matriz 2-D como parte de una estructura. Cambié a una matriz 1-D y todo está funcionando ahora. Gracias a todos los que me ayudaron, este es de lejos el foro de programación más útil que he conocido. – KMM

Respuesta

5

Parece que puede crear matrices de longitud variable, por lo que está en un sistema C99 o en un sistema que lo admita. Pero no todos los compiladores los respaldan. Si desea utilizarlos, no necesita la declaración del puntero arr en su estructura. Suponiendo que no hay entre longitud y matrices de variables, veamos las partes pertinentes de su código:

/*data for each image*/ 
typedef struct 
{ 
    int height; 
    int width; 
    pixelStruct *arr; /*pointer to 2-d array of pixels*/ 
} imageStruct; 

arr es un puntero a pixelStruct, y no a una matriz 2-D de píxeles. Claro, puede usar arr para acceder a dicha matriz, pero el comentario es engañoso e indica un malentendido. Si realmente desea declarar una variable de este tipo, que haría algo como:

pixelStruct (*arr)[2][3]; 

y arr sería un puntero a una "matriz de 2 de la matriz 3 de pixelStruct", lo que significa que los puntos arr a una 2- d matriz. Esto no es realmente lo que quieres. Para ser justos, esto no es lo que declaras, entonces todo está bien. Pero su comentario sugiere un malentendido de punteros en C, y eso se manifiesta más adelante en su código.

En este punto, harás bien en leer una buena introducción a las matrices y punteros en C, y una muy buena es C For Smarties: Arrays and Pointers de Chris Torek. En particular, asegúrese de comprender el primer diagrama en la página y todo lo que se encuentre en la definición de la función f allí.

Dado que desea poder indexar arr de forma natural utilizando los índices "columna" y "fila", le sugiero que declare arr como un puntero al puntero. Por lo que su estructura se convierte en:

/* data for each image */ 
typedef struct 
{ 
    int height; 
    int width; 
    pixelStruct **arr; /* Image data of height*width dimensions */ 
} imageStruct; 

Luego, en función de su ReadImage, se puede asignar memoria que necesita:

int i; 
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr); 
for (i=0; i < thisImage.height; ++i) 
    thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]); 

Tenga en cuenta que para mayor claridad, no he hecho ninguna comprobación de errores en malloc. En la práctica, debe verificar si malloc devolvió NULL y tomar las medidas apropiadas.

Asumiendo que toda la asignación de memoria fue exitosa, ahora puede leer su imagen en thisImage.arr (como lo hacía con imageArr en su función original).

Una vez que haya terminado con thisImage.arr, asegúrese de liberarlo:

for (i=0; i < thisImage.height; ++i) 
    free(thisImage.arr[i]); 

free(thisImage.arr); 

En la práctica, tendrá que envolver las piezas de asignación y desasignación más arriba en sus respectivas funciones que asignar y liberar el objeto arr y ocuparse de la comprobación de errores.

+0

¡Guau, gracias por una respuesta en profundidad! Tienes toda la razón de que no entiendo bien los punteros de C. Creo que mi problema está completamente resuelto ahora. ¡Gracias de nuevo! – KMM

2

No creo que sizeof imageArr funcione como se espera cuando se utilizan matrices del tamaño de un runtime. Que, por cierto, son una especie de característica C99 "nicho". Debe agregar algunas impresiones de valores cruciales, como el sizeof para ver si hace lo que piensa.

más clara sería la de utilizar la asignación explícita de la matriz:

thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr); 

También creo que es difícil (si es aún posible) para implementar un "verdadero" matriz 2D como este. Yo recomendaría sólo haciendo el cómputo dirección de sí mismo, es decir, el acceso a un píxel de esta manera:

unsigned int x = 3, y = 1; // Assume image is larger. 
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]); 

no veo cómo la información dimensión requerida puede estar asociado con una serie en tiempo de ejecución; No creo que eso sea posible.

+0

Si height = 10 y width = 1, y cada spot en la matriz tiene 3 ints para la estructura pixelStruct, entonces cada ranura debe ser 3 * 4 = 12 bytes, entonces para la matriz completa es 120 ... ¿Estoy en lo correcto? Si es así, entonces mi código "sizeof imageArr" funciona bien. Probé tu código, pero sizeof * thisImage.arr sale a 4. Cuando reemplacé mi código malloc con el tuyo, obtuve exactamente los mismos resultados. ¡Gracias por su ayuda hasta ahora! – KMM

+0

Si sizeof * thisImage.arr es cuatro, entonces hay algo mal con el código que mostró. Debe ser del tamaño de los datos apuntados, es decir, sizeof (pixelStruct). ¿Incluiste la estrella? – unwind

+0

Sí, tienes razón. Cambié la declaración de pixelstruct * arr a pixelstruct ** arr. Entonces ahora sale a 12 y 120, pero ese es el mismo resultado que mi malloc original. Gracias. – KMM

0

alto y ancho no están definidos; es posible que desee inicializar ellos en primer lugar, al igual que en

thisImage.height = 10; thisImage.width = 20;

también,

  • lo que es colorRGB?
+0

La altura y el ancho son cosas que definí en la sección del código que saqué en la parte que dice "obtener datos de encabezado de la imagen". No hay problema con estos valores. ColorRGB era el nombre original de mi estructura pixelStruct. Hice un hallazgo y reemplazo para cambiarlo, pero me perdí uno. Gracias – KMM

0

Parece que está intentando copiar la matriz por asignación. No puede usar el operador de asignación simple para hacer eso, tiene que usar alguna función para copiar cosas, por ejemplo memcpy.

*thisImage.arr = *imageArr; 
thisimage.arr[0] = imagearr[0]; 

Las declaraciones anteriores están haciendo lo mismo. Sin embargo, esto no es lo más probable que cause daños en la memoria

dado que está trabajando con matrices bidimensionales, asegúrese de inicializarlas correctamente. Mirando el código, ni siquiera debería compilar: ¿la matriz se declara como unidimensional en la estructura de su imagen, pero usted se refiere como bidimensional?

+0

¿Cómo declaro el conjunto como 2-D en la estructura de la imagen? Gracias. – KMM

0

*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*

Esto no funcionará. Debe declarar arr como colorRGB **, asignarlo en consecuencia, etc.

Cuestiones relacionadas