[C] Problema con stampa matrice

Zeldic
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 :

 

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
apatriarca
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.

vict85
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 :roll: (come professore ovviamente).

Zeldic
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..

apatriarca
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
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.

Zeldic
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.. :(

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) ...

P.S. Io avevo compilato il tuo codice con Pelles C come codice C11..

vict85
"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.

apatriarca
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.

hamming_burst
"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.

Zeldic
"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.. :D Effettivamente il mio problema è che il codice presenta delle imperfezioni e come hai detto tu precedentemente nasconde molto gli errori ed è davvero difficile da gestire..
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 ?

Zeldic
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.. :cry:
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 :

 

#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à !

apatriarca
È 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.

apatriarca
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):
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.

apatriarca
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.

Zeldic
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.

vict85
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...

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.