[C] Problema con stampa matrice
Ciao, ragazzi ! Ho terminato un progetto (abbastanza lungo) in C in cui devo compiere diverse operazioni sulle matrici attraverso l'utilizzo di una lista di liste (in cui andranno solo elementi di tipo float), non ho alcun problema nella compilazione. Quando eseguo il programma inserisco i dati all'interno della matrice, ma nel momento in cui si esegue la trasposta, vengono stampati tanti 0 quanti sono gli elementi, non sto riuscendo a capire dove sia l'errore, credo nella funzione di stampa stampaMatrice().
Provo a postare qui parte del codice, perché è davvero lungo :
main.c :
funzioni.h :
funzioni.c :
Spero qualcuno mi aiuterà, grazie per la pazienza.
Provo a postare qui parte del codice, perché è davvero lungo :
main.c :
main() { //...................................................................... //TRASPOSTA DI UNA MATRICE //...................................................................... printf("*** TRASPOSTA DI UNA MATRICE ***\n\n\n"); Matrice a; Matrice a_t; //INIZIALIZZAZIONE MATRICE DI PARTENZA printf("Inizializzazione della matrice di partenza (MATRICE A)\n\n"); inizializzaMatrice( &a, acquisisciDimensione("Inserire il numero di righe: "), acquisisciDimensione("Inserire il numero di colonne: ") ); acquisisciValori( &a, leggiRighe(a), leggiColonne(a) ); //INIZIALIZZAZIONE TRASPOSTA inizializzaMatrice( &a_t, leggiColonne(a), leggiRighe(a) ); trasposta(a, &a_t); //STAMPA DELLE MATRICI printf("\n\nMATRICE\n"); stampaMatrice( &a, leggiRighe(a), leggiColonne(a) ); printf("MATRICE TRASPOSTA\n"); stampaMatrice( &a_t, leggiRighe(a_t), leggiColonne(a_t) );
funzioni.h :
typedef struct Elemento_lista { float valore; struct Elemento_lista *successivo; } Elemento_lista; typedef struct Elemento_lista Nodo_lista; typedef struct Elemento_lista *Elem_lista; typedef struct Elemento_lista_puntatori { Elem_lista valore; struct Elemento_lista_puntatori *successivo_lista; } Elemento_lista_puntatori; typedef struct Elemento_lista_puntatori Nodo_lista_puntatori; typedef struct Elemento_lista_puntatori *Elem_lista_puntatori; typedef struct Matrice { int numero_righe; int numero_colonne; Elem_lista_puntatori val; } Matrice; typedef enum { FALSE, TRUE } boolean; // FUNZIONI MATRICE int acquisisciDimensione(char []); int leggiRighe(Matrice); int leggiColonne(Matrice); void scriviRighe(Matrice *, int); void scriviColonne(Matrice *, int); void inizializzaMatrice(Matrice *, int, int); void acquisisciValori(Matrice *, int, int); float leggiMatrice(Matrice, int, int); void scriviMatrice(Matrice *, int, int, float); void stampaMatrice(Matrice *, int, int); boolean controlloProd(int, int); float acquisisciScalare(); void trasposta(Matrice, Matrice *); // FUNZIONI LISTA void* inizializzaLista(); int listaVuota(Elem_lista); int listaPuntatoriVuota(Elem_lista_puntatori); Elem_lista_puntatori inserimentoListaPuntatori(Elem_lista_puntatori, int, int); Elem_lista leggiLista(Elem_lista, int, int); Elem_lista_puntatori leggiListaPuntatori(Elem_lista_puntatori, int, int); Elem_lista inserimentoLista(Elem_lista, int, int, float);
funzioni.c :
float val; int acquisisciDimensione(char s[]) { int num; printf("%s", s); scanf("%d", &num); return num; } int leggiRighe (Matrice m) { return m.numero_righe; } int leggiColonne (Matrice m) { return m.numero_colonne; } void scriviRighe(Matrice *m, int r) { m->numero_righe = r; } void scriviColonne(Matrice *m, int c) { m->numero_colonne = c; } void inizializzaMatrice(Matrice *m, int r, int c) { int i; scriviRighe(m, r); scriviColonne(m, c); m->val = inizializzaLista(); } void acquisisciValori(Matrice *m, int r, int c) { int i, j; printf("\nInserisci i valori della matrice separati da uno spazio;\n"); printf("Premi invio al termine di ogni riga;\n\n"); for(i = 0; i < r; i++) { for(j = 0; j < c; j++) { scanf("%f", &val); scriviMatrice(m, i, j, val); } } } float leggiMatrice(Matrice m, int r, int c) { Elem_lista_puntatori dato; Elem_lista puntatore_valore; dato = leggiListaPuntatori(m.val, r, 0); puntatore_valore = leggiLista(dato->valore, c, 0); return puntatore_valore->valore; } void scriviMatrice(Matrice *m, int r, int c, float val) { Elem_lista_puntatori dato; dato = leggiListaPuntatori(m->val, r, 0); if(dato == NULL) m->val = inserimentoListaPuntatori(m->val, r, 0); dato = leggiListaPuntatori(m->val, r, 0); dato->valore = inserimentoLista(dato->valore, c, 0, val); } void stampaMatrice(Matrice *m, int r, int c) { int i, j; for(i = 0; i < r; i++) { for(j = 0; j < c; j++) { printf( "%5.2f ", leggiMatrice(*m, i, j) ); } printf("\n"); } printf("\n\n"); } boolean controlloProd (int m, int n) { boolean c = FALSE; if(m == n) c = TRUE; return c; } float acquisisciScalare() { float scal; printf("Inserire di seguito un valore scalare: "); scanf("%f", &scal); return scal; } void* inizializzaLista() { return NULL; } int listaVuota(Elem_lista lista) { if(lista == NULL) return 1; else return 0; } int listaPuntatoriVuota(Elem_lista_puntatori lista) { if(lista == NULL) return 1; else return 0; } Elem_lista_puntatori inserimentoListaPuntatori(Elem_lista_puntatori lista, int posizione, int posizione_corrente) { Elem_lista_puntatori dato; if( listaPuntatoriVuota(lista) ) { dato = (Elem_lista_puntatori)malloc( sizeof(Nodo_lista_puntatori) ); dato->valore = inizializzaLista(); dato->successivo_lista = NULL; return dato; } else { if(posizione_corrente == posizione) { dato = (Elem_lista_puntatori)malloc( sizeof(Nodo_lista_puntatori) ); dato->valore = inizializzaLista(); dato->successivo_lista = lista->successivo_lista; lista->successivo_lista = dato; return lista; } else { posizione_corrente++; lista->successivo_lista = inserimentoListaPuntatori(lista->successivo_lista, posizione, posizione_corrente); return lista; } } } Elem_lista leggiLista(Elem_lista lista, int posizione, int posizione_corrente) { if( listaVuota(lista) ) return lista; else { if(posizione_corrente == posizione) return lista; else { posizione_corrente++; lista = leggiLista(lista->successivo, posizione, posizione_corrente); return lista; } } } Elem_lista_puntatori leggiListaPuntatori(Elem_lista_puntatori lista, int posizione, int posizione_corrente) { if( listaPuntatoriVuota(lista) ) return lista; else { if(posizione_corrente == posizione) return lista; else { posizione_corrente++; lista = leggiListaPuntatori(lista->successivo_lista, posizione, posizione_corrente); return lista; } } } void trasposta(Matrice m, Matrice *m_t) { int i, j; for(i = 0; i < leggiRighe(*m_t); i++) { for(j = 0; j < leggiColonne(*m_t); j++) { scriviMatrice( m_t, i, j, leggiMatrice(m, j, i) ); } } } Elem_lista inserimentoLista(Elem_lista lista, int posizione, int posizione_corrente, float val) { Elem_lista dato; if( listaVuota(lista) ) { dato = (Elem_lista)malloc( sizeof(Nodo_lista) ); dato->valore = val; dato->successivo = NULL; return dato; } else { if(posizione_corrente == posizione) { dato = (Elem_lista)malloc( sizeof(Nodo_lista) ); dato->valore = val; dato->successivo = lista->successivo; lista->successivo = dato; return lista; } else { posizione_corrente++; lista->successivo = inserimentoLista(lista->successivo, posizione, posizione_corrente, val); return lista; } } }
Spero qualcuno mi aiuterà, grazie per la pazienza.

Risposte
Spero si tratti di un esercizio e non di un progetto vero. Credo sia in assoluto il metodo peggiore per implementare una matrice bidimensionale. Nessuno dei vantaggi delle liste sugli array si applica in questo caso.
Se le altre matrici le stampa correttamente, non credo che il problema sia nella funzione che stampa la matrice, ma in quella che calcola la trasposta. In effetti, la funzione di stampa mi sembra corretta. Anche se non capisco perché stai passando il numero di righe e colonne come argomento quando queste informazioni sono già contenute nella struttura della matrice. Fossi in te proverei a fare il debug nella funzione che calcola la trasposta. Sei certo che tutte le altre funzioni di base siano corrette? Domani ci do una occhiata migliore che adesso è tardi.
Se le altre matrici le stampa correttamente, non credo che il problema sia nella funzione che stampa la matrice, ma in quella che calcola la trasposta. In effetti, la funzione di stampa mi sembra corretta. Anche se non capisco perché stai passando il numero di righe e colonne come argomento quando queste informazioni sono già contenute nella struttura della matrice. Fossi in te proverei a fare il debug nella funzione che calcola la trasposta. Sei certo che tutte le altre funzioni di base siano corrette? Domani ci do una occhiata migliore che adesso è tardi.
Mi associo alla perplessità di apatriarca: se questo è un progetto reale l'unica opzione possibile è buttare via tutto il codice e ri-incominciare usando un design basato sugli array mono-dimensionali. Il tuo design nasconde molto gli errori, è difficile da gestire e ha vantaggi in operazioni che, in algebra lineare, non hanno alcun senso. In pratica fa pena. In termini di performance potrebbe essere facilmente battuto da un codice scritto in un paio di ore da un programmatore di media esperienza.
Se invece è proposto da un professore allora fa pena lui
(come professore ovviamente).
Se invece è proposto da un professore allora fa pena lui

Ciao, grazie ad entrambi per avermi risposto ! Qualunque critica / opinione è sempre ben accetta !
Questo è un progetto che dovrei consegnare quanto prima al professore per poter continuare a frequentare il corso ed a sostenere le altre prove più difficili, ma credo che sarò fuori, perché purtroppo è da una settimana che sto lavorando su questo progetto che come dite voi credo sia proprio da buttar via e rifare tutto.
Lo scopo del prof è quello di farci esercitare con tutti i tipi di strutture, applicate sempre alla matrice ; infatti le varie operazioni sulla matrice (trasposta, somma, norma, differenza, ...) sono riuscito ad implementarle (senza problemi) con :
- vettore multidimensionale ;
- vettore monodimensionale ;
- puntatore singolo ;
- puntatore doppio ;
- lista semplice ;
- l'ultimo esercizio, cioè questo, è con una lista di liste ; lo scopo è di creare una lista di puntatori, ciascuno dei quali punta a sua volta ad una lista di elementi di tipo float. Le liste avranno lunghezza variabile e sono preferite all'utilizzo dei vettori per ottimizzare l'uso della memoria ( allocando di volta in volta lo spazio necessario per i dati con la malloc() ).
Questo è in teoria ciò che dovrei fare, quindi ho preso il codice della lista semplice funzionante e l'ho modificato nelle strutture dei dati utilizzate (3 strutture anziché 2 : la struttura dal dato 'Matrice', la struttura della lista di puntatori e quella della lista effettiva di elementi float).
Credevo fosse più semplice, ma evidentemente mi sbagliavo. Ho provato ad eliminare la funzione interna 'acquisisciDimensione()' per rendere un po' più snello il codice, ma non so come fare ora a passare il valore del numero di righe e di colonne..
Questo è un progetto che dovrei consegnare quanto prima al professore per poter continuare a frequentare il corso ed a sostenere le altre prove più difficili, ma credo che sarò fuori, perché purtroppo è da una settimana che sto lavorando su questo progetto che come dite voi credo sia proprio da buttar via e rifare tutto.
Lo scopo del prof è quello di farci esercitare con tutti i tipi di strutture, applicate sempre alla matrice ; infatti le varie operazioni sulla matrice (trasposta, somma, norma, differenza, ...) sono riuscito ad implementarle (senza problemi) con :
- vettore multidimensionale ;
- vettore monodimensionale ;
- puntatore singolo ;
- puntatore doppio ;
- lista semplice ;
- l'ultimo esercizio, cioè questo, è con una lista di liste ; lo scopo è di creare una lista di puntatori, ciascuno dei quali punta a sua volta ad una lista di elementi di tipo float. Le liste avranno lunghezza variabile e sono preferite all'utilizzo dei vettori per ottimizzare l'uso della memoria ( allocando di volta in volta lo spazio necessario per i dati con la malloc() ).
Questo è in teoria ciò che dovrei fare, quindi ho preso il codice della lista semplice funzionante e l'ho modificato nelle strutture dei dati utilizzate (3 strutture anziché 2 : la struttura dal dato 'Matrice', la struttura della lista di puntatori e quella della lista effettiva di elementi float).
Credevo fosse più semplice, ma evidentemente mi sbagliavo. Ho provato ad eliminare la funzione interna 'acquisisciDimensione()' per rendere un po' più snello il codice, ma non so come fare ora a passare il valore del numero di righe e di colonne..
Il tuo codice, una volta aggiunta la parentesi graffa alla fine del main (che ti eri dimenticato di copiare) e una volta aggiunte le librerie corrette per poter usare printf/scanf e malloc (hai tolto le librerie incluse nei vari codici che hai postato), funziona correttamente per i due/tre test che ho fatto. A questo punto, o il problema è legato a qualcosa che non hai postato, oppure al tuo compilatore/sistema.
Volendo comunque fare qualche osservazione veloce:
1. L'ordine in cui gli argomenti passati ad una funzione vengono valutati non è definito dallo standard ed è lasciato ad ogni compilatore. E' quindi buona norma non dare per scontato un particolare ordine di valutazione. Non c'è insomma alcuna garanzia nel tuo codice che nelle seguenti righe
vengano richieste prima le righe e poi le colonne o viceversa. E' normalmente meglio scrivere qualcosa come:
Continuo a non capire però perché passi tutte le volte il numero di righe e colonne come argomenti quando puoi richiamare leggiRighe e leggiColonne dentro alla funzione per ottenere le stesse informazioni.
Volendo comunque fare qualche osservazione veloce:
1. L'ordine in cui gli argomenti passati ad una funzione vengono valutati non è definito dallo standard ed è lasciato ad ogni compilatore. E' quindi buona norma non dare per scontato un particolare ordine di valutazione. Non c'è insomma alcuna garanzia nel tuo codice che nelle seguenti righe
inizializzaMatrice( &a, acquisisciDimensione("Inserire il numero di righe: "), acquisisciDimensione("Inserire il numero di colonne: ") );
vengano richieste prima le righe e poi le colonne o viceversa. E' normalmente meglio scrivere qualcosa come:
int r = acquisisciDimensione("Inserire il numero di righe: "); int c = acquisisciDimensione("Inserire il numero di colonne: "); inizializzaMatrice( &a, r , c );
Continuo a non capire però perché passi tutte le volte il numero di righe e colonne come argomenti quando puoi richiamare leggiRighe e leggiColonne dentro alla funzione per ottenere le stesse informazioni.
Ciao, apatriarca ! Ti ringrazio molto x l'interesse ed il tempo che hai dedicato al mio codice.
Scusa se ti scrivo soltanto adesso, perché ho tuttora problemi col compilatore che non esegue più nemmeno il debug, per cui non riesco a capire dove sia localizzato l'errore. Il codice mi sembra corretto ora che ho apportato le modifiche che mi hai indicato, ma dopo l'inserimento dei dati nella matrice, il programma si chiude in errore.
Ti ringrazio comunque, ma ho un pc pessimo e molto vecchio, il Dev-C++ anche, senza debug, con questi strumenti proprio non riesco a lavorare..
Scusa se ti scrivo soltanto adesso, perché ho tuttora problemi col compilatore che non esegue più nemmeno il debug, per cui non riesco a capire dove sia localizzato l'errore. Il codice mi sembra corretto ora che ho apportato le modifiche che mi hai indicato, ma dopo l'inserimento dei dati nella matrice, il programma si chiude in errore.
Ti ringrazio comunque, ma ho un pc pessimo e molto vecchio, il Dev-C++ anche, senza debug, con questi strumenti proprio non riesco a lavorare..

Lo sviluppo di Dev-C++ è fermo da una decina di anni ormai, e non è mai stato privo di bug. Code::Blocks è un'ottima alternativa. Visual C++ lo sconsiglio se vuoi programmare in C e non in C++ (il compilatore Microsoft ha deciso di non aggiornare il supporto al C99 o C11), ma ci sono anche altre alternative come Pelles C (supporta solo il C e non il C++) oppure Qt Creator (credo sia necessario installare mingw o clang a parte) ...
P.S. Io avevo compilato il tuo codice con Pelles C come codice C11..
P.S. Io avevo compilato il tuo codice con Pelles C come codice C11..
"Zeldic":
Lo scopo del prof è quello di farci esercitare con tutti i tipi di strutture, applicate sempre alla matrice ; infatti le varie operazioni sulla matrice (trasposta, somma, norma, differenza, ...) sono riuscito ad implementarle (senza problemi) con :
- vettore multidimensionale ;
- vettore monodimensionale ;
- puntatore singolo ;
- puntatore doppio ;
- lista semplice ;
- l'ultimo esercizio, cioè questo, è con una lista di liste ; lo scopo è di creare una lista di puntatori, ciascuno dei quali punta a sua volta ad una lista di elementi di tipo float. Le liste avranno lunghezza variabile e sono preferite all'utilizzo dei vettori per ottimizzare l'uso della memoria ( allocando di volta in volta lo spazio necessario per i dati con la malloc() ).
Io dicevo che era da buttare solo perché, come stai notando, usare le liste per implementare una matrice è sia più difficile, che meno efficiente dal punto di vista computazionale. È un po' come se per una gara di corsa tu ti sparassi ad un piede per cercare di correre più velocemente. Quindi come progetto personale è meglio usare un array monodimensionale dinamico (o anche statico a seconda che tu sappia o meno la dimensione della matrice a priori). D'altra parte se lo usi per imparare le liste è un codice come un altro. Quindi non scoraggiarti troppo.
Un'ultima osservazione che farei sul tuo codice è che accedere ad ogni singolo elemento di questa matrice è incredibilmente inefficiente. È quindi molto importante scorrere gli elementi in modo lineare quando possibile. Dovresti cercare di lavorare direttamente sulle singole liste. Inoltre non credo abbia senso usare la ricorsione in funzioni come inserimentoLista.
"apatriarca":
ma ci sono anche altre alternative come Pelles C (supporta solo il C e non il C++)
molto interessante!
non ero a conoscenza di questo IDE.
"apatriarca":
Lo sviluppo di Dev-C++ è fermo da una decina di anni ormai, e non è mai stato privo di bug. Code::Blocks è un'ottima alternativa. Visual C++ lo sconsiglio se vuoi programmare in C e non in C++ (il compilatore Microsoft ha deciso di non aggiornare il supporto al C99 o C11), ma ci sono anche altre alternative come Pelles C (supporta solo il C e non il C++) oppure Qt Creator (credo sia necessario installare mingw o clang a parte) ...
Grazie delle informazioni.. Anche Code::Blocks è effettivamente un ottimo ambiente di sviluppo..
"vict85":
Io dicevo che era da buttare solo perché, come stai notando, usare le liste per implementare una matrice è sia più difficile, che meno efficiente dal punto di vista computazionale. È un po' come se per una gara di corsa tu ti sparassi ad un piede per cercare di correre più velocemente.
Scusami, questo tuo esempio mi ha fatto davvero sorridere..

Oggi è stata la mia giornata "cruciale" in cui dovevo mostrare e spiegare il progetto al prof, ma come immaginavo presenta ancora errori e ci sono delle funzioni non necessarie. Quindi mi ha spiegato che devo quasi rifarlo tutto, modificando le funzioni interne di base, tra cui la leggiMatrice() e scriviMatrice(), e che soprattutto devo prima allocare lo spazio di una matrice col numero di righe e di colonne inserito dall'utente (la matrice dovrà risultare vuota); poi la dovrò di volta in volta riempire di valori con l'utilizzo di una lista di liste spostando il puntatore.. La riga sarà la lista di puntatori, la colonna sarà la lista di valori.
Questo progetto mi servirà per creare un gioco in C, il gioco "Forza4". Credo di aver capito ora in teoria ciò che devo fare, ma non so nemmeno da dove cominciare.. Ora mi metto subito al lavoro, e spero di avere ancora la possibilità di chiedere a voi esperti qualche prezioso suggerimento.
"apatriarca":
Dovresti cercare di lavorare direttamente sulle singole liste. Inoltre non credo abbia senso usare la ricorsione in funzioni come inserimentoLista.
Scusa la mia ignoranza, apatriarca, ma in che senso lavoro sulle singole liste ?
Ciao ragazzi ! E' da giorni che provo a correggere il mio codice ed a documentarmi sulla lista di liste, ma con scarsi risultati purtroppo..
Non ho consegnato questo programma al prof nei tempi previsti, per cui adesso sono ormai fuori dal progetto del gioco "Forza4" ed all'esame..
Mi piacerebbe tanto comunque, se fosse possibile, sapere dove ho sbagliato, ma ho capito che all'università la disponibilità è pari a 0 e c'è posto solo per i professionisti che hanno già lavorato in passato nell'ambito informatico (visto che i prof si stancano troppo anche a parlare, perché ritengono di guadagnare troppo poco e poi fanno perdere anni a noi studenti che invece, al contrario loro, i soldi ce li possiamo solo sognare, soprattutto di questi tempi..), o meglio vanno avanti coloro che conoscono bene l'arte del "copia-incolla".. Non lo so su, ma almeno qui a Bari funziona così, qui ci capiamo qualcosa o grazie a forum come questo, o guardando video su Youtube di altre facoltà di Roma o Torino, dove i Professori hanno la P maiuscola..
Scusatemi per lo sfogo, chiusa questa parentesi, mi piacerebbe qui postare il mio codice sulla lista di liste ricorretto, anche se un po' lunghetto, sempre che gli admin non trovino obiezioni per la lunghezza.
Spero di ricevere almeno qualche suggerimento, perché non riesco ad effettuare neanche il debug per via di quei soliti 4 errori di "incompatible types in return" che non so risolvere..
Ma secondo voi esperti ho dichiarato correttamente le strutture nel file .h ?
MAIN :
FUNZIONI.H :
FUNZIONI.C :
OPERAZIONI.H :
OPERAZIONI.C :
Un Grazie a chi mi aiuterà !


Mi piacerebbe tanto comunque, se fosse possibile, sapere dove ho sbagliato, ma ho capito che all'università la disponibilità è pari a 0 e c'è posto solo per i professionisti che hanno già lavorato in passato nell'ambito informatico (visto che i prof si stancano troppo anche a parlare, perché ritengono di guadagnare troppo poco e poi fanno perdere anni a noi studenti che invece, al contrario loro, i soldi ce li possiamo solo sognare, soprattutto di questi tempi..), o meglio vanno avanti coloro che conoscono bene l'arte del "copia-incolla".. Non lo so su, ma almeno qui a Bari funziona così, qui ci capiamo qualcosa o grazie a forum come questo, o guardando video su Youtube di altre facoltà di Roma o Torino, dove i Professori hanno la P maiuscola..
Scusatemi per lo sfogo, chiusa questa parentesi, mi piacerebbe qui postare il mio codice sulla lista di liste ricorretto, anche se un po' lunghetto, sempre che gli admin non trovino obiezioni per la lunghezza.
Spero di ricevere almeno qualche suggerimento, perché non riesco ad effettuare neanche il debug per via di quei soliti 4 errori di "incompatible types in return" che non so risolvere..
](/datas/uploads/forum/emoji/eusa_wall.gif)
MAIN :
#include "operazioni.h" #include <stdio.h> #include <stdlib.h> main() { Matrice a, a_t; int i, j; float num = 1; Nodo_Elemento_matrice elem; //TRASPOSTA DI UNA MATRICE printf("*** TRASPOSTA DI UNA MATRICE ***\n\n"); inizializzaMatrice( &a, leggiRighe(a), leggiColonne(a) ); for(i = 0; i < ( leggiRighe(a) * leggiColonne(a) ); i++) { acquisisciValori(&a); elem = insInCoda(&a, leggiRighe(a), leggiColonne(a), num); } trasposta(a, &a_t); printf("MATRICE TRASPOSTA\n"); stampaMatrice(&a_t); printf("Premere un tasto per continuare\n"); getch(); fflush(stdin); system("cls"); //PRODOTTO DI UNO SCALARE PER UNA MATRICE printf("*** PRODOTTO DI UNO SCALARE PER LA MATRICE A ***\n\n"); //DICHIARAZIONE E INIZIALIZZAZIONE DELLO SCALARE float scalare = acquisisciScalare(); //DICHIARAZIONE E INIZIALIZZAZIONE DELLA MATRICE CHE CONTERRA' IL RISULTATO Matrice m_risultante; inizializzaMatrice(&m_risultante, leggiRighe(a), leggiColonne(a) ); //PRODOTTO prodScalMat(scalare, a, &m_risultante); //STAMPA DEL RISULTATO printf("\n\nRISULTATO DEL PRODOTTO\n"); stampaMatrice(&m_risultante); printf("Premere un tasto per continuare\n"); getch(); fflush(stdin); system("cls"); //SOMMA DI DUE MATRICI printf("*** SOMMA DI DUE MATRICI (MATRICE A + MATRICE B)***\n\n"); //DICHIARAZIONE E INIZIALIZZAZIONE DELLA MATRICE B E DELLA MATRICE RISULTATO (mRis_somma) Matrice b; Matrice mRis_somma; inizializzaMatrice( &b, leggiRighe(a), leggiColonne(a) ); inizializzaMatrice( &mRis_somma, leggiRighe(a), leggiColonne(a) ); printf("Inizializzazione della MATRICE B.\n"); printf("N.B.: per poterne eseguire somma e differenza,\nle matrici A e B devono avere egual numero di righe e colonne\n\n"); for(i = 0; i < ( leggiRighe(a) * leggiColonne(a) ); i++) { acquisisciValori(&a); elem = insInCoda(&a, leggiRighe(a), leggiColonne(a), num); } //SOMMA sommaMat(a, b, &mRis_somma); //STAMPA DEL RISULTATO printf("\n\nRISULTATO DELLA SOMMA (A+B)\n"); stampaMatrice(&mRis_somma); printf("Premere un tasto per continuare\n"); getch(); fflush(stdin); system("cls"); //DIFFERENZA DI DUE MATRICI printf("*** DIFFERENZA TRA DUE MATRICI (MATRICE A - MATRICE B)***\n\n"); printf("Viene ora eseguita la differenza tra le matrici A e B"); //DICHIARAZIONE E INIZIALIZZAZIONE DELLA MATRICE OPPOSTA A B E DELLA MATRICE RISULTATO (mRis_differenza) Matrice opp_b, mRis_differenza; inizializzaMatrice( &mRis_differenza, leggiRighe(a), leggiColonne(a) ); inizializzaMatrice( &opp_b, leggiRighe(b), leggiColonne(b) ); //DIFFERENZA prodScalMat(-1.0, b, &opp_b); sommaMat(a, opp_b, &mRis_differenza); //STAMPA DEL RISULTATO printf("\n\nRISULTATO DELLA DIFFERENZA\n"); stampaMatrice(&mRis_differenza); printf("Premere un tasto per continuare\n"); getch(); fflush(stdin); system("cls"); //PRODOTTO RIGHE PER COLONNE TRA DUE MATRICI printf("*** PRODOTTO RIGHE PER COLONNE TRA MATRICI ***\n\n"); Matrice mRis_prodotto; if(controlloProd( leggiColonne(a), leggiRighe(b) ) == TRUE) { printf("Viene ora eseguito il prodotto righe per colonne tra A e B\n"); inizializzaMatrice( &mRis_prodotto, leggiRighe(a), leggiColonne(b) ); prodottoMatrici(a, b, &mRis_prodotto); printf("\n\nRISULTATO DEL PRODOTTO\n"); stampaMatrice(&mRis_prodotto); } else { printf("E' impossibile eseguire il prodotto righe per colonne tra A e B:\n"); } printf("Premere un tasto per continuare\n"); getch(); fflush(stdin); system("cls"); //CALCOLO DELLA NORMA DELLE MATRICI A E B printf("*** CALCOLO DELLA NORMA DELLE MATRICI ***\n\n"); printf( "Norma della Matrice A ---> %.3f\n\n", normaMatrice(a) ); printf( "Norma della Matrice B ---> %.3f\n\n", normaMatrice(b) ); printf("Premere un tasto per continuare\n"); getch(); system("PAUSE"); return 0; }
FUNZIONI.H :
typedef struct Matrice { int numero_righe; int numero_colonne; struct Riga* val; } Matrice; typedef struct Riga { struct Elemento_matrice *riga; struct Riga *colonna; } Nodo_Riga; typedef struct Nodo_Riga* ListaDiPuntatori; typedef struct Elemento_matrice { float valore; struct Elemento_matrice *successivo; } Nodo_Elemento_matrice; typedef struct Nodo_Elemento_matrice *ListaDiElem; typedef enum { FALSE, TRUE } boolean; // FUNZIONI MATRICE int acquisisciDimensione(char []); int leggiRighe(Matrice); int leggiColonne(Matrice); void scriviRighe(Matrice *, int); void scriviColonne(Matrice *, int); void inizializzaMatrice(Matrice *, int, int); void acquisisciValori(Matrice *); Nodo_Elemento_matrice leggiMatrice(Matrice, int, int); void scriviMatrice(Matrice *, int, int, float); boolean controlloProd(int, int); float acquisisciScalare(); void stampaMatrice(Matrice *); // FUNZIONI LISTA //boolean listaVuota(ListaDiElem); Nodo_Riga leggiListaPuntatori();
FUNZIONI.C :
#include <stdio.h> #include "funzioni.h" int acquisisciDimensione(char s[]) { int num; printf("%s", s); scanf("%d", &num); return num; } int leggiRighe(Matrice m) { return m.numero_righe; } int leggiColonne(Matrice m) { return m.numero_colonne; } void scriviRighe(Matrice *m, int r) { m->numero_righe = r; } void scriviColonne(Matrice *m, int c) { m->numero_colonne = c; } void inizializzaMatrice(Matrice *m, int r, int c) { Nodo_Riga *elemento; Nodo_Elemento_matrice *dato; int i, j; /*elemento = leggiListaPuntatori(elemento); elemento = malloc( 1 * sizeof(Nodo_Riga) ); m->val = elemento->riga;*/ for(i = 0; i < r; i++) { elemento = malloc( sizeof(Nodo_Riga) ); elemento->colonna = NULL; { for(j = 0; j < r; j++) { dato = malloc( r * sizeof(Nodo_Elemento_matrice) ); dato = insInCoda(m, r, c, 0.0); dato->successivo = NULL; } /*elemento = malloc(sizeof(Nodo_Riga) ); elemento = elemento->colonna; elemento->riga = dato;*/ } } void acquisisciValori(Matrice *m) { int i, j; float val; int r = acquisisciDimensione("Inserire il numero di righe ---> "); int c = acquisisciDimensione("Inserire il numero di colonne ---> "); inizializzaMatrice(m, r, c); printf("\nInserire i valori della matrice separati da uno spazio;\n"); printf("Premi invio al termine di ogni riga;\n\n"); for(i = 0; i < leggiRighe(*m); i++) { for(j = 0; j < leggiColonne(*m); j++) { scanf("%f", &val); scriviMatrice(m, i, j, val); } } } Nodo_Elemento_matrice leggiMatrice(Matrice m, int r, int c) { Nodo_Riga *elemento; Nodo_Elemento_matrice *dato; int i, j; if(dato->valore == 0.0) { dato->successivo = NULL; return dato; } else { for(i = 0; i < c; i++) { for(j = 0; j < r; j++) { return dato; dato = dato->successivo; } elemento = elemento->colonna; } } } void scriviMatrice(Matrice *m, int r, int c, float val) { Nodo_Riga *punt; Nodo_Elemento_matrice *dato; int i, j; // Ciclo sulle righe for(i = 0; i < r; i++) { punt = m; punt = leggiListaPuntatori(); //spostati nella lista elem_lista_puntatori // Ciclo sulle colonne for(j = 0; j < c; j++) { punt->riga = dato->successivo; //spostati nella lista elem_lista_puntatori.elem_lista dato->successivo = NULL; dato->valore = val; //PUNTATORE.valore=val; } } } boolean controlloProd (int m, int n) { boolean c = FALSE; if(m == n) c = TRUE; return c; } float acquisisciScalare() { float scal; printf("Inserire di seguito un valore scalare: "); scanf("%f", &scal); return scal; } void stampaMatrice(Matrice *m) { int i, j; Nodo_Riga *lista; Nodo_Elemento_matrice *matrice; lista = lista->colonna; matrice = matrice->successivo; while(lista->colonna == NULL) { printf("\n"); while(matrice->successivo == NULL) { printf(" %.3f ", matrice->valore); } lista = lista->colonna; } } /*if( ! (lista) ) printf("La matrice e' vuota !\n\n"); else { for(i = 0; i < leggiRighe(*m); i++) { for(j = 0; j < leggiColonne(*m); j++) { printf("[ %.3f ] ---> ", matrice->valore); matrice = matrice->successivo; } printf("\n"); } } }*/ /*boolean listaVuota(ListaDiElem lista) { if(lista == NULL) return TRUE; return FALSE; }*/ Nodo_Riga leggiListaPuntatori() { Nodo_Riga *punt; if(! (punt) ) return NULL; punt = punt->colonna; return punt; }
OPERAZIONI.H :
#include "funzioni.h" // OPERAZIONI MATRICE void trasposta(Matrice, Matrice *); void prodScalMat(float, Matrice, Matrice *); void sommaMat(Matrice, Matrice, Matrice *); void prodottoMatrici(Matrice, Matrice, Matrice *); float normaMatrice(Matrice); // OPERAZIONI LISTA Nodo_Elemento_matrice insInCoda(Matrice *, int, int, float); boolean esisteInLista(ListaDiPuntatori, float); void cancellaTestaLista(ListaDiPuntatori); void cancellaElementoLista(ListaDiPuntatori, float); void cancellaLista(Matrice);
OPERAZIONI.C :
#include <stdio.h> #include <math.h> #include "operazioni.h" void trasposta(Matrice m, Matrice *m_t) { int i, j; for(i = 0; i < leggiRighe(*m_t); i++) { for(j = 0; j < leggiColonne(*m_t); j++) { scriviMatrice( m_t, i, j, leggiMatrice(m, j, i) ); } } } void prodScalMat(float scal, Matrice m, Matrice *mRis) { int i, j; for(i = 0; i < leggiRighe(m); i++) { for(j = 0; j < leggiColonne(m); j++) { scriviMatrice( mRis, i, j, scal * leggiMatrice(m, i, j) ); } } } void sommaMat(Matrice m, Matrice n, Matrice *sum) { int i, j; for(i = 0; i < leggiRighe(m); i++) { for(j = 0; j < leggiColonne(m); j++) { scriviMatrice( sum, i, j, ( leggiMatrice(m, i, j) + leggiMatrice(n, i, j) ) ); } } } void prodottoMatrici(Matrice m, Matrice n, Matrice *prod) { int i, j, k; float temp; for(i = 0; i < leggiRighe(m); i++) { for(j = 0; j < leggiColonne(n); j++) { temp = 0; for(k = 0; k < leggiColonne(m); k++) { temp = temp + ( leggiMatrice(m, i, k) * leggiMatrice(n, k, j) ); scriviMatrice(prod, i, j, temp); } } } } float normaMatrice(Matrice m) { int i, j; float sommatoria = 0; float risultato; for(i = 0; i < leggiColonne(m); i++) for(j = 0; j < leggiRighe(m); j++) sommatoria+= pow(leggiMatrice(m, j, i), 2); risultato = sqrt(sommatoria); return risultato; } Nodo_Elemento_matrice insInCoda(Matrice *m, int r, int c, float val) { Nodo_Riga *elemento; Nodo_Elemento_matrice *dato; int i, j; //elemento = leggiListaPuntatori(); /*dato = leggiMatrice(*m); m->val = elemento->riga; elemento->riga = dato->valore;*/ for(i = 0; i < c; i++) { for(j = 0; j < r; j++) { dato->valore = val; dato = dato->successivo; } dato->successivo = elemento->riga; } return dato; } boolean esisteInLista(ListaDiPuntatori lista, float val) { boolean trovato = FALSE; Nodo_Riga *dato; dato = lista; if( listaVuota(lista) ) { printf("Impossibile trovare l'elemento. La lista e' vuota !\n\n"); return trovato; } else { while(lista != NULL) { if(val == dato->valore) { trovato = TRUE; printf("L'elemento %.3f e' presente nella lista !\n\n", dato->valore); return trovato; } else { printf("L'elemento %.3f non e' stato trovato nella lista !\n\n", dato->valore); return trovato; } } } } void cancellaTestaLista(ListaDiPuntatori matrice) { Nodo_Riga *dato; if( listaVuota(matrice) ) { printf("Impossibile cancellare il primo elemento della lista. La lista e' vuota !\n\n"); return ;; } else { dato = matrice; printf("L'elemento che sara' cancellato e' il seguente ---> %.3f\n\n", dato->valore); matrice = matrice->successivo; free(dato); dato = NULL; } } void cancellaElementoLista(ListaDiPuntatori matrice, float val) { Nodo_Riga *dato; int scelta = 0; dato = matrice; if( listaVuota(dato) ) printf("Impossibile cancellare l'elemento %.3f. La lista e' vuota !\n\n"); else { while(matrice != NULL) { if(val == dato->valore) { do { printf("\nScegli una delle opzioni seguenti :\n\n"); printf("1) Eliminare solo la prima occorrenza dell'elemento %.3f nella lista ;\n", dato->valore); printf("2) Eliminare tutte le occorrenze dell'elemento %.3f nella lista.\n", dato->valore); printf("Effettua una scelta ---> "); scanf("%i", &scelta); printf("\n\n"); switch(scelta) { case 1 : printf("L'elemento che sara' cancellato e' il seguente ---> %.3f\n\n", dato->valore); matrice = matrice->successivo; free(dato); dato = NULL; break; case 2 : while(matrice != NULL) { printf("L'elemento che sara' cancellato e' il seguente ---> %.3f\n\n", dato->valore); matrice = matrice->successivo; free(dato); dato = NULL; } break; default : printf("Scelta sbagliata !\n\n"); break; } } while(scelta != 0); } } } } void cancellaLista(Matrice m) { Nodo_Elemento_matrice *dato; int i, j; while(dato) { for(i = 0; i < leggiRighe(m); i++) { for(j = 0; j < leggiColonne(m); j++) { free(dato); dato = dato->successivo; } } } }
Un Grazie a chi mi aiuterà !
È secondo me a questo punto necessario che tu prenda una decisione sul tipo di aiuto che a questo punto vuoi. Ci sono infatti diverse cose che andrebbero fatte diversamente rispetto al tuo codice. Queste cose non sono però veri e propri errori ed è probabilmente possibile aggiustare il tuo codice in modo da renderlo funzionante e valido. Una prima cosa che si può fare è quindi prendere il tuo codice e correggere gli errori più gravi e che ne impediscono il funzionamento. In alternativa si può decidere di lasciare perdere questo codice e cercare di vedere insieme come realizzare programmi di questo tipo, probabilmente partendo da zero e con un esercizio diverso. Oppure si possono anche fare entrambe le cose.
In questo momento non posso provare a compilare e correggere il tuo codice, sarebbe però utile vedere i messaggi di errori del tuo compilatore in modo da capire in quali righe stai cercando di restituire qualcosa di tipo diverso da quello che si aspetta il compilatore.
In questo momento non posso provare a compilare e correggere il tuo codice, sarebbe però utile vedere i messaggi di errori del tuo compilatore in modo da capire in quali righe stai cercando di restituire qualcosa di tipo diverso da quello che si aspetta il compilatore.
Copiando il tuo codice e facendolo formattare dal computer (cosa che faccio ogni volta che provo un programma) ho trovato un primo possibile errore nel file funzioni.c. Il corpo della funzione inizializzaMatrice non è mai stato chiuso. Questo dovrebbe insegnare un po' il valore di formattare il codice correttamente.
Lanciando a questo la compilazione del tuo programma ottengo i seguenti errori e warning (oggi sto usando clang in linux):
Ecco come risolvere questi errori:
1. Per quanto riguarda il primo warning, viene già fornita una soluzione: includi stdlib.h in funzioni.c.
2. I successivi due warning sono dovuti al fatto che insInCoda non è mai stata dichiarata in quel contesto. operazioni.h non è infatti incluso in funzioni.c. Probabilmente la divisione tra funzioni e operazioni non ha mai avuto realmente senso e avresti dovuto mettere tutto insieme. E' in effetti la soluzione che ho deciso di adottare.. Ho copiato il contenuto di funzioni.h in operazioni.h e incluso operazioni.h ovunque eliminando poi funzioni.h. Spero sia chiaro.
3. Dopo queste due correzioni il compilatore continua però a dare un errore sulla stessa riga del secondo warning. Questa volta l'errore è il seguente:
Il problema non è però in questa riga, ma la funzione insInCoda. Perché restituisce un nodo per valore? In effetti, tale funzione è tutta da buttare. Il codice non ha alcun senso.
Continuo più tardi che ora devo andare.
Lanciando a questo la compilazione del tuo programma ottengo i seguenti errori e warning (oggi sto usando clang in linux):
funzioni.c:42:16: warning: implicitly declaring library function 'malloc' with type 'void *(unsigned long)' elemento = malloc( sizeof(Nodo_Riga) ); ^ funzioni.c:42:16: note: please include the header <stdlib.h> or explicitly provide a declaration for 'malloc' funzioni.c:46:9: warning: implicit declaration of function 'insInCoda' is invalid in C99 [-Wimplicit-function-declaration] dato = insInCoda(m, r, c, 0.0); ^ funzioni.c:46:7: warning: incompatible integer to pointer conversion assigning to 'Nodo_Elemento_matrice *' (aka 'struct Elemento_matrice *') from 'int' [-Wint-conversion] dato = insInCoda(m, r, c, 0.0); ^ ~~~~~~~~~~~~~~~~~~~~~~~ funzioni.c:82:12: error: returning 'Nodo_Elemento_matrice *' (aka 'struct Elemento_matrice *') from a function with incompatible result type 'Nodo_Elemento_matrice' (aka 'struct Elemento_matrice'); dereference with * return dato; ^~~~ * funzioni.c:86:9: error: returning 'Nodo_Elemento_matrice *' (aka 'struct Elemento_matrice *') from a function with incompatible result type 'Nodo_Elemento_matrice' (aka 'struct Elemento_matrice'); dereference with * return dato; ^~~~ * funzioni.c:74:44: warning: unused parameter 'm' [-Wunused-parameter] Nodo_Elemento_matrice leggiMatrice(Matrice m, int r, int c) { ^ funzioni.c:101:10: warning: incompatible pointer types assigning to 'Nodo_Riga *' (aka 'struct Riga *') from 'Matrice *' (aka 'struct Matrice *') [-Wincompatible-pointer-types] punt = m; ^ ~ funzioni.c:102:10: error: assigning to 'Nodo_Riga *' (aka 'struct Riga *') from incompatible type 'Nodo_Riga' (aka 'struct Riga') punt = leggiListaPuntatori(); //spostati nella lista elem_lista_puntatori ^ ~~~~~~~~~~~~~~~~~~~~~ funzioni.c:131:7: warning: unused variable 'i' [-Wunused-variable] int i, j; ^ funzioni.c:131:10: warning: unused variable 'j' [-Wunused-variable] int i, j; ^ funzioni.c:130:29: warning: unused parameter 'm' [-Wunused-parameter] void stampaMatrice(Matrice *m) { ^ funzioni.c:171:12: error: returning 'void *' from a function with incompatible result type 'Nodo_Riga' (aka 'struct Riga') return NULL; ^~~~ /usr/bin/../lib/clang/3.2/include/stddef.h:52:16: note: expanded from macro 'NULL' # define NULL ((void*)0) ^~~~~~~~~~ funzioni.c:175:10: error: returning 'Nodo_Riga *' (aka 'struct Riga *') from a function with incompatible result type 'Nodo_Riga' (aka 'struct Riga'); dereference with * return punt; ^~~~ * 8 warnings and 5 errors generated.
Ecco come risolvere questi errori:
1. Per quanto riguarda il primo warning, viene già fornita una soluzione: includi stdlib.h in funzioni.c.
2. I successivi due warning sono dovuti al fatto che insInCoda non è mai stata dichiarata in quel contesto. operazioni.h non è infatti incluso in funzioni.c. Probabilmente la divisione tra funzioni e operazioni non ha mai avuto realmente senso e avresti dovuto mettere tutto insieme. E' in effetti la soluzione che ho deciso di adottare.. Ho copiato il contenuto di funzioni.h in operazioni.h e incluso operazioni.h ovunque eliminando poi funzioni.h. Spero sia chiaro.
3. Dopo queste due correzioni il compilatore continua però a dare un errore sulla stessa riga del secondo warning. Questa volta l'errore è il seguente:
funzioni.c:44:7: error: assigning to 'Nodo_Elemento_matrice *' (aka 'struct Elemento_matrice *') from incompatible type 'Nodo_Elemento_matrice' (aka 'struct Elemento_matrice') dato = insInCoda(m, r, c, 0.0); ^ ~~~~~~~~~~~~~~~~~~~~~~~
Il problema non è però in questa riga, ma la funzione insInCoda. Perché restituisce un nodo per valore? In effetti, tale funzione è tutta da buttare. Il codice non ha alcun senso.
Continuo più tardi che ora devo andare.
insInCoda non è corretta perché non hai alcun modo di sapere quanti valori hai già inserito in quella riga. Era a questo punto meglio la versione precedente in cui inserivi i valori in posizioni particolari della matrice. Usavi le liste come se fossero array, ma se non altro il programma funzionava meglio.
Ciao, apatriarca ! Grazie di cuore per avermi risposto.. Purtroppo però ho apportato al mio codice le modifiche che mi hai indicato, ma ottengo ancora diversi errori.. Credo che la scelta migliore sia quella di rifare tutto quanto il programma, perché alcune funzioni come la insInCoda(), effettivamente non hanno molto senso. Devo trattare le liste come se fossero array, perché la loro dimensione è definita dalle funzioni leggiRighe() e leggiColonne(). Mi sono basata su questo programma, perché erano esattamente queste le funzioni che il prof vuole, ma non sono corrette. Ti ringrazio ancora.
Se vuoi rifare questo programma penso che sia importante capire cosa il tuo professore esattamente vuole e cosa invece possiamo consigliarti di modificare.
Comunque ho dato un occhiata ai tuoi vecchi post e vorrei evidenziare che la frase “Le liste avranno lunghezza variabile e sono preferite all'utilizzo dei vettori per ottimizzare l'uso della memoria” è sbagliata sotto moltissime ragioni. Al di là della impossibilità di accedere in modo casuale alla memoria e di non assicurare la contiguità dei dati in memoria, il fatto è che su un computer a 64 bit un puntatore è di 64 bit mentre un float ne ha ‘solo’ 32. Questo significa che una double linked list di float usa 5 volte la memoria di quella necessaria, quando un semplice array dinamico ‘espandibile’ né contiene al massimo 2-3 volte tanto. Inoltre l'accesso ad elementi non-contigui nella memoria è uno dei maggiori motivi di riduzione di performance dei computer e poche applicazioni usano tutta la memoria disponibile di un sistema di fascia medio-alta. I videogiochi attualmente, ho letto su un articolo recentemente, tendono ad usare meno di 4GB (anche perché PS3 e Xbox360 hanno quella memoria). In questo momento il mio pc usa, per esempio, il 22% della memoria (su 8GB). Per intenderci i 6GB che rimangono inutilizzati nel mio sistema sono pari a \(\displaystyle 6 \cdot 2^{30} \) bits cioè \(\displaystyle 6\cdot 2^{25} \cdot 32 \) bit (in pratica 200 milioni di float). Dubito che un programma di forza4 metta a dura prova la memoria del mio pc...
Comunque ho dato un occhiata ai tuoi vecchi post e vorrei evidenziare che la frase “Le liste avranno lunghezza variabile e sono preferite all'utilizzo dei vettori per ottimizzare l'uso della memoria” è sbagliata sotto moltissime ragioni. Al di là della impossibilità di accedere in modo casuale alla memoria e di non assicurare la contiguità dei dati in memoria, il fatto è che su un computer a 64 bit un puntatore è di 64 bit mentre un float ne ha ‘solo’ 32. Questo significa che una double linked list di float usa 5 volte la memoria di quella necessaria, quando un semplice array dinamico ‘espandibile’ né contiene al massimo 2-3 volte tanto. Inoltre l'accesso ad elementi non-contigui nella memoria è uno dei maggiori motivi di riduzione di performance dei computer e poche applicazioni usano tutta la memoria disponibile di un sistema di fascia medio-alta. I videogiochi attualmente, ho letto su un articolo recentemente, tendono ad usare meno di 4GB (anche perché PS3 e Xbox360 hanno quella memoria). In questo momento il mio pc usa, per esempio, il 22% della memoria (su 8GB). Per intenderci i 6GB che rimangono inutilizzati nel mio sistema sono pari a \(\displaystyle 6 \cdot 2^{30} \) bits cioè \(\displaystyle 6\cdot 2^{25} \cdot 32 \) bit (in pratica 200 milioni di float). Dubito che un programma di forza4 metta a dura prova la memoria del mio pc...