strutture dati nel linguaggio c

Pubblicità

seven speed

Nuovo Utente
Messaggi
19
Reazioni
0
Punteggio
25
ragazzi sto preparando un esame di programmazione di base (sono iscritto al primo anno del polito).con il linguaccio c ho preso abbastanza dimestichezza le uniche cose che non ho ben capito sono le strutture dati.(mi manca inoltre solo un po di esercizio sulla riga di comando,ma non mi sembra nulla di impossibile).non ho capito:ma in una struttara,ci si può scrivere?cioè è una variabile a tutti gli effetti come con un vettore in cui sono io da tastiera a scegliere i dati da inserire?ad esempio in un struttura in cui c'è una variabile char che rappresenta il nome ed un int che rappresenta una valutazione,sono io che da tastiera scrivo nome e voto,o sono dati gia salvati in un file a cui devo fare riferimento?purtroppo ho a disposizione pochi programmi da prendere in esempio e questi mi sembrano poco chiari...mi potete dare voi qualche delucidazione?
 
Ciao Seven,premetto che non sono un esperto programmatore,però conosco qualcosina,e spero di esserti utile,e se vuoi puoi continuare a scrivere per chiarire dei dubbi,e se saprò risponderti,appena avrò tempo lo farò volentieri.
Adesso non ho materiale sotto gli occhi,e non sono sicuro di ricordare bene,e pertanto mi mantengo sul generico.
1)Il compilatore riserva dello spazio di memoria per allocare variabili,puntatori,vettori,...,che varia a seconda del tipo(int,float,...).
Non tutti gli elementi sono memorizzati in aree di memoria gestite con caratteristiche identiche,ad esempio vi sono dati che vengono memorizzati nello "heap",
ed altri che vengono memorizzati in altre aree della memoria.
2)Non tutti gli elementi hanno caratteristiche simili.
Ad esempio i vettori,le matrici(vettori multi dimensionali)i quali sono degli insiemi di elementi tutti dello stesso tipo,hanno una dimensione fisica(quella allocata dal compilatore al momento della loro dichiarazione)ed una dimensione logica,ossia il numero di celle che l'utente decide di utilizzare per risolvere il suo problema specifico.
Tuttavia,tali elementi non sono gestiti in modo dinamico dal compilatore,cioè,non è possibile modificare la loro dimensione fisica durante la fase di sviluppo del codice,e questo può presentare degli svantaggi notevoli.
Vi sono strutture dati(astratte) dinamiche,come liste(semplici,con priorità-ossia gestite tramite un ordinamento specifico-,con doppi puntatori...)code,code circolari,pile...(che sono anch'esse riconducibili al tipo di dato lista,ma che si differenziano tra loro perchè non sempre sono gestite allo stesso modo per quel che concerne le operazioni di base,quali inserimento o cancellazione di elementi,ad esempio in testa,in coda,...)alberi binari,...,le cui dimensioni le può modificare l'utente al momento del bisogno,a seconda delle necesità.
Per fare ciò,si può usare la funzione predefinita malloc() per allocare spazio,e la funzione predefinita free() per liberare la memoria,quando l'utente non ha
più bisogno di gestire determinati elementi correlati a tali strutture dati.
Tali strutture dati(liste,code,...)sono definite tramite il tipo di dato struttura,che si differisce dal tipo di dato array perchè contiene elementi che non sono tutti dello stesso tipo,quali ad esempio,int,flloat,...
Ciao ed in bocca al lupo seven,vedrai che andrà tutto benissimo...

- - - Updated - - -

Ciao Seven,premetto che non sono un esperto programmatore,però conosco qualcosina,e spero di esserti in qualche modo utile.
---------------
Certo seven,le strutture sono tipi di dato che possono essere inizializzate da riga di comando.
Comincio col dirti che la differenza sostanziale tra i tipi di dato struttura e gli array,è che gli array possono
contenere solamente elementi dello stesso tipo.
ALCUNI ESEMPI:
1)int vet[5]; è la dichiarazione di un array che può contenere al massimo 5 interi.
2)float vet[7]; è la dichiarazione di un array che può contenere al massimo 7 numeri decimali.
3)char str[10]; è la di chiarazione di un array di caratteri,detto comunemente "stringa",che può contenere al massimo 10
caratteri,incluso il carattere '\0' che è il carattere di fine stringa.
STRUTTURE:
Le strutture possono invece contenere anche elementi di tipi differenti.
DEFINIZIONE DI UNA STRUTTRA
struct dati
{
int valore;
char str[30];
};
Così facendo ho definito una struttura di nome dati che contiene due elementi al suo interno,ossia un dato intero di nome valore,
ed una stringa di caratteri di nome str.
Così facendo noi abbiamo solamente definito una struttura,ma il compilatore non riserverà ad essa alcuno spazio in memoria,in quanto non abbiamo dichiarato alcuna struttura.
DICHIARAZIONE DI UNA STRUTTURA
La dichiarazione di una struttura può avvenire in due modi:
1a)
struct dati
{
int valore;
char str[30];
}prima,seconda;

In tal modo abbiamo dichiarato due strutture di tipo dati,una di nome prima,e l'altra di nome seconda,ciascuna delle quali
contiene al suo interno due valori,ossia un intero di nome valore,ed una stringa di caratteri di nome str.
1b)

struct coord
{

int x;
int y;

}prima,seconda;

In tal modo abbiamo dichiarato due strutture di tipo coord,una di nome prima,e l'altra di nome seconda,ciascuna delle quali
contiene al suo interno due valori di tipo int,ossia x ed y.

2)
//Definizione della struttura coord
struct coord
{
int x;
int y;

};
//Dichiarazione delle strutture prima e seconda
struct coord prima;
struct coord seconda;
INIZIALIZZAZIONE DI UNA STRUTTURA
Supponiamo di avere:
struct coord
{
int x;
int y;
}prima,seconda;
Per accedere agli elementi x ed y delle strutture prima e seconda,si utilizza il punto . (operatore di elemento della struttura).
Pertanto,scrivendo:
prima.x accediamo all'elemento x della struttura prima,e scrivendo prima.y accediamo all'elemento y della medesima struttura(prima).
Stessa cosa dicasi per la struttura seconda.
Proviamo ora ad inizializzare i componenti delle strutture prima e seconda.
prima.x =15; //Abbiamo assegnato il valore 15 al componente x della struttura prima
prima.y=20;//Abbiamo assegnato il valore 20 al componente y della struttura prima
seconda.x=7;//Abbiamo assegnato il valore 7 al componente x della struttura seconda
seconda.y=12;//Abbiamo assegnato il valore 12 al componente y della struttura seconda
DA RIGA DI COMANDO

printf(" Inserire il valore di x della struttura prima: ");
scanf("%d",&prima.x);
printf(" Inserire il valore di y della struttura prima: ");
scanf("%d",&prima.y);
...

COI PUNTATORI
Supponiamo di avere:
struct coord
{
int x;
int y;
};

struct coord *p_int; //Dichiarazione del puntatore di tipo coord di nome p_int
Come tu sai seven,un puntatore necessita di un indirizzo di memoria a cui puntare,è pertanto dobbiamo necessariamente
dichiarare un'istanza di tipo coord alla quale il puntatore possa essere indirizzato:

struct coord prima; //Dichiarazione della struttura prima di tipo coord

p_int = &prima;//Inizializzazione del puntatore p_int

ACCESSO AI COMPONENTI DELLA STRUTTURA PRIMA
SENZA AVVALERSI DEL PUNTATORE(metodo visto precedentemente)
prima.x =10;
prima.y=9;

TRAMITE I PUNTATORI
primo modo:
(*p_int).x=10;
(*p_int).y=9;
Le parentesi sono necessarie in quanto l'operatore . ha la precedenza sull'opratore *.

secondo modo(tramite il puntatore di membro indiretto -> che si ottiene premendo il tasto meno seguito dal simbolo maffiore >):
p_int->x=10;
p_int->y=9;

Quelli che ti ho fatto io sono solamente dei semplicissimi esempi,ma le strutture possono contenere al loro interno qualsiasi tipo di dato,anche altre strutture.

ARRAY DI STRUTTURE

struct utente
{
int codice;
char nome[30];
char cogome[30];

}array[3];

Così facendo ho dichiarato tre strutture di tipo utente e di nome array,ognuna delle quali contiene al suo interno un intero di nome codice,e le stringhe nome e cognome,le quali ovviamente vanno inizializzate.
Tali strutture di nome array sono: array[0],array[1] ed array[2] in quanto come tu ben sai gli array sono indicizzati da 0 ad n-1.
Ora ti facco vedere un altro modo per inizializzare le strutture.
struct utente
{
int codice;
char nome[30];
char cogome[30];

}array[3]={{128,'Giada','Bianchi'},{002,'Clarissa','Rossi'},{13,'Serena','Venturi'}};

PERCHE' SI UTILIZZANO LE STRUTTRE?
Uno dei principali vantaggi delle strutture consiste nel fatto che si possono copiare le informazioni tra strutture dello stesso tipo,
tramite una semplice istruzione di eguaglianza.
ESEMPIO:
struct dati
{

int x;
int y;
int z;
}prima,seconda;

L'istruzione prima=seconda;
corrisponde alle tre istruzioni a seguire:
prima.x=seconda.x;
prima.y=seconda.y;
prima.z=seconda.z;

P.S.
Oggi ti ho risposto senza centrare la tua domanda,a causa del fatto che mi sono distratto.
Spero di esserti stato utile seven.
In bocca al lupo
 
grazie mille davveroo!!!! sei stato abbastanza chiaro,ma nonostante ciò non riesco a risolvere un problema..ora ti facio vedere il mio programma che non gira a dovere...è un semplice programmino di prova,cioè devo fare una struttura che tenga in un campo il nome di una materia e in un altro il voto rispettivo.l'utente dovrà inserire il nome della materia ed il voto.stop(programma di prova solo per vedere come scriverci dentro e definire le strutture,e nonostante questo il programma va mael..)
ora ti posto le righe di codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define nesami 5




struct s_esami{
char materia[50];
int voto;
};
typedef struct s_esami studente;




int main()
{


studente esame[nesami] ;
int i,j;
int giudizio;
giudizio=0;


for(i=0;i<nesami;i++)


{
printf("inserisci il nome dell'esame:");
gets(esame.materia);
}
for(i=0;i<nesami;i++)
{


printf("inserisci il voto:");
scanf("%d",&esame[j].voto);
if(esame[j].materia>23)
{
giudizio=1;
}


}
if(giudizio==1)
printf("l'esame %s e' andato bene",esame.materia);
else
printf("l'esame %s e' andato male",esame.materia);*/










return 0;
}

- - - Updated - - -

ah dimenticavo in questa versione del programma ho provato a dargli un senso facendo una piccola operazione col flag giudizio,che dovrebbe dire se l'esame è andato bene o male(nel senso che abbia avuto un voto accettabile)
 
Se ho visto bene stai usando l'indice sbagliato nel secondo ciclo; il primo usa l'indice i e tutto va bene, ma il secondo usa l'indice i per il ciclo e l'indice j per scorrere l'array (il quale non è neanche inizializzato) :)
Altra cosa, nell'if che usi stai testando il campo materia della struttura, mentre a te dovrebbe interessare voto.

Codice:
[COLOR=#333333]for(i=0;i<nesami;i++)[/COLOR][COLOR=#333333]{[/COLOR]
[COLOR=#333333]   printf("inserisci il nome dell'esame:");[/COLOR]
[COLOR=#333333]   gets(esame[i].materia);[/COLOR]
[COLOR=#333333]}[/COLOR]
Quest è il primo ciclo è va bene; anche se ti consiglierei di non usare la get in quanto rischia di crearti problemi; la get non esegue controlli sulla lunghezza della stringa in input e questo può portare a diversi problemi (in alternativa potresti scrivere una piccola funzione che legge carattere per carattere di una linea in input, così da non saltare gli spazi ed eseguire gli opportuni controlli) :)

Codice:
[COLOR=#333333]for([U][B]i[/B][/U]=0;[U][B]i[/B][/U]<nesami;[B]i[/B]++)[/COLOR][COLOR=#333333]{[/COLOR]
[COLOR=#333333]   printf("inserisci il voto:");[/COLOR]
[COLOR=#333333]   scanf("%d",&esame[[U][B]j[/B][/U]].voto);[/COLOR]
[COLOR=#333333]   if(esame[[U][B]j[/B][/U]].[B][U]materia[/U][/B]>23)[/COLOR][COLOR=#333333]{[/COLOR]
[COLOR=#333333]      giudizio=1;[/COLOR]
[COLOR=#333333]   }[/COLOR]
[COLOR=#333333]}   // [U][B]end for[/B][/U][/COLOR]
[COLOR=#333333]if(giudizio==1) [/COLOR][COLOR=#333333]printf("l'esame %s e' andato bene",esame[i].materia);[/COLOR]
[COLOR=#333333]else [/COLOR][COLOR=#333333]printf("l'esame %s e' andato male",esame[i].materia);[/COLOR]
Questo è il secondo ciclo è le parti marcate sono quelle che non vanno.
Stai usando due indici diversi nello stesso ciclo, i per muoverti nel ciclo e j per considerare gli elementi dell'array (il quale non è inizializzato).
In oltre nel costrutto if dovresti considerare voto e non materia.
Poi c'è anche un errore logico nella progettazione, ovvero: usi la variabile giudizio per settarla a 1 quando trovi un voto >23, ma dato che chiudi il ciclo prima del controllo della variabile stessa, basta che un solo voto sia >23 e la frase l'esame %s e' andato bene",esame.materia verrà stampata, o meglio, non verrà stampata perchè dato che consideri il costrutto if-else fuori dal ciclo, la variabile i assumerà un valore non presente nell'array ed otterrai un segmentation fault.

Poi ci sono delle considerazioni che si possono fare sul programma in generale :)
Usi due cicli for, ma se ci pensi questo tipo di progettazione è molto scomoda per una serie di motivi:
1- percorri l'array più volte per inserire un egual numero di dati nelle stesse posizioni.
2- quando un utente inserisce una materia non sempre si ricorda cosa ha inserito, quindi quando concludi il primo ciclo ed inizi il secondo l'utente come fa a sapere quale voto va a quale materia ed in che ordine queste sono state inserite?
3- puoi risolvere tutto con un unico ciclo ed un unico indice.

i.e. guarda questo codice:

for(i=0;i<nesami;i++){


printf("inserisci il nome dell'esame:");
gets(esame.materia);

printf("inserisci il voto:");
scanf("%d",&esame.voto);

}
 
grazie mille! adesso ho risolto .D cmq l'indice j è un residuo di un precedente codice che poi ho modificato e ho dimenticato di "aggiustare" ;)sisi comunque adesso è tutto risolto :D spero di non avere altri problemi :)

- - - Updated - - -

adesso ho fatto tutto con un unico ciclo
 
Ciao seven,mi dispiace ma ho commesso un errore di distrazione nell'ultimo modo che ti ho descritto sulla inizializzazione di una struttura.
Ecco la correzione(I nomi ed i cognomi vanno inseriti all'interno di doppi apici,e non singoli apici):
struct utente
{
int codice;
char nome[30];
char cogome[30];

}array[3]={{128,"Giada","Bianchi"},{002,"Clarissa","Rossi"} ,{13,"Serena","Venturi"}};

Complimenti Matteo per tutte le bellissime spiegazioni che fai...
 
Ciao seven,mi dispiace ma ho commesso un errore di distrazione nell'ultimo modo che ti ho descritto sulla inizializzazione di una struttura.
Ecco la correzione(I nomi ed i cognomi vanno inseriti all'interno di doppi apici,e non singoli apici):
struct utente
{
int codice;
char nome[30];
char cogome[30];

}array[3]={{128,"Giada","Bianchi"},{002,"Clarissa","Rossi"} ,{13,"Serena","Venturi"}};

Complimenti Matteo per tutte le bellissime spiegazioni che fai...
Ty ;)
Cmq si, gli apici singoli vengono usati per i caratteri (char), anche quelli speciali; i.e. se consideriamo una stringa in C sappiamo che la stessa non è altro che un array di caratteri un po' particolare, ovvero terminato dal carattere speciale '\0'. Questa in sostanza è la differenza strutturale tra un array semplice di caratteri ed una stringa in C.
Btw il linguaggio permette anche una più comoda gestione delle stringhe appunto con i doppi apici :)
Ciao,
Matteo.
 
Pubblicità
Pubblicità
Indietro
Top