Как да транспонирам матрица от указатели

Имам матрица на оформление

const int boatRect[MAX_BITMAP_SIZE][MAX_BITMAP_SIZE] = { // 5
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0}
};

и структура с указател към нея (матрица):

typedef struct bitmap {
    Shape shape;
    const int (*matrix)[MAX_BITMAP_SIZE];
    int orientation;
    int size;
} Bitmap;

След това искам да транспонирам (част от процеса на ротация) матрицата в структурата:

void transpose(const int (*shape)[MAX_BITMAP_SIZE]) {
    const int *temp;
    for(int i = 0; i < MAX_BITMAP_SIZE; i++) {
        for(int j = 0; j < i; j++) {
            temp = (const int *) shape[i][j]; //Cast to 'const int *' from smaller integer type 'int'
            shape[i][j] = shape[j][i];        //Read-only variable is not assignable
            shape[j][i] = temp;               //Read-only variable is not assignable
        }
    }
}

но получавам тези грешки, не съм сигурен какво правя погрешно!

Опитвам се да го направя по този начин, за да имам само една матрица в кода и да имам указатели към нея и да въртя тези указатели по начин, по който предават завъртяната матрица, без да създават друга.

И така, как да създам в моята растерна структура матрица от указатели, които сочат към const int матрицата, и след това да завъртя тази матрица от указатели (не тази от int)?


person obvionaoe    schedule 21.04.2020    source източник
comment
Трябва да промените сигнатурата на функцията на void transpose(int (*shape)[MAX_BITMAP_SIZE]) Предупреждението за преобразуването ще продължи, но можете да се отървете от това, като промените const int *temp; на const int temp; и премахнете преобразуването (тъй като присвоявате int на int).   -  person Louis Cloete    schedule 21.04.2020


Отговори (1)


Вашата матрица не е "матрица от указатели", което би било матрица, чиито елементи са указатели. Това е матрица от цели числа. Вие го дефинирате като масив от масиви от int.

const int boatRect[MAX_BITMAP_SIZE][MAX_BITMAP_SIZE] = { ... };

Подобно на други масиви, той може да бъде представен като указател към първия си елемент, който във вашия случай е масив от MAX_BITMAP_SIZE ints.

const int (*matrix)[MAX_BITMAP_SIZE];

Дереферирането му два пъти ще ви даде int, а именно целочислената стойност в дадения ред и колона. Следователно вашата temp променлива за размяна трябва да бъде int:

int temp = shape[i][j];

Не е необходим кастинг! (Предупреждението означава, че ints са "по-тесни" от указател на вашата система и че ще загубите информация в присвояването.)

С тази промяна втората грешка все още ще съществува: Вие сте направили матрицата const: Елементите на const T* не могат да бъдат променени. Ако искате да промените матрицата на място, не я правете const. (Все още можете да го направите локално const във функции, които имат достъп, но не го променяйте.)

person M Oehm    schedule 21.04.2020
comment
Знам, че оригиналната матрица не е матрица от указатели, но искам да имам указателна матрица, която да сочи към нея, и след това да завъртя тази указателна матрица - person obvionaoe; 21.04.2020
comment
Значи искате да имате матрица, чиито елементи са указатели към целочислените елементи на оригиналната матрица? И ако имате обратна матрица, просто разменяте указатели? Според мен това няма смисъл. Това, което имате, е указател към матрица, така че вашата структура просто поддържа указател, без да копира цялата матрица. Ако модифицирате матрицата чрез този указател, вие променяте оригиналната матрица, защото те са еднакви. - person M Oehm; 21.04.2020
comment
тогава какъв би бил най-добрият начин да имате само една матрица в паметта? защото това е моята цел, иначе нямаше да се забърквам с указатели, просто бих го копирал - person obvionaoe; 21.04.2020
comment
Това сте направили, с изключение на това, че изглежда имате погрешна представа за това каква част е показалецът: показалецът е външната част; не засяга вътрешните части. Вземете прост масив: int a = [1, 2, 3]. Сега дефинирайте указател към него: int *p = a. И a[0], и p[0] имат достъп до първия елемент от a и присвояването на нова стойност на p[0] също ще промени елемент a[0] от основния масив. Това искаш, нали? (продължение) - person M Oehm; 21.04.2020
comment
Забележете, че тук елементите на a и p са ints. p само по себе си е указател, но това, към което сочи, са цели числа. Сега използвате този метод за двуизмерен масив, int M[5][5]. Елементите на M са масиви от пет int. Указател към този масив е int (*P)[5]. (Отначало трябва да свикнете с този синтаксис.) P сочи към масив от пет int и M[0] и P[0] имат достъп до първия ред на вашата матрица. За да стигнете до цялото число в определена колона на този ред, трябва да предоставите втория индекс: M[0][i] и P[0][j] са едно и също цяло число. - person M Oehm; 21.04.2020
comment
Просто искам да променя там, където сочи показалецът, всъщност не искам да променям стойностите! Ако имах матрица 2*2 с { {0,1}, {0,1} }, искам всяка структура да има матрица от указатели { {ptr1, ptr2}, {ptr3, ptr4} } и в моята функция за завъртане искам тази матрица на указателя да се завърти { {ptr2, ptr4}, {ptr1, ptr3} }, но да запазя оригиналната матрица като { {0,1}, {0,1} }! мога ли да направя това или е пълна глупост? Просто се опитвам да имам възможно най-малко активи в паметта :/ - person obvionaoe; 21.04.2020
comment
Може би typedef може да бъде полезно тук: typedef int Matrix5x5[5][5]; Дефинирайте матрица с Matrix5x5 m = {{...}};. Сега членът на вашата структура, указателят към тази матрица, е Matrix5x5 *p;, точно както при всеки друг тип. (Но създаването на typedefs за масиви с фиксирани размери замъглява природата на типа, така че обикновено не го правя.) - person M Oehm; 21.04.2020
comment
Но по този начин ще имам указател към матрица, искам матрица от указатели - person obvionaoe; 21.04.2020
comment
Нека продължим тази дискусия в чата. - person obvionaoe; 21.04.2020
comment
Добре, говорихме напречно тук. Вие всъщност наистина искахте да имате матрица от указатели. Това не е глупаво, но не виждам истинската полза тук. Вашият базов тип данни, цели числа, са малки, обикновено по-малки от указател. Създаването на нова матрица е също толкова евтино, що се отнася до паметта, колкото създаването на матрица от указатели. Наличието на масив от указатели все още е полезна техника: Представете си, че имате едномерен масив от големи обекти, всеки от които е килобайт. Искате да ги покажете в определен ред. Вместо да ги сортирате, създайте масив от леки указатели и ги сортирайте индиректно. - person M Oehm; 21.04.2020
comment
Както и да е, ако искате да имате матрица от указатели, дефинирайте int *pm[5][5]. Вече не можете да зададете матрицата с една инструкция, трябва да инициализирате всеки елемент с pm[j][i] = &m[j][i] изрично. - person M Oehm; 21.04.2020