PDA

View Full Version : [C] Implementazione lista di liste


guylmaster
04-06-2010, 18:12
Salve a tutti,
per una consegna universitaria mi trovo a dover consegnare un programma che lavora su una struttura dati che in realtà è una lista di lista, come rappresentato in questa immagine:

http://img97.imageshack.us/img97/4989/listage.jpg

Creando questa lista di liste in poche parole si vuole creare una "matrice dinamica", ovvero, ci sarà una lista principale composta da due puntatori e di questi due puntatori:

Uno punterà all'elemento successivo della lista;
Uno punterà ad un'altra lista che in realtà rappresenterà un intera colonna della matrice;

Per farla breve una lista servirà per scorrere per le colonne, arrivata alla colonna desiderata si punterà alla seconda lista che a sua volta conterrà gli elementi veri e propri della colonna in questione.

Il problema è che questo esame non è di Algoritmi e strutture dati, che ancora non ho fatto essendo solo al primo anno, ma è un esame di laboratorio di informatica in cui ci è stato appena accennato come funziona una lista, e non riesco bene a definire come far funzionare una lista di liste.

Mi sono bloccato già solo alla creazione di una funzione che inizializzi la lista. Ovvero che allochi lo spazio, passandogli semplicemente un puntatore ed il numero di righe e di colonne.
Stavo pensando ad allocare, con un primo ciclo tutti gli elementi della prima lista, e man mano che si alloca il singolo elemento della prima lista, con un'altro ciclo anniato, gli si alloca la seconda lista ad esso collegata.

Ho però tante idee e ben confuse, quindi se potreste aiutarmi a creare e a gestire questa struttura dati ve ne sarei ben grato. Magari non sono il primo a voler creare una lista di liste.

Vi ringrazio in anticipo,
guylmaster.

DanieleC88
04-06-2010, 19:16
Fermati a pensare un attimo sulla struttura di questa sorta di "matrice" che stai creando.

Come noti tu stesso, è una lista di liste. Se riesci a rappresentare una lista come un puntatore al nodo in testa, allora il resto è molto semplice: visto che ogni nodo contiene un valore di qualche tipo, puoi fare per prima cosa una lista di colonne. I nodi di questa lista potranno contenere, come valore, il puntatore alla testa di una lista con le celle da memorizzare in quella colonna.

Il fatto che tu lo stia facendo in C ti complicherà leggermente la vita, ma se farai le scelte giuste non sarà difficile. :)

ciao ;)

guylmaster
04-06-2010, 19:53
Sto provando ad iniziare per gradi ovvero di provare inanzi tutto a realizzare una semplice lista.

Ho trovato su internet un codice piu complicato che ho provato a semplificare.

Ho tre file, il main.c, funzioni.c (contenente le funzioni di inserimento), funzioni.h (contenendo le definizioni delle strutture), e sono le seguenti:


main.c

#include <stdio.h>
#include <stdlib.h>
#include "funzioni.h"

int main(int argc, char *argv[])
{
struct elemento *lista = NULL;
lista = aggiungiContatto(lista);
system("PAUSE");
return 0;
}



funzioni.h

/*Elementi pubblici della libreria funzioni*/

//Struttura dati
struct elemento
{
float inf;
struct elemento *pun;
};
//Prototipi funzioni
struct elemento *aggiungiContatto(struct elemento *p);


funzioni.c

#include <stdio.h>
#include <stdlib.h>
#include "funzioni.h"

struct elemento *aggiungiContatto(struct elemento *p)
{ // aggiungiContatto() - OPEN


// Dichiaro le variabili
float daInserire;
struct elemento *punt;

// Popolo la variabile daInserire
printf (" Float > ");
scanf ("%f", daInserire);


if(p != NULL)
{ // IF - OPEN

/* creazione elementi successivi */
// Alloco la memoria necessaria
punt = (struct elemento *)malloc(sizeof(struct elemento));
// Metto daInserire nell'informazione del puntatore
punt->inf = daInserire;
// Metto il puntatore in testa alla lista
punt->pun = p;

} else { // ELSE

/* creazione primo elemento */
// Alloco la memoria necessaria
p = (struct elemento *)malloc(sizeof(struct elemento));
// Metto daInserire nell'informazione del puntatore
p->inf = daInserire;
// p punta a NULL, ovvero il marcatore di fine lista
p->pun = NULL;
// Assegno p a punt
punt = p;

} // IF - CLOSE

// Esce dalla funzione e restituisce la lista
return(punt);

}



Il problema è che il programma arriva a leggere il valore float e poi crasha inspiegabilmente. Da cosa può dipendere?

Ma anche non avresti qualche guida che spiega in linguaggio C, magari in maniera dettaggliata (e codice copiabile direttamente) come sviluppare una semplice lista senza fronzoli? Perchè secondo me mi mancano proprio le basi.

Ho una dispensa del professore i cui stessi esempi non funzionano e non sto riuscendo a trovare in internet programmi in C di liste ridotte all'osso.

Se potresti aiutarmi anche in tal senso te ne sarei grato.

guylmaster
04-06-2010, 20:08
Ho trovato anche questo codice per le liste, molto piu stringato ma con il problema di non avere nemmeno un commento a disposizione:


#include<stdlib.h>
#include<stdio.h>
#include<string.h>

typedef struct node_s {
void *data;
struct node_s *next;
} NODE;

NODE *list_create(void *data)
{
NODE *node;
if(!(node=malloc(sizeof(NODE)))) return NULL;
node->data=data;
node->next=NULL;
return node;
}

NODE *list_insert_after(NODE *node, void *data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}

NODE *list_insert_beginning(NODE *list, void *data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = list;
return newnode;
}

int list_remove(NODE *list, NODE *node)
{
while(list->next && list->next!=node) list=list->next;
if(list->next) {
list->next=node->next;
free(node);
return 0;
} else return -1;
}

int list_foreach(NODE *node, int(*func)(void*))
{
while(node) {
if(func(node->data)!=0) return -1;
node=node->next;
}
return 0;
}

NODE *list_find(NODE *node, int(*func)(void*,void*), void *data)
{
while(node) {
if(func(node->data, data)>0) return node;
node=node->next;
}
return NULL;
}

int printstring(void *s)
{
printf("%s\n", (char *)s);
return 0;
}

int findstring(void *listdata, void *searchdata)
{
return strcmp((char*)listdata, (char*)searchdata)?0:1;
}

int main()
{
NODE *list, *second, *inserted;
NODE *match;

/* Create initial elements of list */
list=list_create((void*)"First");
second=list_insert_after(list, (void*)"Second");
list_insert_after(second, (void*)"Third");

printf("Initial list:\n");
list_foreach(list, printstring);
putchar('\n');

/* Insert 1 extra element in front */
list=list_insert_beginning(list, "BeforeFirst");
printf("After list_insert_beginning():\n");
list_foreach(list, printstring);
putchar('\n');

/* Insert 1 extra element after second */
inserted=list_insert_after(second, "AfterSecond");
printf("After list_insert_after():\n");
list_foreach(list, printstring);
putchar('\n');

/* Remove the element */
list_remove(list, inserted);
printf("After list_remove():\n");
list_foreach(list, printstring);
putchar('\n');

/* Search */
if((match=list_find(list, findstring, "Third")))
printf("Found \"Third\"\n");
else printf("Did not find \"Third\"\n");

system("PAUSE");
return 0;
}




Non mi è chiara inanzitutto la funzione list_insert_after che vi riporto di seguito:

NODE *list_insert_after(NODE *node, void *data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}


Praticameente questa prima crea il nuovo nodo, poi però dice "newnode->next = node->next;" che significa? cioè il sucessivo di newnode è se stesso? non mi torna.

Anche perchè ho provato a fare "newnode->next = NULL;" e non va più l'ultima funzione di ricerca di un elemento.

TRF83
04-06-2010, 20:45
...
Praticameente questa prima crea il nuovo nodo, poi però dice "newnode->next = node->next;" che significa? cioè il sucessivo di newnode è se stesso? non mi torna.
...
Quella funzione fa l'inserimento DOPO il nodo che gli passi come parametro, che può essere l'ultimo, come il primo.
Per semplicità, immaginiamo che tu voglia inserire dopo il primo elemento (quindi in seconda posizione). Quale sarà il successore del nuovo nodo, cioè quello che ORA dovrà essere in terza posizione? Quello che PRIMA era in seconda posizione, quindi nodo_dopo_il_quale_inserire->next. Per questo fai newnode->next=node->next;
L'istruzione node->next=newnode, invece serve per indicare che il successore del nodo è il nuovo nodo creato. Spero di essere stato chiaro..

A->C->D;
devi inserire B dopo la A, quindi chiami insert_after(&A,&B).
A questo punto crei il nodo con i dati di B (lo chiamo B per semplicità). Chi sarà il successore di B? C, quindi A->next. E il successore di A? B. Con l'esempietto dovrebbe essere decisamente più semplice da capire di quanto ho scritto sopra! ;)

guylmaster
04-06-2010, 21:19
Quella funzione fa l'inserimento DOPO il nodo che gli passi come parametro, che può essere l'ultimo, come il primo.
Per semplicità, immaginiamo che tu voglia inserire dopo il primo elemento (quindi in seconda posizione). Quale sarà il successore del nuovo nodo, cioè quello che ORA dovrà essere in terza posizione? Quello che PRIMA era in seconda posizione, quindi nodo_dopo_il_quale_inserire->next. Per questo fai newnode->next=node->next;
L'istruzione node->next=newnode, invece serve per indicare che il successore del nodo è il nuovo nodo creato. Spero di essere stato chiaro..

A->C->D;
devi inserire B dopo la A, quindi chiami insert_after(&A,&B).
A questo punto crei il nodo con i dati di B (lo chiamo B per semplicità). Chi sarà il successore di B? C, quindi A->next. E il successore di A? B. Con l'esempietto dovrebbe essere decisamente più semplice da capire di quanto ho scritto sopra! ;)

Ho capito, quindi con quell'insert_after ho la possibilità di aggiungere nodi anche a metà della lista.

Ma come mai data lo da come puntatore di tipo void?

Se volessi modificare questo esempio per far si che questa lista abbia come elementi l'inizio di un'altra lista, come da post originario, come potrei fare?

guylmaster
04-06-2010, 21:38
Quella funzione fa l'inserimento DOPO il nodo che gli passi come parametro, che può essere l'ultimo, come il primo.
Per semplicità, immaginiamo che tu voglia inserire dopo il primo elemento (quindi in seconda posizione). Quale sarà il successore del nuovo nodo, cioè quello che ORA dovrà essere in terza posizione? Quello che PRIMA era in seconda posizione, quindi nodo_dopo_il_quale_inserire->next. Per questo fai newnode->next=node->next;
L'istruzione node->next=newnode, invece serve per indicare che il successore del nodo è il nuovo nodo creato. Spero di essere stato chiaro..

A->C->D;
devi inserire B dopo la A, quindi chiami insert_after(&A,&B).
A questo punto crei il nodo con i dati di B (lo chiamo B per semplicità). Chi sarà il successore di B? C, quindi A->next. E il successore di A? B. Con l'esempietto dovrebbe essere decisamente più semplice da capire di quanto ho scritto sopra! ;)

Ho capito, quindi con quell'insert_after ho la possibilità di aggiungere nodi anche a metà della lista.

Ma come mai data lo da come puntatore di tipo void?

Se volessi modificare questo esempio per far si che questa lista abbia come elementi l'inizio di un'altra lista, come da post originario, come potrei fare?

Ho provato anche solo a modificare i tipi in float in questo modo ma mi va in loop:


#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//Struttura dati
typedef struct node_s {
//void *data;
float data;
struct node_s *next;
} NODE;

//Prototipi funzioni
NODE *list_create(float data);
NODE *list_insert_after(NODE *node, float data);
NODE *list_insert_beginning(NODE *list, void *data);
int list_remove(NODE *list, NODE *node);
int list_foreach(NODE *node, int(*func)(float));
NODE *list_find(NODE *node, int(*func)(void*,void*), void *data);
int printstring(void *s);
int findstring(void *listdata, void *searchdata);

//funzioni

NODE *list_create(float data)
{
NODE *node;
if(!(node=malloc(sizeof(NODE)))) return NULL;
node->data=data;
node->next=NULL;
return node;
}

NODE *list_insert_after(NODE *node, float data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = node->next;
//newnode->next = NULL;
node->next = newnode;
return newnode;
}
/*
NODE *list_insert_beginning(NODE *list, void *data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = list;
return newnode;
}

int list_remove(NODE *list, NODE *node)
{
while(list->next && list->next!=node) list=list->next;
if(list->next) {
list->next=node->next;
free(node);
return 0;
} else return -1;
}
*/
int list_foreach(NODE *node, int(*func)(float))
{
while(node) {
if(func(node->data)!=0) return -1;
node=node->next;
}
return 0;
}
/*
NODE *list_find(NODE *node, int(*func)(void*,void*), void *data)
{
while(node) {
if(func(node->data, data)>0) return node;
node=node->next;
}
return NULL;
}
*/
int printstring(void *s)
{
printf("%s\n", (char *)s);
return 0;
}
/*
int findstring(void *listdata, void *searchdata)
{
return strcmp((char*)listdata, (char*)searchdata)?0:1;
}
*/


//main
int main()
{
NODE *list, *second, *inserted;
NODE *match;

/* Create initial elements of list */
list=list_create(1);
second=list_insert_after(list, 2);
//list_insert_after(second, 3);

printf("Initial list:\n");
list_foreach(list, printstring);
putchar('\n');

system("PAUSE");
return 0;
}


Poi in questo prototipo:

int list_foreach(NODE *node, int(*func)(void*))


Non riesco a capire cosa significhi "int(*func)(void*)", com in generale non riesco a capire perchè nella struttura definisca il dato di tipo void in questo modo "void *data;"

DanieleC88
04-06-2010, 22:37
Non riesco a capire cosa significhi "int(*func)(void*)", com in generale non riesco a capire perchè nella struttura definisca il dato di tipo void in questo modo "void *data;"
Quella dichiarazione è un puntatore ad una generica funzione che restituisce un intero e accetta un puntatore a void come argomento.
Il dato nella lista è di tipo void* per dare una certa "universalità" all'implementazione (ci puoi virtualmente infilare ciò vuoi, quindi quella singola implementazione della lista è adattabile ad ogni contenuto).

guylmaster
04-06-2010, 22:44
Per altro con la insert_after riesco ad inserire un nodo solo in mezzo a due nodi.
Se volessi invece inserire un nodo a fine lista come potrei fare?

DanieleC88
04-06-2010, 22:54
Ti basta inserirlo... dopo l'ultimo nodo della lista. :D

guylmaster
04-06-2010, 22:56
Per fare l'inserimentro a fine lista ho provato ad implementare la seguente funzione:


NODE *Inserisci_alla_fine(NODE *node, float data)
{
NODE2 *newnode;
while(node)
{
if(node->next != NULL)
{
node = node->next;
}
else
{
newnode = list_create2(data);
node->next = newnode;
newnode->next = NULL;
}
}
return newnode;
}


Tenendo conto che la struttura è la seguente:

typedef struct node_s2 {
float data;
struct node_s2 *next;
} NODE2;


e che la list_create2 è questa:


NODE2 *list_create2(float data)
{
NODE2 *node;
if(!(node=malloc(sizeof(NODE2)))) return NULL;
node->data=data;
node->next=NULL;
return node;
}


Il programma compila, si esegue ma mi da la schermata nera.

guylmaster
04-06-2010, 22:57
Ti basta inserirlo... dopo l'ultimo nodo della lista. :D

Ok, ma in quella struttura come lo trovo l'ultimo nodo della lista? ho provato a fare il ciclo while sopra ripotato ma non va..

DanieleC88
04-06-2010, 23:08
Non va perché l'aggiunta la fai dentro il while, dal quale non uscirai mai perché appena trovi la fine della lista inserisci un nuovo blocco e non aggiorni più il puntatore node, per cui non smetterai mai di ripetere l'aggiunta dell'ultimo blocco.

Fai prima un ciclo while dove imponi come condizione che siano validi sia il blocco attuale che il blocco successivo. Appena fallirà la condizione, uscirai dal ciclo while stando sull'ultimo blocco.

Avrai due casi: o ti fermerai su NULL (nel qual caso la lista è vuota), o ti fermerai su un qualche nodo, sul quale potrai usare la list_insert_after().

Se sai che dovrai fare un gran numero di inserimenti in coda o in testa, prendi in considerazione l'idea di usare liste circolari. ;)

guylmaster
04-06-2010, 23:10
Non va perché l'aggiunta la fai dentro il while, dal quale non uscirai mai perché appena trovi la fine della lista inserisci un nuovo blocco e non aggiorni più il puntatore node, per cui non smetterai mai di ripetere l'aggiunta dell'ultimo blocco.

Fai prima un ciclo while dove imponi come condizione che siano validi sia il blocco attuale che il blocco successivo. Appena fallirà la condizione, uscirai dal ciclo while stando sull'ultimo blocco.

Avrai due casi: o ti fermerai su NULL (nel qual caso la lista è vuota), o ti fermerai su un qualche nodo, sul quale potrai usare la list_insert_after().

Se sai che dovrai fare un gran numero di inserimenti in coda o in testa, prendi in considerazione l'idea di usare liste circolari. ;)

Mi puoi fare un esempio pratico del while che sono totalmente fuso? :fagiano:

DanieleC88
04-06-2010, 23:18
Abbozzo uno pseudocodice:

nodo_t x = lista->testa;

finché (x non è nullo) e (x->next non è nullo) {
x = x->next;
}

aggiungi_dopo(x, nuovoValore);

A te la gestione del caso in cui ottieni un x nullo... :p

guylmaster
04-06-2010, 23:22
Abbozzo uno pseudocodice:

nodo_t x = lista->testa;

finché (x non è nullo) e (x->next non è nullo) {
x = x->next;
}

aggiungi_dopo(x, nuovoValore);

A te la gestione del caso in cui ottieni un x nullo... :p

L'ho riscritta così:

NODE *Inserisci_alla_fine(NODE *node, float data)
{
NODE2 *newnode;
while(node && node->next)
{
node = node->next;
}
list_insert_after2(node, data);
return newnode;
}


Ma mi concatena un valore 0.000000 :fagiano:

DanieleC88
04-06-2010, 23:25
No, non ti concatena uno zero, è che... newnode chi lo inizializza? :D

E ricordati di gestire il caso in cui node è nullo!

guylmaster
04-06-2010, 23:32
No, non ti concatena uno zero, è che... newnode chi lo inizializza? :D

E ricordati di gestire il caso in cui node è nullo!

Emm come lo devo inizializzare?

Ho visto che se sostituito " newnode=list_create(data);" con " newnode=list_create(333.333);" funziona. Ovvero se invece di passargli la variabile data metto direttamente il numero float.

Possibile?

guylmaster
04-06-2010, 23:34
Che poi l'inizializzazione non la fa esattamente la riga di codice:


newnode=list_create(data);


no?

guylmaster
04-06-2010, 23:39
Cioè attualmente il codice della mia funzione è questo:


NODE *Inserisci_alla_fine(NODE *node, float data)
{
NODE2 *newnode;
while(node->next != NULL)
{
node = node->next;
}
newnode=list_create(data);
node->next = newnode;
return newnode;
}



Se la riga "newnode=list_create(data);" la sostituisco con "newnode=list_create(666);" va, altrimenti continua a concatenare 0.000000... non me lo so proprio spiegare.

DanieleC88
04-06-2010, 23:39
Sì, ma quella è una riga che "vive" nel contesto di list_insert_after2(), e le modifiche che fai lì non saranno visibili nella tua Inserisci_alla_fine()... :)

guylmaster
04-06-2010, 23:52
Sì, ma quella è una riga che "vive" nel contesto di list_insert_after2(), e le modifiche che fai lì non saranno visibili nella tua Inserisci_alla_fine()... :)

Sarà che sto fuso ma davvero non riesco a capire il problema, so che non è bello chiedere "direttamente" la soluzione, ma se mi puoi far notare chiaramente la soluzion te ne sarei grato. Perchè così su due piedi non mi sto proprio raccapezzando.

DanieleC88
05-06-2010, 00:04
Ho visto adesso l'ultimo post col codice modificato, e così (in teoria) dovrebbe funzionare, non saprei dirti su due piedi cosa succede.

Consiglio: dormici su e ripensaci domani con calma. :cool:

guylmaster
05-06-2010, 00:07
Ho visto adesso l'ultimo post col codice modificato, e così (in teoria) dovrebbe funzionare, non saprei dirti su due piedi cosa succede.

Consiglio: dormici su e ripensaci domani con calma. :cool:

Ci sto impazzendo, perchè a quanto pare il float passato nella matrice, se gli passo una cifra mi prende a volte -2, a volte 0.0000 e non ho capito minimamente il perchè di questo.

Sembrerebbe come se ci fosse qualche problema nel "tipo" di definizione del numero. Eppure nel main lo dichiarato come float, nelle funzioni pure.. non capisco dove sbaglio :fagiano:

DanieleC88
05-06-2010, 00:12
Domattina rileggilo e ripensaci. Se non riuscirai a risolverlo nemmeno domattina, posta l'intero codice, così almeno non andiamo per tentativi.

guylmaster
05-06-2010, 00:14
L'intero codice è questo:

funzioni.h

/*Elementi pubblici della libreria funzioni*/

//Struttura dati
typedef struct node_s {
float data;
struct node_s *next;
struct node_s *next_down;
} NODE;


typedef struct node_s2 {
float data;
struct node_s2 *next;
} NODE2;


//Prototipi funzioni
NODE *list_create(float data);
NODE2 *list_create2(float data);
void stampa_lista(NODE *list);
NODE *list_insert_after(NODE *node, float data);


funzioni.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

NODE *list_create(float data)
{
NODE *node;
if(!(node=malloc(sizeof(NODE)))) return NULL;
node->data=data;
node->next=NULL;
return node;
}

NODE2 *list_create2(float data)
{
NODE2 *node;
if(!(node=malloc(sizeof(NODE2)))) return NULL;
node->data=data;
node->next=NULL;
return node;
}

void stampa_lista(NODE *list)
{
while(list)
{
printf("[%f]\n", list->data);
list = list->next;
}
}
void stampa_colonna(NODE2 *list)
{
while(list)
{
printf("[%f]\n", list->data);
list = list->next;
}
}

NODE *list_insert_after(NODE *node, float data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}

NODE *list_insert_after2(NODE2 *node, float data)
{
NODE2 *newnode;
newnode=list_create(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}

NODE *Inserisci_alla_fine(NODE *node, float data)
{
NODE2 *newnode;
printf("\n\n[[[%f]]]",data);
while(node->next != NULL)
{
node = node->next;
}
newnode=list_create2(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}



main.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

int main()
{
NODE *list;
NODE2 *list2;
float numero;
numero = 32.9;
list = list_create(563);
list2 = list_create2(43);
list->next_down = list2;
//list_insert_after(list, 1.987);
//list_insert_after(list2, 555);
Inserisci_alla_fine(list2, numero);
//stampa_lista(list);
stampa_colonna(list->next_down);
system("PAUSE");
return 0;
}

DanieleC88
05-06-2010, 00:30
Prova dichiarando Inserisci_alla_fine() anche nell'header...
Se il compilatore non trova dichiarata la funzione che invoca, solitamente assume che i parametri siano di tipo int, che casualmente ha la stessa dimensione del void*, ma non certo del float.

Compila sempre con tutti i warning attivi, e dagli ascolto. :)
Il codice alla fine dovrai cercare di renderlo più pulito, secondo me potresti cavartela anche implementando un solo tipo di lista, e non due separati.

guylmaster
05-06-2010, 00:39
Prova dichiarando Inserisci_alla_fine() anche nell'header...
Se il compilatore non trova dichiarata la funzione che invoca, solitamente assume che i parametri siano di tipo int, che casualmente ha la stessa dimensione del void*, ma non certo del float.

Compila sempre con tutti i warning attivi, e dagli ascolto. :)
Il codice alla fine dovrai cercare di renderlo più pulito, secondo me potresti cavartela anche implementando un solo tipo di lista, e non due separati.

Ecco effettivamente era quello l'errore, anche se mi scrive invece di 32.978 il numero 32.978001 (e quell'1 non mi spiego da dove esca).

Come consiglieresti tu di sviluppare una sola struttura ?
Conta che per adesso c'è il tipo float anche nella prima struttura ma in realtà da li lo devo cancellare (era solo per prova).

DanieleC88
05-06-2010, 00:47
Che ti scriva un numero un po' diverso è normale, è per via dell'approssimazione che viene fatta nella rappresentazione di quel numero... In base 2 alcuni numeri con la virgola vengono periodici. Non c'è, ad esempio, una rappresentazione intera del numero 0.2! :O

Per come strutturare la lista... che esercizio è se te lo faccio io? Proponi tu delle modifiche. :p
A domani.

ciao ;)

guylmaster
05-06-2010, 00:59
Umm ho fatto qualche modifica ed ho provato ad aggiungere un'altra "colonna" alla matrice e ora non si compila nemmeno più, ahia.

Il codice attuale è il seguente:

main.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

int main()
{
NODE *list;
NODE2 *list2,list3;
float numero;
numero = 32.978;
list = list_create();
list2 = list_create2(43);
list->next_down = list2;
//list_insert_after(list, 1.987);
//list_insert_after(list2, 555);
Inserisci_alla_fine(list2, numero);
Inserisci_alla_fine(list2, 5.2);
Inserisci_alla_fine(list2, 3.4);
Inserisci_alla_fine(list2, 5.8);
Inserisci_alla_fine2(list);

list3 = list_create2(33);
list->next_down = list3;
Inserisci_alla_fine(list3, 99.99);
//stampa_lista(list);
stampa_colonna(list->next_down);
system("PAUSE");
return 0;
}


funzioni.h

/*Elementi pubblici della libreria funzioni*/

//Struttura dati
typedef struct node_s {
struct node_s *next;
struct node_s2 *next_down;
} NODE;


typedef struct node_s2 {
float data;
struct node_s2 *next;
} NODE2;


//Prototipi funzioni
NODE *list_create();
NODE2 *list_create2(float data);
void stampa_lista(NODE *list);
NODE *list_insert_after(NODE *node, float data);
NODE2 *list_insert_after2(NODE2 *node, float data);
NODE2 *Inserisci_alla_fine(NODE2 *node, float data);
NODE *Inserisci_alla_fine2(NODE *node);


funzioni.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

NODE *list_create()
{
NODE *node;
if(!(node=malloc(sizeof(NODE)))) return NULL;
node->next=NULL;
return node;
}

NODE2 *list_create2(float data)
{
NODE2 *node;
if(!(node=malloc(sizeof(NODE2)))) return NULL;
node->data=data;
node->next=NULL;
return node;
}

void stampa_lista(NODE *list)
{
while(list)
{
printf("[%f]\n", list->data);
list = list->next;
}
}
void stampa_colonna(NODE2 *list)
{
while(list)
{
printf("[%f]\n", list->data);
list = list->next;
}
}

NODE *list_insert_after(NODE *node, float data)
{
NODE *newnode;
newnode=list_create(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}

NODE2 *list_insert_after2(NODE2 *node, float data)
{
NODE2 *newnode;
newnode=list_create2(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}
NODE *Inserisci_alla_fine2(NODE *node)
{
NODE *newnode;
while(node->next != NULL)
{
node = node->next;
}
newnode=list_create();
newnode->next = node->next;
node->next = newnode;
return newnode;
}

NODE2 *Inserisci_alla_fine(NODE2 *node, float data)
{
NODE2 *newnode;
while(node->next != NULL)
{
node = node->next;
}
newnode=list_create2(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}



Nel main mi da "incompatible type of assignment" in queste tre righe:


list3 = list_create2(33);
list->next_down = list3;
Inserisci_alla_fine(list3, 99.99);


Eppure qualche riga di codice sopra ho creato alla stessa maniera list2! Se commento quelle righe si compila.

guylmaster
05-06-2010, 01:05
Come non detto,
mi ero sbagliato a dichiarare list3 e non l'avevo dichiarata come puntatore.

Domanda, ma se volessi tener conto di dove inizia la lista, dove potrei salvarmelo tale dato? Vorrei evitare poco pratiche variabili globali, ma se volessi salvarmelo nella struttura come dovrei fare?

Inoltre mi dicevi di gestire il caso in cui node è nullo, che intendevi?

TRF83
05-06-2010, 09:01
Domanda, ma se volessi tener conto di dove inizia la lista, dove potrei salvarmelo tale dato? Vorrei evitare poco pratiche variabili globali, ma se volessi salvarmelo nella struttura come dovrei fare?
Cosa intendi con "dove inizia la lista"? Nel tuo main, questo dato è rappresentato dalla variabile list..


Inoltre mi dicevi di gestire il caso in cui node è nullo, che intendevi?

Penso che intendesse dire, in pratica, in caso tu debba inserire il primo elemento, e quindi il node passato valga NULL. In questo caso non puoi associare a newnode->next node->next, perchè node->next semplicemente non esiste! Vero è che con una gestione come quella che stai facendo tu (cioè con il primo nodo allocato "a mano" tramite chiamata di list_creat) tale problema NON DOVREBBE mai verificarsi. Per sicurezza, però, il controllo sulla validità di node e, quindi, sulla condizione di uscita dal while lo farei.. Intendo dire: se esci per via di node->next==NULL, allochi normalmente come fai già ora; se invece esci per via di node==NULL, invece di allocare newnode, allochi node. Può sembrare una cosa banale e stupida, ma se nel tuo programma ci saranno delle cancellazioni previste, il fatto di trovarti a metà codice con la lista totalmente vuota, non è poi così remoto..

guylmaster
05-06-2010, 09:43
Bene, quello che intendevo io sull'inizio della lista è di prevedere appunto un puntatore a inizio lista.

Trattandosi di una libreria non posso semplicemente creare un puntatore nel main che punti all'inizio della lista, ma devo prevedere nella mia struttura funzioni.c un elemento che punti alla lista.

Il punto è che non posso fare una variabile globale perchè, se uno richiama più volte la libreria per creare più di una struttura di quel tipo, come faccio?

E se creassi un ulteriore struttura con due nodi, uno che punta alla testa ed uno che punta alla coda? Oppure che altre soluzioni ci sono?

DanieleC88
05-06-2010, 11:11
Non c'è bisogno di variabili globali, semplicemente usa funzioni che restituiscano il puntatore alla testa della lista, o NULL se fallisci. Così ti basterà invocare le tue funzioni in questo modo:

list_t lista = NULL;

[...]

lista = list_do_something(lista, valore);

E in questo modo, una volta che avrai restituito la nuova testa della lista al chiamante, avrai propagato tutte le modifiche all'esterno.
Un altro approccio che potresti adottare è quello di ricevere in input nelle tue funzioni non una lista, ma un puntatore ad una lista (in modo così da poterla modificare direttamente da dentro alla funzione che utilizzi).

guylmaster
05-06-2010, 11:43
Non c'è bisogno di variabili globali, semplicemente usa funzioni che restituiscano il puntatore alla testa della lista, o NULL se fallisci. Così ti basterà invocare le tue funzioni in questo modo:

list_t lista = NULL;

[...]

lista = list_do_something(lista, valore);

E in questo modo, una volta che avrai restituito la nuova testa della lista al chiamante, avrai propagato tutte le modifiche all'esterno.
Un altro approccio che potresti adottare è quello di ricevere in input nelle tue funzioni non una lista, ma un puntatore ad una lista (in modo così da poterla modificare direttamente da dentro alla funzione che utilizzi).

Appunto, se invece di passare in pasto alle mie funzioni, il puntatore ad inizio lista, creo un secondo puntatore che punta ad inizio lista e gli passo quello riesco comunque a mantenere la testa della lista, no?

Anche perchè io poi, per creare quella struttura a forma di matrice, avrò un ulteriore struttura chje sarà del tipo:


typedef struct matrice
{
NODE Inizio_Lista;
int righe;
int colonne;
} matrice;


Quello che dovrò creare saranno, sostanzialmente, tre funzioni:

- Leggi in posizione riga-colonna;
- Scrivi in posizione riga-colonna;
- Stampa l'intero contenuto della lista sottoforma di matrice;

Facciamo unesempio di scrivi all'interno di una determinata posizione in pseudocodice.

Io fornirò il prototipo all'utente del tipo:
Scrivi_elemento(Puntatore_Inizio_lista, riga, colonna,elemento);

Poi scrivi elemento si comporterà cosi:

Creo NODO che punta a Puntatore_Inizio_lista
Per i che va da 1 a riga
NODO = NODO-> Next
NODO = NODO_Next_Down

Per i che va da 1 a colonna
NODO = NODO->Next
NODO->data = elemento


Cosa ne pensi come implementazione? e cosi il puntatore ad inizio lista non dovrebbe essere toccato.

DanieleC88
05-06-2010, 15:37
A grandi linee direi che va bene così.
Io infatti di solito utilizzo una organizzazione di questo tipo in C:
struct node_s {
TipoDati valore;
struct node_s *next;
};

struct list_s {
struct node_s *head;
struct node_s *tail;
unsigned int elements;
};

typedef struct node_s Node;
typedef struct list_s List;
in modo da operare sempre sulla stessa struttura List che riceverò in input nelle varie funzioni, e sapendo già quali sono la testa e la coda della lista (in modo da inserire in tempo costante sia nodi in testa alla lista che in coda alla lista, anche se si potrebbe utilizzare un unico puntatore ed una lista circolare!) e quanti sono gli elementi che essa contiene.

Se tu utilizzassi come tipo di dato un generico puntatore a void, allora potresti creare una prima lista (la "riga di colonne" nell'immagine che portavi come esempio in primo post), la quale conterrà un puntatore ad un'altra lista strutturata in maniera del tutto simile, la quale salverà i valori della matrice dentro i propri campi void*, ed eventualmente a seguito di opportuni cast per fare felice il compilatore.

Implementato così una sola volta il generico tipo di dato "lista", potrai scrivere delle funzioni che saranno coscienti di questo annidamento interno, e che sapranno accedere correttamente in lettura/scrittura ai campi della matrice in questione. A quel punto, il tipo di dato "matrice" che andrai a creare potrà anche essere semplicemente il puntatore ad una particolare lista.

ciao ;)

guylmaster
05-06-2010, 17:29
A grandi linee direi che va bene così.
Io infatti di solito utilizzo una organizzazione di questo tipo in C:
struct node_s {
TipoDati valore;
struct node_s *next;
};

struct list_s {
struct node_s *head;
struct node_s *tail;
unsigned int elements;
};

typedef struct node_s Node;
typedef struct list_s List;
in modo da operare sempre sulla stessa struttura List che riceverò in input nelle varie funzioni, e sapendo già quali sono la testa e la coda della lista (in modo da inserire in tempo costante sia nodi in testa alla lista che in coda alla lista, anche se si potrebbe utilizzare un unico puntatore ed una lista circolare!) e quanti sono gli elementi che essa contiene.

Se tu utilizzassi come tipo di dato un generico puntatore a void, allora potresti creare una prima lista (la "riga di colonne" nell'immagine che portavi come esempio in primo post), la quale conterrà un puntatore ad un'altra lista strutturata in maniera del tutto simile, la quale salverà i valori della matrice dentro i propri campi void*, ed eventualmente a seguito di opportuni cast per fare felice il compilatore.

Implementato così una sola volta il generico tipo di dato "lista", potrai scrivere delle funzioni che saranno coscienti di questo annidamento interno, e che sapranno accedere correttamente in lettura/scrittura ai campi della matrice in questione. A quel punto, il tipo di dato "matrice" che andrai a creare potrà anche essere semplicemente il puntatore ad una particolare lista.

ciao ;)

A dir la verità vorrei evitare di complicare troppo le cose.
Adesso ho riscritto un pò le funzioni con dei nomi più "capibili" e ho dato una mini-pulizia al codice.

Adesso però vado in segmentation fault nella funzione in cui cerco di creare la matrice, ovvero una funzione che crea tutti i singoli nodi, mettendo però come campo dell'elemento float della seconda lista il valore 0.

Non riesco a capire dove sbaglio, vi riposto il codice intero:

funzioni.h

/*Elementi pubblici della libreria funzioni*/

//Struttura dati
typedef struct nodo_puntatori {
struct nodo_puntatori *seguente;
struct nodo_puntatori *seguente_down;
} nodo_puntatori;


typedef struct nodo_colonna {
float elemento;
struct nodo_colonna *seguente;
} nodo_colonna;

typedef struct matrice {
int numero_righe;
int numero_colonne;
nodo_puntatori *lista;
} matrice;

//Prototipi funzioni private
nodo_puntatori *crea_lista_puntatori();
nodo_colonna *crea_lista_colonna(float elemento);
void stampa_colonna(nodo_colonna *lista);
nodo_puntatori *Inserisci_a_fine_puntatori(nodo_puntatori *nodo);
nodo_colonna *Inserisci_a_fine_colonna(nodo_colonna *nodo, float elemento);

//Prototipi funzioni pubbliche
void creamatrice(matrice *matrice, int riga, int colonna);


main.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

int main()
{
matrice matrice;
creamatrice(&matrice, 4, 4);
stampa_colonna(matrice.lista->seguente_down);

system("PAUSE");
return 0;
}



funzioni.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

nodo_puntatori *crea_lista_puntatori()
{
nodo_puntatori *nodo;
nodo=malloc(sizeof(nodo_puntatori));
nodo->seguente=NULL;
return nodo;
}

nodo_colonna *crea_lista_colonna(float elemento)
{
nodo_colonna *nodo;
nodo=malloc(sizeof(nodo_colonna));
nodo->elemento=elemento;
nodo->seguente=NULL;
return nodo;
}

void stampa_colonna(nodo_colonna *lista)
{
nodo_colonna *scorri;
scorri = lista;
while(scorri)
{
printf("[%f]\n", scorri->elemento);
scorri = scorri->seguente;
}
}

nodo_puntatori *Inserisci_a_fine_puntatori(nodo_puntatori *nodo)
{
nodo_puntatori *scorri;
scorri = nodo;
nodo_puntatori *nuovo_nodo;
while(scorri->seguente != NULL)
{
scorri = scorri->seguente;
}
nuovo_nodo = crea_lista_puntatori();
nuovo_nodo->seguente = scorri->seguente;
scorri->seguente = nuovo_nodo;
return nuovo_nodo;
}

nodo_colonna *Inserisci_a_fine_colonna(nodo_colonna *nodo, float elemento)
{
nodo_colonna *nuovo_nodo,*scorri;
scorri = nodo;
while(scorri->seguente != NULL)
{
scorri = scorri->seguente;
}
nuovo_nodo = crea_lista_colonna(elemento);
nuovo_nodo->seguente = scorri->seguente;
scorri->seguente = nuovo_nodo;
return nuovo_nodo;;
}

void creamatrice(matrice *matrice, int riga, int colonna)
{
int i,j;
nodo_colonna *lista_colonna;
nodo_puntatori *scorri_puntatori;
scorri_puntatori = matrice->lista;

//***********************************
matrice->numero_righe = riga;
matrice->numero_colonne = colonna;
//***********************************

for(i=0; i < colonna; i++)
{
if(i == 0)
{
scorri_puntatori = crea_lista_puntatori();
}
else
{
scorri_puntatori = Inserisci_a_fine_puntatori(scorri_puntatori);
}
}

scorri_puntatori = matrice->lista;
for(i=0; i < colonna; i++)
{
for(j=0; j < riga; j++)
{
if(i == 0)
{
lista_colonna = crea_lista_colonna(i);
scorri_puntatori->seguente_down = lista_colonna;
}
else
{
Inserisci_a_fine_colonna(scorri_puntatori->seguente_down, j);
}
}
scorri_puntatori = scorri_puntatori->seguente;
}



}


La funzione incriminata è la

void creamatrice(matrice *matrice, int riga, int colonna);


Praticamente prim alloca il puntatore diciamo di puntatori, con un primo ciclo, con il secondo ciclo dovrebbe accedere ad ogni elemento della prima lista e creare la seconda lista.

Ad andare in segmentation fault è proprio in questo nuovo ciclo, e l'istruzione che lo fa crashare è:

scorri_puntatori = scorri_puntatori->seguente;


Che dovrebbe dirgli, una volta creata l'intera lista della colonna, di passare al prossimo elemento della lista di puntatori.

Se commento quella riga di codice semplicemente mi stampa tutti gli elementi in una sola colonna (nel main ho richiamato la funzione stampa_colonna() proprio per vedere cosa combinava).

Non so, forse nel primo ciclo non alloca bene la prima lista e quando gli dice di passare al secondo elemento nel primo mi va in segmentation fault?

DanieleC88
05-06-2010, 17:38
Tu innanzitutto allochi una struttura "matrice" contenente un puntatore, ma non la inizializzi. Il valore del puntatore matrice->lista a seguito della creazione della matrice sullo stack quanto varrà?

Poi crei una riga di colonne usando un iteratore "scorri_puntatori", ma poi non lo assegni a matrice->lista, anzi: lo sovrascrivi proprio col valore di matrice->lista, che per l'appunto non è inizializzato e punterà a qualche zona a caso della memoria...

Stai molto attento ai puntatori quando scrivi il codice!

guylmaster
05-06-2010, 17:40
Tra l'altro ho un grosso dubbio, ho provato a scorrere nelle liste manualmente con il main in questo modo:


#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "funzioni.h"

int main()
{
nodo_puntatori *lista, *head;
nodo_colonna *lista2,*lista3;
float numero;
numero = 0.11;

lista = crea_lista_puntatori();
head = lista;
lista2 = crea_lista_colonna(numero);
lista->seguente_down = lista2;
Inserisci_a_fine_colonna(lista2, 1.11);
Inserisci_a_fine_colonna(lista2, 2.22);
Inserisci_a_fine_colonna(lista2, 3.33);
//stampa_colonna(lista2);
//******************************************************************************
lista3 = crea_lista_colonna(4.44);
Inserisci_a_fine_puntatori(lista);
lista->seguente_down = lista3;
Inserisci_a_fine_colonna(lista3, 5.55);
Inserisci_a_fine_colonna(lista3, 6.66);
Inserisci_a_fine_colonna(lista3, 7.77);

stampa_colonna(head->seguente_down);
head = head->seguente;
stampa_colonna(head->seguente_down);
//******************************************************************************

system("PAUSE");
return 0;
}



Dovre praticamente creo il primo elemento della prima lista, e ci attacco sotto la nuova lista; Creo un'altro elemento della prima lista e ci attacco sotto una nuova lista;

Prima però mi ero creato un puntatore *head che punta all'inizio della lista, e con le funzioni:


stampa_colonna(head->seguente_down);
head = head->seguente;
stampa_colonna(head->seguente_down);


vorrei stampare le due colonne, invece mi va in loop e mi stampa tutti zero. Se metto solo la prima stampa invece mi stampa solo l'ultima colonna aggiunta.

guylmaster
05-06-2010, 17:42
Tu innanzitutto allochi una struttura "matrice" contenente un puntatore, ma non la inizializzi. Il valore del puntatore matrice->lista a seguito della creazione della matrice sullo stack quanto varrà?

Poi crei una riga di colonne usando un iteratore "scorri_puntatori", ma poi non lo assegni a matrice->lista, anzi: lo sovrascrivi proprio col valore di matrice->lista, che per l'appunto non è inizializzato e punterà a qualche zona a caso della memoria...

Stai molto attento ai puntatori quando scrivi il codice!

Ovvero cosa dovrei fare per inizializzarla?

DanieleC88
05-06-2010, 17:46
Quanto meno un:
memset(&strutturaDellaMatrice, 0, sizeof(matrice));

EDIT: e correggi il codice di quella funzione creamatrice(), ha errori.

guylmaster
05-06-2010, 17:51
Quanto meno un:
memset(&strutturaDellaMatrice, 0, sizeof(matrice));

EDIT: e correggi il codice di quella funzione creamatrice(), ha errori.

Che errori? e che intendi nel codice per "&strutturaDellaMatrice" ?

Ho provato a scrivere solo questo codice nel main, mi va comunque in segmentation fault:
matrice matrice;
memset(&matrice, 0, sizeof(matrice));
creamatrice(&matrice, 4, 4);

DanieleC88
05-06-2010, 17:56
Il codice l'hai tradotto bene, intendevo proprio quello. :)
Però come vedi non basta! Devi correggere la funzione di creazione della matrice... leggila per bene e capirai dove sbagli. Non posso mica farti tutto io. :p

ciao ;)

guylmaster
05-06-2010, 18:04
Il codice l'hai tradotto bene, intendevo proprio quello. :)
Però come vedi non basta! Devi correggere la funzione di creazione della matrice... leggila per bene e capirai dove sbagli. Non posso mica farti tutto io. :p

ciao ;)

Ehm, no davvero, sto impazzendo per questo esame, e ho la consegna a giorni, se hai visto dove è l'errore e potresti dirmelo mi risolveresti un sacco di rogne.

guylmaster
05-06-2010, 18:11
Nel secondo ciclo effettivamente c'era un errore, l'if valuava la variabile "i" invece che "j". Ma anche cambiando quella comunque quella stringa di codice mi manda il programma in segmentation fault!

DanieleC88
05-06-2010, 18:18
Pensa: cosa fa quel "scorri_puntatori = matrice->lista"?

guylmaster
05-06-2010, 19:08
Pensa: cosa fa quel "scorri_puntatori = matrice->lista"?

Fa si che scorri_puntatori punti all'indirizzo di matrice->lista, in modo da avere un puntatore all'inizio della lista, o no?

DanieleC88
05-06-2010, 19:18
È quello che vorresti, ma dove punta matrice->lista? :D

guylmaster
05-06-2010, 19:26
È quello che vorresti, ma dove punta matrice->lista? :D

Evidentemente non li.
Dai cosi facnedo dov'è che punta? per scriverlo correttamente cosa dovrei fare?
Su è davvero diabolico aver trovato l'errore e non volermelo dire :fagiano:

DanieleC88
05-06-2010, 19:47
Non è diabolico, sarei sicuramente meno d'aiuto se non cercassi di farti ragionare su ciò stai facendo. Così risolveresti questo problema sul momento, e alla prossima funzione ti ritroveresti un bug che non sai spiegarti.

Una volta che tu ricevi il puntatore ad una struttura di cui hai azzerato tutta la memoria con la memset() di prima, avrai che matrice->lista punta a 0, ovvero a NULL. Con quel scorri_puntatore = matrice->lista stai effettivamente scegliendo di iniziare l'iterazione della lista su... NULL, possibile? No, e infatti va in crash.

In realtà tu avresti voluto fare il contrario: una volta allocata la riga di colonne (la prima lista), avresti voluto assegnare il riferimento corretto a quanto appena creato. Quindi, al limite, sarebbe stato un matrice->lista = scorri_puntatore.

Rivedi la logica di quella funzione, se ti gira riscrivila interamente: la puoi fare più semplice e meno soggetta ad errori. :)
(E ci perdi meno tempo di quanto ce ne vorrebbe a debuggarla.)

ciao ;)

guylmaster
05-06-2010, 19:51
Non è diabolico, sarei sicuramente meno d'aiuto se non cercassi di farti ragionare su ciò stai facendo. Così risolveresti questo problema sul momento, e alla prossima funzione ti ritroveresti un bug che non sai spiegarti.

Una volta che tu ricevi il puntatore ad una struttura di cui hai azzerato tutta la memoria con la memset() di prima, avrai che matrice->lista punta a 0, ovvero a NULL. Con quel scorri_puntatore = matrice->lista stai effettivamente scegliendo di iniziare l'iterazione della lista su... NULL, possibile? No, e infatti va in crash.

In realtà tu avresti voluto fare il contrario: una volta allocata la riga di colonne (la prima lista), avresti voluto assegnare il riferimento corretto a quanto appena creato. Quindi, al limite, sarebbe stato un matrice->lista = scorri_puntatore.

Rivedi la logica di quella funzione, se ti gira riscrivila interamente: la puoi fare più semplice e meno soggetta ad errori. :)
(E ci perdi meno tempo di quanto ce ne vorrebbe a debuggarla.)

ciao ;)

Ma spiegamelo con delle righe di codice, cosi a parole non ci sto capendo nulla :fagiano:

DanieleC88
05-06-2010, 19:56
Ma se il codice di cui parlo l'hai scritto tu! :confused:
Se mi rispondi a bruciapelo senza prima aver ragionato sul codice non se ne fa niente. ;)

guylmaster
05-06-2010, 19:58
Cioè qualcosa del genere? (che comunuqe non funziona mi va in segmentation fault)


void creamatrice(matrice *matrice, int riga, int colonna)
{
int i,j;
nodo_colonna *lista_colonna;
nodo_puntatori *scorri_puntatori;
scorri_puntatori = matrice->lista;
//***********************************
matrice->numero_righe = riga;
matrice->numero_colonne = colonna;
//***********************************

for(i=0; i < colonna; i++)
{
for(j=0; j < riga; j++)
{
if(j == 0)
{
lista_colonna = crea_lista_colonna(i);
scorri_puntatori->seguente_down = lista_colonna;
//scorri_puntatori->seguente_down = (nodo_puntatori*)lista_colonna;
}
else
{
Inserisci_a_fine_colonna(lista_colonna, j);
}
}
scorri_puntatori->seguente_down = lista_colonna;
scorri_puntatori = scorri_puntatori->seguente;
}



}


Perfavore aiutami con del codice che cosi a parole non ti sto seguendo proprio.

guylmaster
05-06-2010, 20:14
L'ho riscritta cosi:


void creamatrice(matrice *matrice, int riga, int colonna)
{
int i,j;
nodo_colonna *lista_colonna;
nodo_puntatori *scorri_puntatori;
//***********************************
matrice->numero_righe = riga;
matrice->numero_colonne = colonna;
//***********************************
scorri_puntatori = crea_lista_puntatori();
matrice->lista = scorri_puntatori;
for(i=0; i < colonna; i++)
{
for(j=0; j < riga; j++)
{
if(j == 0)
{
lista_colonna = crea_lista_colonna(0);
}
else
{
Inserisci_a_fine_colonna(lista_colonna, 1);
}
}
scorri_puntatori->seguente_down = lista_colonna;
scorri_puntatori = Inserisci_a_fine_puntatori(scorri_puntatori);

}



}


Dici che ho risolto o è una mia pia illusione? :fagiano:

Te lo chiedo perchè ti vedo piu esperto e temo di non avere stasera il tempo per testarla perbenino, ma vorrei andare a dormire "tranquillo" :D

guylmaster
05-06-2010, 20:18
Ho provato a dare queste stampe nel main e sembra andare:


matrice ma;
creamatrice(&ma, 4, 4);
printf("COLONNA 1\n");
stampa_colonna(ma.lista->seguente_down);
ma.lista = ma.lista->seguente;
printf("COLONNA 2\n");
stampa_colonna(ma.lista->seguente_down);
ma.lista = ma.lista->seguente;
printf("COLONNA 3\n");
stampa_colonna(ma.lista->seguente_down);
ma.lista = ma.lista->seguente;
printf("COLONNA 4\n");
stampa_colonna(ma.lista->seguente_down);
ma.lista = ma.lista->seguente;
printf("COLONNA 5\n");
stampa_colonna(ma.lista->seguente_down);


All'ultima stampa, la 5, essendo di 4x4, mi da una stampa vuota, se ne aggiuno un'altra crasha. Evidentemente alle quinta stampa si posa sul nodo "NULL" di fine lista.

DanieleC88
05-06-2010, 21:08
Dici che ho risolto o è una mia pia illusione? :fagiano:
Abbastanza. ;)
Vedi che ci potevi arrivare?

guylmaster
06-06-2010, 11:12
Abbastanza. ;)
Vedi che ci potevi arrivare?

Il punto è che non sapevo come allocarlo a manina, poi però mi sono accorto che invece di scervellarmi per creare nuove righe di codice che allocassero lo facevano già le mie stesse funzioni.

Il punto però non è il non volermela cavare da solo, è il tempo hce stringe :fagiano: