Проблема кодирования с использованием 2-мерного массива структур внутри другой структуры в C

Я работаю с 2-мерным массивом структур, который является частью другой структуры. Это не то, что я сделал много, поэтому у меня проблемы. Эта функция заканчивается неудачей после перехода к "тесту" для цикла ближе к концу. Он печатает одну строку правильно, прежде чем она будет устранена.

Части моего кода, которые считывают данные в манекен-2-мерный массив структур, отлично работают, поэтому мой присваивающий массив должен быть частью другой структуры (imageStruct).

Любая помощь будет принята с благодарностью!

/*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;
}

(В случае, если вам интересно, почему я использую фиктивный массив в первую очередь, ну, потому что, когда я начал писать этот код, я не мог понять, как делать то, что я пытаюсь сделать сейчас.)

EDIT: Один человек предположил, что я не инициализировал свой 2-мерный массив правильно в typedef для imageStruct. Может ли кто-нибудь помочь мне исправить это, если это действительно проблема?

Ответ 1

Кажется, вы можете создавать массивы переменной длины, поэтому вы находитесь в системе C99 или в системе, которая ее поддерживает. Но не все компиляторы поддерживают их. Если вы хотите использовать их, вам не требуется объявление указателя arr в вашей структуре. Предполагая массивы переменной длины, рассмотрим соответствующие части вашего кода:

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

arr является указателем на pixelStruct, а не на 2-мерный массив пикселей. Конечно, вы можете использовать arr для доступа к такому массиву, но комментарий вводит в заблуждение, и он намекает на недоразумение. Если вы действительно хотите объявить такую ​​переменную, вы бы сделали что-то вроде:

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

и arr будет указателем на "массив 2 из массива 3 элемента pixelStruct", что означает, что arr указывает на 2-й массив. Это не то, что вы хотите. Справедливости ради, это не то, что вы заявляете, так что все хорошо. Но ваш комментарий предполагает недоразумение указателей в C, и это проявляется позже в вашем коде.

На этом этапе вам будет полезно прочитать хорошее введение в массивы и указатели на C, а действительно хороший C Для Smarties: массивы и Указатели Криса Торека. В частности, убедитесь, что вы поняли первую диаграмму на странице и все, что содержится в определении функции f.

Поскольку вы хотите иметь возможность индексировать arr естественным образом, используя индексы "column" и "row", я предлагаю вам объявить arr как указатель на указатель. Таким образом, ваша структура становится:

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

Затем в вашей функции ReadImage вы выделяете нужную вам память:

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]);

Обратите внимание, что для ясности я не выполнял проверку ошибок на malloc. На практике вы должны проверить, возвращен ли malloc NULL, и принять соответствующие меры.

Предполагая, что все выделение памяти выполнено успешно, вы можете теперь прочитать свое изображение в thisImage.arr (как и в imageArr в исходной функции).

Как только вы закончите с thisImage.arr, не забудьте его освободить:

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

free(thisImage.arr);

На практике вам нужно будет обернуть части распределения и освобождения выше в своих соответствующих функциях, которые выделяют и освобождают объект arr и заботятся об ошибках.

Ответ 2

Я не думаю, что sizeof imageArr работает так, как вы ожидаете, когда вы используете массивы времени исполнения. Что, кстати, это своего рода "ниша" C99. Вы должны добавить некоторые распечатки важных значений, таких как sizeof, чтобы увидеть, делает ли он то, что вы думаете.

Clearer будет использовать явное выделение массива:

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

Я также считаю, что трудно (если возможно) реализовать "истинный" 2D-массив, подобный этому. Я бы рекомендовал просто выполнить вычисления адресов самостоятельно, то есть получить доступ к пикселю, подобному этому:

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]);

Я не вижу, как требуемая информация об размерности может быть связана с массивом во время выполнения; Я не думаю, что это возможно.

Ответ 3

высота и ширина undefined; вы можете сначала инициализировать их, как в

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

также,

  • что такое colorRGB?

Ответ 4

похоже, что вы пытаетесь скопировать массив по заданию. Вы не можете использовать простой оператор присваивания для этого, вам нужно использовать некоторую функцию для копирования вещей, например memcpy.

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

Вышеприведенные утверждения делают то же самое. Однако это не является наиболее вероятным, что вызывает повреждение памяти.

так как вы работаете с двухмерными массивами, убедитесь, что вы правильно их инициализировали. Глядя на код, он даже не должен компилироваться: массив объявлен как одномерный в вашей структуре изображения, но вы называете его двумерным?

Ответ 5

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

Это не сработает. Вы должны объявить arr как colorRGB **, выделить его соответственно и т.д.