View Full Version : [C] Passare sottomatrice ad una funzione
Salve ragazzi.
Ho una funzione che prende in ingresso un float**, rappresentante una matrice allocata con malloc, e la dimensione n della matrice stessa . Questa funzione dovrebbe richiamare due volte se stessa su una matrici di dimensioni n/2: la prima volta sulla sottomatrice in alto a sinistra (formata dalle prime n/2 righe e le prime n/2 colonne) e la seconda volta sulla sottomatrice in basso a destra (formata dalle ultime n/2 righe e le ultime n/2 colonne).
Non penso francamente di dover effettuare una copia in altre due matrici per fare questo.. Ho pensato di passare un intero relativo alla posizione iniziale (0 nel primo caso, n/2 nel secondo) ma mi complicherebbe le cose visto che l'algoritmo è abbastanza complesso ed in questo modo so già che farei un casino di errori :fagiano:
C'è modo di passare direttamente un puntatore alla sottomatrice, come se fosse una normale matrice? :D
Vi ringrazio per la pazienza :)
Up ragazzi. Anche un semplice "no, non è possibile", così mi metto l'anima in pace e inizio a correggere le varie funzioni che ho fatto passando gli indici :D
Ho provato a passare alla funzione tipo &x[2][2], ed ho provato ad utilizzare questo come se fosse una matrice, ma ovviamente non funziona, immagino perchè &x[2][2] è un puntatore ad intero mentre una matrice è rappresentabile come un puntatore doppio!
clockover
22-02-2011, 01:27
Te lo dico subito... non lo so e non ci avevo mai pensato prima, ma siccome mi sono incuriosito ho fatto delle prove con una matrice 2x2
printf("%d\n", &tmp[0][0]);
printf("%d\n", &tmp[0][1]);
printf("%d\n", &tmp[1][0]);
printf("%d\n", &tmp[1][1]);
risultati
1606417088
1606417092
1606417096
1606417100
quindi se io volessi puntare direttamente al valore contenuto nella cella tmp[1][0] posso utilizzare l'indirizzo di memoria 1606417096
l'elemento successivo ovviamente è semplice, basta incrementare di 4 bytes. Ma se dobbiamo cambiare riga, cioè supponiamo che abbiamo anche la riga 2, non basta più incrementare di 4 bytes, ma di 8 (in questo semplice caso)
Quindi la regola dovrebbe essere
1) mantenere memorizzata la dimensione originale della matrice
2) incrementare di X bytes (a seconda del puntatore) per scorrere la colonna
3) incrementare di X*dimensione originale per cambiare la riga
a tutto il resto ci si pensa domani dato che mi sono appena sbranato un piatto di pasta e una birrozza :D :D
Ps
ho supposto la matrice quadrata e fatto le prove con int
malocchio
22-02-2011, 02:16
Salve ragazzi.
Ho una funzione che prende in ingresso un float**, rappresentante una matrice allocata con malloc, e la dimensione n della matrice stessa . Questa funzione dovrebbe richiamare due volte se stessa su una matrici di dimensioni n/2: la prima volta sulla sottomatrice in alto a sinistra (formata dalle prime n/2 righe e le prime n/2 colonne) e la seconda volta sulla sottomatrice in basso a destra (formata dalle ultime n/2 righe e le ultime n/2 colonne).
Non penso francamente di dover effettuare una copia in altre due matrici per fare questo.. Ho pensato di passare un intero relativo alla posizione iniziale (0 nel primo caso, n/2 nel secondo) ma mi complicherebbe le cose visto che l'algoritmo è abbastanza complesso ed in questo modo so già che farei un casino di errori :fagiano:
C'è modo di passare direttamente un puntatore alla sottomatrice, come se fosse una normale matrice? :D
Vi ringrazio per la pazienza :)
Presupposto che la funzione che vuoi creare ha un header del tipo
<qualcosa> funzione (float **matrice, int dimensione)
se la matrice è quadrata, altrimenti le dimensioni da passare sono due ;)
Allora, quel float** indica che la matrice è allocata come un array di array.
Più o meno:
_ _____________
|0| -> |_____________|
|1| -> |_____________|
|2| -> |_____________|
|3| -> |_____________|
^
|
|matrice|La variabile matrice contiene l'indirizzo dell'array verticale di sinistra, che contiene gli indirizzi dei quattro array orizzontali di destra, ciascuno dei quali contiene quattro variabili float. Con l'aritmetica dei puntatori si possono fare parecchie belle cose, ma per il tuo caso servirà qualcosa di più potente.
Richiamare funzione sul quadrante alto/sx è piuttosto semplice:
funzione(matrice, n/2);L'indirizzo di partenza è lo stesso della matrice più grande, ma il numero di righe e il numero di colonne è dimezzato.
L'altro caso è più complicato, perché tramite i puntatori puoi passare ad una funzione una matrice escludendo le prime n righe usando l'operatore +, ma non puoi "tagliare" un certo numero di colonne a sinistra (per tagliarle a destra basta diminuire la dimensione).
Secondo me il metodo più "facile" per fare quello che vuoi fare tu è allocare un array... vabbè te lo scrivo in C che forse risulta più chiaro:
<qualcosa> funzione (float **m, int n) {
funzione(m, n/2);
float **t = (float**) malloc(n / 2 * sizeof(float*));
for (int i = 0; i < n/2; i++) {
t[i] = m[n/2 + i] + n/2;
}
funzione(t, n/2);
free(t);
}
Un esempio: matrice 4x4, la struttura è uguale al disegnino postato prima.
Io non faccio altro che allocare un array di puntatori di dimensione 2, chiamato "t".
t[0] = m[2] + 2
t[1] = m[3] + 2
o anche
t[0] = &m[2][2]
t[1] = &m[3][2]
m[2][2] e m[3][2] sono le celle sulla prima colonna della sotto-matrice in basso a destra. In questo modo, passando t sarà come passare (per indirizzo) il quarto quadrante della matrice grande.
A tua disposizione se hai dubbi :D
edit: ah, dimenticavo, esiste un metodo che sarebbe anche migliore del papiro che ti ho scritto sopra, ovvero aggiungere un terzo argomento a funzione che specifica da quale riga/colonna partire:
<qualcosa> funzione (float **m, int offset, int dim) {
funzione(m, offset, dim/2);
funzione(m, offset + dim/2, dim/2);
}
Vi ringrazio per le risposte :D
Vabbè dunque mi sembra di capire che non ci siano modi banali per fare quello che avevo in mente... Entrambi i metodi postati complicherebbero comunque le cose, quindi alla fine ho riscritto il codice con delle variabili di offset come evidenziato da malocchio (era quello che avevo in mente di fare :D ). Stranamente non ho fatto errori di distrazioni ed il tutto ha funzionato :mbe: ancora non ci credo :sofico:
Vi ringrazio per l'aiuto, siete stati gentilissimi :D
malocchio
22-02-2011, 22:30
Stranamente non ho fatto errori di distrazioni ed il tutto ha funzionato :mbe: ancora non ci credo :sofico:
Con la ricorsione il codice da scrivere è così poco che se è sbagliato te ne accorgi subito ;).
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.