Pages: [1]   Go Down
Print
Author Topic: Struct : problemi  (Read 817 times)
0 Members e 1 Utente non registrato stanno visualizzando questa discussione.
milos224
Forumista
***
Offline Offline

Posts: 830


« on: 12-11-2012, 23:24:00 »

Non sto riuscendo a capire bene le struct. Allora:
Code:
// dichiarazione della struct
struct libro
{
  char titolo[100];
  char autore[50];
  int anno_pubblicazione;
  float prezzo;
};

struct libro biblio = {"Guida al C", "Fabrizio Ciacchi", 2003, 45.2};

e ho i miei valori. Ma se voglio modificare per esempio solo il titolo?
Code:
biblio.titolo="Guida Java";

perchè mi da errore?
Inoltre
Code:
struct libro
{
  char titolo[100];
  char autore[50];
  int anno_pubblicazione;
  float prezzo;
}biblio;

in questo modo ho già il mio "biblio". Ma per inizializzare i valori?

Non si fa
Code:
biblio={"Guida al C", "Fabrizio Ciacchi", 2003, 45.2};
Logged
ɹǝǝuıƃuǝsɹǝʌǝɹ
Administrator
God of the Forum
*****
Offline Offline

Gender: Male
Posts: 4.474


Più grande è la lotta, e più è glorioso il trionfo


WWW
« Reply #1 on: 13-11-2012, 00:53:47 »

Prima di tutto bisogna dire che le struct sono delle aggregazioni di dati.
Quando usate come "variabili" (nel senso che si vuole rappresentare una variabile composta da sotto-parti variabili), è sufficiente scrivere qualcosa come:
Code:
struct
{
    tipo1 campo1;
    tipo2 campo2;
    // ... ecc...
    tipoN campoN;
} miaVariabile;
quindi il nome (identificativo) che segue immediatamente la parola chiave C "struct" è facoltativo.

Ora, scrivendo il nome identificativo dopo struct si ha la possibilità di riciclare la struttura (scheletro) avendole dato un nome, ma pur dovendo scrivere sempre "struct" davanti al nome della struttura, ogni qual volta si vuole usare tale struttura, poiché il nome identificativo non è stato automaticamente promosso a un "tipo", ma è semplicemente un nome interno di C per ricordarsi la struttura precedentemente definita.
Difatti, creando una funzione in cui uno dei parametri è di tipo "struct nomeidentificativo", come in:
Code:
void miaFunzione (struct nome x) {
    //fai qualcosa con x...
}
si fa in modo che, una volta invocato, la funzione chiamata "miaFunzione" riceverà in input una copia di x (cioè una nuova variabile che avrà i campi con gli stessi dati di x) il cui scope (ambito di visibilità) terminerà una volta giunti alla fine della funzione miaFunzione o se si giunge a un return.

Si può promuovere a "tipo" una scrittura come le precedenti (senza l'identificativo) usando l'istruzione interna C typedef, come segue:
Code:
typedef struct {
    tipo1 nome1;
    tipo2 nome2;
    //... ecc...
    tipoN nomeN;
} mioNuovoTipo;
Adesso, ogni qual volta si vorrà indicare l'intero tipo "struct {blablabla}" si potrà optare per la semplice scrittura "mioNuovoTipo", come in:
Code:
mioNuovoTipo varStrutturata1;
mioNuovoTipo varStrutturataNesima;

Non sto riuscendo a capire bene le struct. Allora:

e ho i miei valori. Ma se voglio modificare per esempio solo il titolo?
Code:
biblio.titolo="Guida Java";

perchè mi da errore?
Lo capisci meglio se consideri che "biblio.titolo" indica a tutti gli effetti un array.
Come tutti gli array, scrivere il solo nome dell'array, quando usato come R-value viene valutato nell'indirizzo al primo elemento (cioè è un puntatore al tipo corrispondente e relativamente al primo elemento), ma non si può usare come L-value, cioè valore assegnabile. Staresti "riassegnando" l'indirizzo del primo elemento infatti, in tal caso! Questa operazione non è lecita in C.

Diversamente dalle struct (che hanno una dimensione precisa), gli array sono semplicemente puntatori a dati di un certo tipo (al primo di una sequenza, se vogliamo, anche unitaria per quanto ne può sapere il compilatore a compile-time...), e quindi quello che con le struct è ovviamente possibile, cioè assegnare una struct con un'altra (sapendo che sarà fatta la copia di tutti i campi della R-value sovrascrivendo quelli della L-value), con gli array diventa impossibile in modo manuale.
Quando non si sa quanta memoria bisogna sovrascrivere non si può finire tutto con un semplice assegnamento fra variabili (giacché C non sa assolutamente quanto spazio occupi un array in un dato momento, non è una informazione conservata fra le sue strutture interne, diciamo, per una scelta implementativa di evitare overhead, scelta da me condivisa vista la potenza che permette) e bisogna usare le funzioni di libreria (giusto perché sono ottimizzate) oppure fare un ciclo manuale che iteri un indice che scorre per tutta la memoria necessaria, per copiare la memoria.

Inoltre
Code:
struct libro
{
  char titolo[100];
  char autore[50];
  int anno_pubblicazione;
  float prezzo;
}biblio;

in questo modo ho già il mio "biblio". Ma per inizializzare i valori?

Non si fa
Code:
biblio={"Guida al C", "Fabrizio Ciacchi", 2003, 45.2};
No.

Puoi copiare i valori inizializzati di un'altra struct identica, però:
Code:
struct miaStruttura copiaConNuoviValori = {valore1, valore2, ..., valoreN};
strutturaOriginale = copiaConNuoviValori;
.

Nel caso di stringhe, puoi fare affidamento a funzioni che copiano i valori presenti nella memoria occupata dalle stringhe come strncpy (non usare MAI strcpy, mai! Motivi di sicurezza! Oppure usala ma solo se sei assolutamente certo di quello che fai!) .
Logged

La grande marcia della distruzione mentale proseguirà. Tutto verrà negato. Tutto diventerà un credo. È un atteggiamento ragionevole negare l'esistenza delle pietre sulla strada; sarà un dogma religioso affermarla. È una tesi razionale pensare di vivere tutti in un sogno; sarà un esempio di saggezza mistica affermare che siamo tutti svegli. Accenderemo fuochi per testimoniare che due più due fa quattro. Sguaineremo spade per dimostrare che le foglie sono verdi in estate. Non ci resterà quindi che difendere non solo le incredibili virtù e saggezze della vita umana, ma qualcosa di ancora più incredibile: questo immenso, impossibile universo che ci guarda dritto negli occhi. Combatteremo per i prodigi visibili come se fossero invisibili. Guarderemo l'erba e i cieli impossibili con uno strano coraggio. Saremo tra coloro che hanno visto eppure hanno creduto.

In tutto, amare e servire.

  
                            ن                           
I can deal with ads,
I can deal with buffer,
but when ads buffer
I suffer...

...nutrimi, o Signore, "con il pane delle lacrime; dammi, nelle lacrime, copiosa bevanda...

   YouTube 9GAG    anobii  S  Steam T.B.o.I. Wiki [univ] Lezioni private  ʼ  Albo d'Ateneo Unicode 3.0.1
Usa "Search" prima di aprire un post - Scrivi sempre nella sezione giusta - Non spammare - Rispetta gli altri utenti - E ricorda di seguire il Regolamento
milos224
Forumista
***
Offline Offline

Posts: 830


« Reply #2 on: 13-11-2012, 10:02:25 »

Prima di tutto bisogna dire che le struct sono delle aggregazioni di dati.
Quando usate come "variabili" (nel senso che si vuole rappresentare una variabile composta da sotto-parti variabili), è sufficiente scrivere qualcosa come:
Code:
struct
{
    tipo1 campo1;
    tipo2 campo2;
    // ... ecc...
    tipoN campoN;
} miaVariabile;
quindi il nome (identificativo) che segue immediatamente la parola chiave C "struct" è facoltativo.

Ora, scrivendo il nome identificativo dopo struct si ha la possibilità di riciclare la struttura (scheletro) avendole dato un nome, ma pur dovendo scrivere sempre "struct" davanti al nome della struttura, ogni qual volta si vuole usare tale struttura, poiché il nome identificativo non è stato automaticamente promosso a un "tipo", ma è semplicemente un nome interno di C per ricordarsi la struttura precedentemente definita.
Difatti, creando una funzione in cui uno dei parametri è di tipo "struct nomeidentificativo", come in:
Code:
void miaFunzione (struct nome x) {
    //fai qualcosa con x...
}
si fa in modo che, una volta invocato, la funzione chiamata "miaFunzione" riceverà in input una copia di x (cioè una nuova variabile che avrà i campi con gli stessi dati di x) il cui scope (ambito di visibilità) terminerà una volta giunti alla fine della funzione miaFunzione o se si giunge a un return.
Non ho capito bene la parte in grassetto, per il resto molto chiaro.
Logged
Pages: [1]   Go Up
Print
Jump to: