[ Buffy @ 30.01.2005. 15:00 ] @
imam problema sa dvodimenzionalnim matricama.
Naime sledeci kod ne radi:

Code:

void funk(int **a)
{
    //...
}

int main()
{
    int mat[10][10];
    funk(mat);
    return 0;
}

Zbog cega gornji kod nece da radi kad sam deklarisao parametar kao pokazivac koji pokazuje
na pokazivac.Compiler kaze:
"cannot convert parameter 1 from int[10][10] to int**."
Zar "mat" ne predstavlja konstantan pokazivac na pokazivac(int**)?
Kako da prenesem pokazivac na dvodimenzionalnu matricu(ili trodimnezionalnu) nekoj funkciji pravilno?
Unaprijed zahvalan!

[ leka @ 30.01.2005. 16:26 ] @
Probaj umesto
Code:
void funk(int **a)
da stavis
Code:
void funk(int a[][10])
. Javi ako ne radi i usput posalji kompletan kod ako ikako moze...
[ Buffy @ 30.01.2005. 22:21 ] @
Radi,
ali mi se taj nacin uopste ne dopada.
Rad sa dvodimenzionalnim matricama je veoma tezak u c/c++ -u ako se jedino na ovaj nacin moze preneti argument.
[ NastyBoy @ 30.01.2005. 23:49 ] @
Ako radish u C++, zashto ne napravish klasu kao wrapper oko dvodimenzionalne matrice i prenesesh objekat te klase u funkciju?
[ Dragi Tata @ 31.01.2005. 01:52 ] @
Citat:
NastyBoy: Ako radish u C++, zashto ne napravish klasu kao wrapper oko dvodimenzionalne matrice i prenesesh objekat te klase u funkciju?


Ako radi u C++u nema nikakve potrebe da sam izmišlja toplu vodu - već postoji mali milion gotovih klasa za matricu.
[ Pah-Wrait @ 31.01.2005. 02:16 ] @
Code:

void funk(int **a)
{
//...
}

int main()
{
int mat[10][10];
funk(mat);
return 0;
}

Fora je u tome sto u C mozes da zanemaris samo poslednju uglastu zagradu (odnosno, ako stavis funk(mat[10]) trebalo bi da radi. Ali nemoj nikad koristiti brojeve za definiciju matrice, nego koristi konstante (M, N).
Onda ne moras da vodis racuna o tome kojeg je reda matrica.
[ NastyBoy @ 31.01.2005. 02:27 ] @
Citat:
Dragi Tata: Ako radi u C++u nema nikakve potrebe da sam izmišlja toplu vodu - već postoji mali milion gotovih klasa za matricu.


Tachno, ali zar ne bi bilo dobro da pokusha da reshi problem samostalno?
Klasa matrice je jako zanimljiva za igranje/vezhbanje :)
[ Marko Stankovic @ 31.01.2005. 14:27 ] @
Citat:
Buffy:
Rad sa dvodimenzionalnim matricama je veoma tezak u c/c++ -u ako se jedino na ovaj nacin moze preneti argument.


U C-u tvoj kod mora da radi, eventualno ce kompajler izbaciti warning da nisu kompatibilni pokazivaci, ali mora da napravi izvrsni fajl. Proveri da nisi isao na new c++ project u cemu god programiras.

Nego aj da ne otvaram novu temu posto se radi o slicnom problemu, kako se u c++ stvara dinamicka matrica, znaci kog tipa treba da je pokazivac da me kompajler ne bi zezao kao u ovom kodu? Ja sam probao sa
Code:

int **mat=new int[10][10];

i ovo naravno nece da radi. Nemojte samo odgovore tipa koristi gotove klase za matrice i slicno.

[Ovu poruku je menjao Marko Stankovic dana 31.01.2005. u 15:30 GMT+1]
[ Buffy @ 31.01.2005. 14:29 ] @
Napravio sam na brzinu najjednostavniju i ne potpunu klasu za rad
sa dvodimenzionalnim matricama.Prvo kod:
Code:

template<class t> class DM
{
public:
    DM(int a,int b):duz(a)
    {
        mat=new t*[a];
        for (int i=0;i<=a-1;++i) mat[i]=new t[b];
    }
    ~DM()
    {
        for (int i=0;i<=duz-1;++i) delete [] mat[i];
        delete [] mat;
    }
    t & operator()(int a,int b)
    {
        return mat[a][b];
    }
    t * operator()(int a)
    {
        return mat[a];
    }
    operator t**()
    {
        return mat;
    }
private:
    t **mat;
    int duz;
};

Nisam siguran da nema bagova.
U konstruktoru se alocira memorija za dvostruki pokazivac koji je clan
DM klase.U destruktoru se dealocira ta memorija,a ostale funkcije sluze za pristup
clanovima niza po indeksu.Sada da vidimo klasu na djelu:
Code:

//program za testiranje DM klase
void funk(int **a)
{
    a[3][4]=157;
}
int main()
{
    DM<int> mat(10,10);
    funk(mat);
    cout<<mat(3,4)<<'\n';
    return 0;

}

Izlaz na ekran je "157" sto znaci da je u redu.
Ja samo znam za ovaj nacin prenosenja argumenata(alociranjem memorije sa slobodnog skladista).
Bolje rjesenje(za mene) je da se umjesto klase napravi funkcija koja alocira memoriju...
Code:

int **DM(int a,int b)
{
    int **pok;
    pok=new int*[a];
    for (int i=0;i<=a-1;++i) pok[i]=new int[b];
    return pok;
}

... i vraca pokazivac na dvodimenzionalni niz.
Imali boljih nacina?
[ Buffy @ 31.01.2005. 14:33 ] @
Citat:
Marko Stankovic
Nego aj da ne otvaram novu temu posto se radi o slicnom problemu, kako se u c++ stvara dinamicka matrica, znaci kog tipa treba da je pokazivac da me kompajler ne bi zezao kao u ovom kodu? Ja sam probao sa
Code:

int **mat=new int[10][10];

i ovo naravno nece da radi. Nemojte samo odgovore tipa koristi gotove klase za matrice i slicno.

Odgovor se nalazi u konstruktoru moje DM klase!

[ Marko Stankovic @ 31.01.2005. 15:10 ] @
Da, ok je taj nacin ali mi se cini da bi operatorom new trebali da mozemo alocirati visedimenzionalne nizove samo jednim pozivom, pa me interesuje kako je to moguce, ako uopste moze.
[ BaCkSpAcE @ 31.01.2005. 16:31 ] @
Evo workaround ;) Fazon je sto ti matricu ispegla u jedan niz, i na tebi je posle da ga rekonstruises u func()...

Code:

#include <stdio.h>

#define ROWS 10
#define COLUMNS 10

void func(int *mat) {
  int i, j;

  for (i=0; i<10; i++) {
    printf ("\n");
    for (j=0; j<10; j++) {
      printf ("%d ", mat[i*ROWS+j]);
    }
  }
}  


int main() {
  int matrica[ROWS][COLUMNS];
  int i, j;
  
  for (i=0; i<10; i++) 
    for (j=0; j<10; j++)
      matrica[i][j]=i+j;  // popunjavam matricu sa i+j, cisto da ima nesto

  func((int *)matrica);

  return 0;
}
[ Marko Stankovic @ 31.01.2005. 19:17 ] @
Da, problem se moze resiti koriscenjem operatora cast, samo ne vidim razlog zasto "peglas" matricu u niz, sve ce to isto raditi ako u zagradi stavis (int**) odnosno ako funkciju pozivas na sledeci nacin:
Code:


void func(int **mat);

...


int main(){

...
func((int**)matrica);
...
}


mada nekako mi nije bas elegantno :)
[ Buffy @ 31.01.2005. 21:05 ] @
Ja sam pokusao staviti:
Code:

func((int**)matrica);

i sve se lijepo kompajlira,ali dodje do greske prilikom izvodjenja.
Ako "ispeglamo" matricu onda sve savrseno radi.
Zbog cega je to tako izgleda niko ne moze da odgovori!!!
[ Pah-Wrait @ 01.02.2005. 00:25 ] @
Da pokusam da vam pomognem: postoji nekoliko nacina za rad sa matricama.
Ako hoces u cistom C-u: mogu biti staticke i dinamicke (ovo sto si ti hteo da uradis). Kada radis sa dinamickim imas dinamicki dodeljeno parce memorije koje pokazuje dinamicki dodeljenu memoriju. Tu se koristi operator malloc pa sad sta sve ide, zaboravio sam, radim sada sasvim druge stvari, ali ima u Laslovoj knjizi za C finih primera. Nasao sam jedan:
/..
int **a;
int m,n,i,j;
scanf("%d%d", &m, &n);//broj vrsta i kolona
a=malloc (m*sizeof(int*));

for(i=0;i<m;i++)*(a+i)=malloc (n*sizeof(int));// *(a+i) je isto sto i *a, ali sam ih namerno odvojio
I to ti je dinamicka matrica. Ukoliko hoces da koristis matricu u funkcijama, moraju se navesti sve velicine osim poslednje: ako je obican niz, kao argument mozes da stavis samo (a[]); ukoliko je rec o matrici 3*6, onda kao argument mozes da stavis (a[3][])...


Sto se tice matrica u standardnom C++ ima jos vise ali primer koji je Buffy objavila izgleda OK. A ako hoces stvarno da naucis C++ NE KORISTI VEC GOTOVE KLASE!!! TO MOZE KASNIJE KADA NAUCIS DOVOLJNO, PA DA NE GUBIS VREME, ALI AKO HOCES DA ZNAS C++, radi sve sam. Ako hoces da koristis vec gotove stvari i samo da ih ubacuje i rasporedjujes, onda uci VB.
Pozdrav
[ glorius @ 01.02.2005. 01:07 ] @
Hmm... Zanimljivo je i ovo:

// NAPOMENA: u daljem tekstu koristim } umesto ] zbog text-editora ovog foruma

Funkcija(int * pMat)
{
// ......
}

main()
{

int mat{10}{10};

// popunjavanje matrice, bla, bla...

for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
int * pokazivacNaElement = &mat{i}{j};

Funkcija(pokazivacNaElement);
}
}

Ovo sam slucajno otkrio i svidja mi se fora ali sluzi samo za predavanje f-ji element po element. Zatreba nekada...


[ Marko Stankovic @ 01.02.2005. 01:35 ] @
Citat:
Buffy:
i sve se lijepo kompajlira,ali dodje do greske prilikom izvodjenja.
Ako "ispeglamo" matricu onda sve savrseno radi.
Zbog cega je to tako izgleda niko ne moze da odgovori!!!


U pravu si dolazi do greske, nisam to primetio jer nisam startovao program samo sam ga iskompajlirao. U pocetku sam se zbunio gde je problem medjutim posle kraceg razmisljanja video sam da ima sasvim logicno objasnjenje.
Ovaj kod koji je ostavio backspace je dobar u slucaju staticki alociranih matrica, a ovaj moj primer jedino u slucaju dinamickih matrica. Jer staticka matrica u memoriji izgleda kao niz duzine n*m (ako je n broj kolona a m broj vrsta) dok je dinamicka pokazivac na niz pokazivaca od kojih svaki pokazuje na po jedan niz koji mogu biti bilo gde u memoriji. Znaci iz adresne aritmetike imamo:

matrica[x][j]=*(*(matrica+x)+j)

e sada kada je staticka matrica mi vec sa *(matrica+x) uzimamo int (jer je staticka matrica ustvari samo niz u memoriji odnosno matrica ce biti tipa int*) pa se ovo +j i * izvrsavaju nad podatkom tipa int i zbog toga program puca sa primerom koji sam ja naveo. Tako da je u tom slucaju ispravno da pisemo matrica[i*ROWS+j] i da ime matrice prenesemo kao int*.
Naravno backspaceov kod nece da radi sa dinamickom matricom jer imamo:

matrica[i*ROWS+j]=*(matrica+i*ROWS+j)

sto ce naravno da izleti iz niza pokazivaca na koji pokazuje matrica a i kada bi cak bilo u opsegu uzelo bi samo pokazivac na niz integera a ne broj iz tog niza. Nacrtao sam cak i malu slicicu koja prikazuje razliku izmedju statickih i dinamickih matrica i zbog cega je cela ova prica.

p.s. samo nemojte da se smejete crtezu :) i naravno levo je staticka a desno dinamicka matrica.

[ Buffy @ 01.02.2005. 12:07 ] @
Svaka cast Marko,izgleda da si rijesio problem.
Sad nam jedino preostaje da koristimo dinamicke matrice!!!
Citat:
Pah-Wrait:...primer koji je Buffy objavila...

Primjer koji je Buffy objavio!!!
[ BaCkSpAcE @ 01.02.2005. 14:35 ] @
Ja sam onaj primer napisao za Buffy-jev kod koji je dao u prvom postu
Code:

void funk(int **a)
{
    //...
}

int main()
{
    int mat[10][10];
    funk(mat);
    return 0;
}


I za njegove potrebe, tj. ono sto je on trazio, ovaj primer radi savrseno jer on koristi staticku matricu (int mat[10][10]), svaki element ove matrice se nalazi u memoriji jedan iza drugog, zato moze onako da se "ispegla"...
[ leka @ 03.02.2005. 14:02 ] @
Buffy, ako ti se ne svidja da imas
Code:

void funk(int a[][10])

onda mozes malo promeniti svoj kod da izgleda ovako:
Code:

void funk(int **a)
{
  //...
}

int main()
{
  // Umesto: int mat[10][10];
  // imas ovo:
  int **mat = new int*[10]; 
  funk(mat);
  return 0;
}

Ovaj kod je skoro isti kao onaj koji si dao na pocetku s malom razlikom koja je oznacena u kodu. Meni se vise svidja void funk(int a[][10]) ... ali to je izgleda pitanje ukusa...
[ blaza @ 03.02.2005. 16:20 ] @
Da li si siguran leko da je isto?
Nisi alocirao prostor za 100 int-ova, vec si alocirao prostor za 10 pointera na int-ove.

Mozda nesto ovako:
Code:

const int SIZE = 10;
void funk(int* b, int size){
     b[x * size + y] = ... //b[x][y]
}
...
int a[SIZE][SIZE]; 
int* mat = reinterpret_cast<int*>(a);
funk(mat, SIZE);
[ Buffy @ 03.02.2005. 20:04 ] @
Dejane,taj nacin moze da pomogne ali ipak nije to to.
Zakljucio sam da su dinamicki nizovi najbolje rjesenje.
Pozdrav!!!
[ Dragi Tata @ 03.02.2005. 20:13 ] @
Ako unapred znaš dimenzije niza, statički nizovi su najčešće bolje rešenje. Ne samo što se mnogo brže alocira/dealocira memorija za njih, već nema ni opasnosti od curenja memorije.
[ tosa @ 04.02.2005. 10:24 ] @
Citat:
leka
Code:

  // Umesto: int mat[10][10];
  // imas ovo:
  int **mat = new int*[10]; 



Ovo nece da moze :)
Alociran ti je samo jedan niz, a ne niz nizova (citaj matrica)...
Mozda radi na linuxu, al' na windows-u nece sigurno :)
[ Buffy @ 04.02.2005. 16:59 ] @
Citat:
Dragi Tata: Ako unapred znaš dimenzije niza, statički nizovi su najčešće bolje rešenje. Ne samo što se mnogo brže alocira/dealocira memorija za njih, već nema ni opasnosti od curenja memorije.

Ali zato je veca kolicina memorije sa slobodnog skladista!
[ Dragi Tata @ 04.02.2005. 17:24 ] @
Najčešće jeste, ali ne mora da znači. To zavisi od OS-a, a često je moguće i programski podesiti veličinu stack-a.