Indice del forum Olimpo Informatico
I Forum di Zeus News
Leggi la newsletter gratuita - Attiva il Menu compatto
 
 FAQFAQ   CercaCerca   Lista utentiLista utenti   GruppiGruppi   RegistratiRegistrati 
 ProfiloProfilo   Messaggi privatiMessaggi privati   Log inLog in 

    Newsletter RSS Facebook Twitter Contatti Ricerca
* [C++] matrici "generali" come argomento di funzi
Nuovo argomento   Rispondi    Indice del forum -> Programmazione
Precedente :: Successivo  
Autore Messaggio
ZTP
Eroe
Eroe


Registrato: 17/02/09 23:40
Messaggi: 60
Residenza: Terra, terzo pianeta dal Sole

MessaggioInviato: 08 Apr 2009 19:13    Oggetto: * [C++] matrici "generali" come argomento di funzi Rispondi citando

Vorrei creare una funzione che abbia come argomenti una matrice bidimensionale e il suo numero di righe e colonne, per poi stamparla. Il problema è che quando dichiaro la funzione devo necessariamente indicare il numero di colonne, e se provo a passare una matrice diversa -anche più piccola!- il compilatore mi segnala un errore -.-
In pratica, se questa è la funzione
Citazione:
void StampaMatrice(int mat[][10], int rig, int col)
{
for(int i = 0; i < rig; i++)
{
for(int j = 0; j < col; j++)
cout << mat[i][j] << endl;
}
}

Posso usarla solo e unicamente per stampare matrici di 10 colonne. C'è un modo per rendere la funzione 'generale'? Probabilmente non è niente di astronomico ma sono ancora agli inizi T_T Grazie in anticpo!
Top
Profilo Invia messaggio privato
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 21:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 08 Apr 2009 20:52    Oggetto: Rispondi citando

Devi usare i puntatori. Come primo parametro della funzione avrai un int**, la matrice dovrà essere allocata dinamicamente fuori dall afunzione e poi passata alla stessa. Gli ultimi due parametri ti servono ancora.

L'ultima modifica di freemind il 01 Lug 2009 23:38, modificato 1 volta
Top
Profilo Invia messaggio privato
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 21:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 08 Apr 2009 21:00    Oggetto: Rispondi citando

Mi son reso conto che il post di prima è praticamente inutile.
Un po' di codice:
Codice:

#include <iostream.h>
void StampaMatrice(int **mat,int righe,int colonne)
{
   for (int i=0;i<righe;++i)
   {
      for (int j=0;j<colonne;++j)
      {
         cout<<mat[i][j]<<" ";
      }
      cout<<endl;
   }
}
void main()
{
   int **m;// puntatore doppio
   m=new int*[3];  // un array di array di 3 elementi
   for (int i=0;i<3;++i)  // allochi i 3 array dandogli dimensione 3
      m[i]=new int[3];
// qui inizializzi la matrici e poi...

// chiami la tua funzione
   StampaMatrice(m,3,3);
}


Top
Profilo Invia messaggio privato
ZTP
Eroe
Eroe


Registrato: 17/02/09 23:40
Messaggi: 60
Residenza: Terra, terzo pianeta dal Sole

MessaggioInviato: 09 Apr 2009 10:29    Oggetto: Rispondi citando

Wow, grazie *Q* Esattamente quello che mi serviva. Avevo provato a usare i puntatori ma più che litigarci non ho fatto Mad Invece adesso la cosa è più chiara. Grazie!
Top
Profilo Invia messaggio privato
SverX
Supervisor Macchinisti
Supervisor Macchinisti


Registrato: 25/03/02 12:16
Messaggi: 11810
Residenza: Tokelau

MessaggioInviato: 09 Apr 2009 12:26    Oggetto: Rispondi citando

freemind: perchè usi puntatore a puntatore a int e non direttamente un puntatore a int? Qualcosa mi sfugge, sono certo che possa funzionare anche solo con un puntatore a int...

edit: anzi, siamo sicuri che funzioni? Quando usi
Citazione:
mat[i][j]

tu parti dal principio che il compilatore sappia quanti elementi ci sono in ogni riga della matrice, e questo è vero se la matrice è definita in compile time (come nel tuo esempio), ma non lo è se la matrice fosse definita in runtime...
Top
Profilo Invia messaggio privato HomePage
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 21:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 09 Apr 2009 13:13    Oggetto: Rispondi citando

New alloca a run-time non in compile-time. Lascia perdere le dimesioni che io ho usato come costanti, era perchè ero di volata.
In teoria avrei dovuto usare due parametri inizializzati in qualche modo per contenere i numeri di righe e di colonne.

Uso il doppio puntatore (quindi un puntatore ad un array di puntatori) per poter concettualmente rappresentare l'array bi-dimensionale come matrice in due dimensioni.
In questo modo potremmo arrivare a creare una "matrice anomala" in cui le righe hanno un numero diverso di colonne, ma questa è un'altra storia.
Il compilatore non sa quanti elementi ci sono nelle righe e nelle colonne ma utilizzando nella funzione StampaMatrice i due parametri sono sicuro che se non faccio viaggiare i puntatori oltre allora non esco dalla matrice.

Hai ragione quando dici che si potrebbe usare un puntatore int*, anzi, sarebbe il modo più corretto anche perchè tanto in ram la memoria viene allocata consecutivamente: facendo così però avrei dovuto comunque ragionare con un vettore e non con una matrice, allontanandomi dal concetto "matematico" di matrice bi-dimensionale.
Top
Profilo Invia messaggio privato
SverX
Supervisor Macchinisti
Supervisor Macchinisti


Registrato: 25/03/02 12:16
Messaggi: 11810
Residenza: Tokelau

MessaggioInviato: 09 Apr 2009 14:25    Oggetto: Rispondi citando

freemind ha scritto:
New alloca a run-time non in compile-time


Chiaro, io intendevo che la dimensione della riga è dichiarata nel sorgente e quindi 'risolta' in compile time
Codice:
m=new int*[3];


Per il resto ho capito il tuo discorso sul concetto matematico, rimane però che per poter avere una funzione che lavori su una matrice n*m dove sia n che m saranno dichiarate solo durante l'esecuzione del programma, dovrai obbligatoriamente usare un int* e puntare all'elemento i-j-esimo dell'array (la matrice in memoria) usando qualcosa del tipo
Codice:
mat[i*n+j]


In questo modo la funzione lavorerà su matrici di qualunque dimensione scelta in run-time Smile

Ciao
Top
Profilo Invia messaggio privato HomePage
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 21:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 09 Apr 2009 15:55    Oggetto: Rispondi citando

SverX ha scritto:

...
Chiaro, io intendevo che la dimensione della riga è dichiarata nel sorgente e quindi 'risolta' in compile time
Codice:
m=new int*[3];

...

Ok, tieni conto che al posto del 3 visto che stiamo parlando di memoria dinamica poteva essere chiamata una variabile e quindi anche dimensione diventerebbe dinamica.

Il tuo discorso sull'uso del puntatore int* è corretto, io però pensavo che ZTP si limitasse alle matrici bi-dimensionali.
Bisogna però anche tener presente che l'utilizzo di una matrice "generica" come la intendi tu ha la sfiga di aver a quel punto anche il numero di indici dinamico e diventerebbe non semplice/veloce da gestire.

Oltre le 3 dimensioni secondo me vale la pensa cambiare struttura.

Miao
Top
Profilo Invia messaggio privato
SverX
Supervisor Macchinisti
Supervisor Macchinisti


Registrato: 25/03/02 12:16
Messaggi: 11810
Residenza: Tokelau

MessaggioInviato: 09 Apr 2009 17:00    Oggetto: Rispondi citando

aspe... io intendevo generica ma comunque bidimensionale... generica solo nel valore delle (2) dimensioni...

freemind ha scritto:
tieni conto che al posto del 3 visto che stiamo parlando di memoria dinamica poteva essere chiamata una variabile e quindi anche dimensione diventerebbe dinamica.


non l'ho capita... mi fai un esempio? Tu dici che se quel 3 fosse una variabile, poi a run-time il codice generato dal compilatore è in grado di accedere all'elemento
Codice:
mat[i][j]
?

O i compilatori hanno cambiato funzionamento (sarò rimasto indietro?) oppure mi sa che non funzionerebbe proprio...

Se hai un attimo prova a compilare con
Codice:
m=new int*[n];

con n letto da input utente, poi vediamo che dice...
Top
Profilo Invia messaggio privato HomePage
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 21:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 09 Apr 2009 17:15    Oggetto: Rispondi citando

Il codice che ti posto è stato compilato tramite g++ 4.1 su Ubuntu 7.10 e funziona. Anche se il mio c++ è un po' arrugginito io mi ricordo che ho sempre fatto così (oppure usavo un indice solo seguendo il tuo discorso) ed è sempre andato.
Codice:

#include <iostream>

using namespace std;

void StampaMatrice(int **mat,int righe,int colonne)
{
   for (int i=0;i<righe;++i)
   {
      for (int j=0;j<colonne;++j)
      {
         cout<<mat[i][j]<<" ";
      }
      cout<<endl;
   }
}
int main()
{
   int **m;// puntatore doppio
   
   int righe=0,colonne=0;
   int i=0,j=0;

   cout<<"Numero di righe: ";
   cin>>righe;
   
   cout<<"Numero di colonne: ";
   cin>>colonne;

   m=new int*[righe];  // un array di array di 3 elementi
   
   for (i=0;i<righe;++i)  // allochi i 3 array dandogli dimensione 3
      m[i]=new int[colonne];
   
   for (i=0;i<righe;++i)
      for (j=0;j<colonne;++j)
      {
         cout<<"Elemento["<<i<<","<<j<<"]: ";
         cin>>m[i][j];
      }

   StampaMatrice(m,righe,colonne);
}

Forse ti stai confondendo con il caso:
Codice:

...
int m[righe][colonne];// questo è scorretto!
...

Lì la matrice è risolta dal compilatore quindi o righe e colonne sono due costanti oppure non si compila.
Top
Profilo Invia messaggio privato
SverX
Supervisor Macchinisti
Supervisor Macchinisti


Registrato: 25/03/02 12:16
Messaggi: 11810
Residenza: Tokelau

MessaggioInviato: 09 Apr 2009 18:52    Oggetto: Rispondi citando

Wow. Shocked

Ok, ci ho messo un po' ma adesso ho capito.

E adesso mi è chiaro anche perchè usi il puntatore a puntatore a interi... in pratica perchè la matrice non la allochi in memoria come 'un sol blocco' di righe*colonne elementi interi di seguito, ma la allochi come un array di colonne elementi, nel quale ogni elemento è un puntatore ad un array lungo righe interi. C'ho preso? Smile

E' curioso. Non l'avrei mai pensato così. Si vede che sono troppo abituato con il C (e anche sono troppo abituato a pensare che qualunque matrice n-dimensionale è comunque possibile trattarla come un array...)

Grazie per il tempo speso a chiarire il mio dubbio

Ciao
Top
Profilo Invia messaggio privato HomePage
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 21:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 09 Apr 2009 19:40    Oggetto: Rispondi citando

SverX ha scritto:
in pratica perchè la matrice non la allochi in memoria come 'un sol blocco' di righe*colonne elementi interi di seguito, ma la allochi come un array di colonne elementi, nel quale ogni elemento è un puntatore ad un array lungo righe interi. C'ho preso? Smile

In realtà alloco un array di righe elementi e oguno è un puntatore ad un array di colonne elementi, c++ è row-based e comunque se noti, nel codice la prima allocazione è con righe.
Uno schemino potrebbe essere:
R0->C0 C1 C2...Ccolonne
R1->C0 C1 C2...Ccolonne
...
Rrighe->C1 C2...Ccolonne

Per il resto c'hai preso!
Io amo molto sia il C che il C++, sono i miei linguaggi preferiti anche se purtroppo ora non li uso praticamente mai!

bau!
Top
Profilo Invia messaggio privato
SverX
Supervisor Macchinisti
Supervisor Macchinisti


Registrato: 25/03/02 12:16
Messaggi: 11810
Residenza: Tokelau

MessaggioInviato: 10 Apr 2009 10:11    Oggetto: Rispondi

freemind ha scritto:
In realtà alloco un array di righe elementi e oguno è un puntatore ad un array di colonne elementi, c++ è row-based e comunque se noti, nel codice la prima allocazione è con righe.


Sì, ho confuso i due termini, mi capita spesso Embarassed
Top
Profilo Invia messaggio privato HomePage
Mostra prima i messaggi di:   
Nuovo argomento   Rispondi    Indice del forum -> Programmazione Tutti i fusi orari sono GMT + 2 ore
Pagina 1 di 1

 
Vai a:  
Non puoi inserire nuovi argomenti
Non puoi rispondere a nessun argomento
Non puoi modificare i tuoi messaggi
Non puoi cancellare i tuoi messaggi
Non puoi votare nei sondaggi