Newsgroup: it.comp.lang.c
Titolo: Puntatore a struct

Per esercitarmi con le struct (sto studiando il C) ho scritto il codice 
riportato sotto.
 
Cosa non va nel codice? Dopo aver inserito il nome, Codeblocks genera un 
errore (per la precisione, va in  crash...
 
Da un'analisi veloce, pare che il problema sia da attribuire alle  righe 
non le istruzioni scanf(....
 
Ciao
nero23
 
 
#include <stdio.h>
 
int main()
{
     struct PIPPO
     {
         char *nome;
         char *cognome;
         int peso;
     } elemento;
 
     struct PIPPO *puntatore;
     puntatore = &elemento;
 
     printf("Inserisci il nome: ");
     scanf("%s", puntatore->nome);
 
     printf("Inserisci il cognome: ");
     scanf("%s", puntatore->cognome);
 
     printf("%s\n",puntatore->nome);
     printf("%s\n",puntatore->cognome);
 
     return 0;
}
 


Che nome e cognome non sono allocati
 


 
 
Forse mi sono perso qualcosa, ma perchï¿œ devo allocare (presumo con 
malloc? ) le variabili nome e cognome?
 
Se sostituisco le istruzioni di scanf... con
 
     puntatore->nome="Mario";
     puntatore->cognome"Rossi";
 
(quindi  l'acquisizione del nome e del cognome ï¿œ giï¿œ assegnato)
tutto fila liscio...
 
ciao

Ho provato a cambiare la struct con questo codice:
 
  struct PIPPO
     {
         char nome[20];
         char cognome[20];
     } elemento;
 
e sembra funzionare....
 
Ma cosï¿œ il nome e il cognome sono limitati a 19 caratteri ed ï¿œ ciï¿œ che 
non voglio...
 


[..]
 
e insomma senza l'uguale non fila tutto liscio : )
 
-- 
Vincenzo Mercuri


 
ho risparmiato per effetto della crisi :)
ciao
 
 


Certo che funziona, qui almeno hai un po' di spazio dove salvare
i caratteri che dai a scanf(), mentre a `char *nome' puoi dare solo
un valore, che ï¿œ l'indirizzo di una locazione di memoria. Quando scrivi:
 
	puntatore->nome = "Mario"
 
con la vecchia dichiarazione della struttura, di fatto scrivi:
 
	puntatore->nome = &"Mario"[0];
 
cioï¿œ l'indirizzo del primo carattere dello string literal "Mario",
e non hai spazio per nient'altro. Siccome devi inserire dei caratteri
a programma avviato, quindi in runtime, sarebbe piï¿œ logico decidere
le dimensioni del tuo array di caratteri in runtime, quindi allocando
memoria dinamicamente. `scanf()' non ti permette di farlo. L'uso piï¿œ
sicuro delle funzioni della famiglia 'scanf()' ï¿œ se hai giï¿œ una
sorgente e conosci giï¿œ la formattazione dell'input, per esempio
se devi inserire caratteri in un array con 'sscanf()' ecc..
ma non conoscendo l'input a priori, nessuna ï¿œ davvero sicura,
forse qualcuna lo ï¿œ piï¿œ di altre, ma..
Secondo me conviene scrivere una funzione di tipo "getline()", come
quella dello Standard POSIX che rialloca dinamicamente il buffer se
l'input ï¿œ piï¿œ grande del "previsto" (buffer allocato con `malloc()'
da te: 
http://man7.org/linux/man-pages/man3/getline.3.html
 
che inoltre restituisce il numero di caratteri letti.
 
-- 
Vincenzo Mercuri

 se devi inserire caratteri in un array con 'sscanf()' ecc..
[..]
 
Intendevo "leggere caratteri da un array", non inserire.
 
-- 
Vincenzo Mercuri


 
e allora fai qualcosa del genere; NON HO controllato il 
codice e sicuramente è cannato, ma l'idea è quella di 
avere un buffer di ampiezza sufficiente, leggere la 
lunghezza della stringa e poi ricopiare dopo allocazione 
dinamica. 1) Dovrai prenderti carico di disallocare quando 
la memoria non ti serve più e comunque prima di terminare 
2) Sicuramente il codice sotto è goffo 3) Ci saranno 
sicuramente modi migliori.
 
 
 
int  main ()
{
      struct PIPPO
      {
          char *nome;
          char *cognome;
          int peso;
      } elemento;
 
     char   buf[129] ;
     int      len  ;
     struct PIPPO  *ptr ;
 
     ptr = &elemento ;
 
     printf("cognome?\n") ;
     scanf("%s",buf) ;
     /* leggi la lunghezza */
     len = strlen (buf) ;
    /* +1 per il carattere di terminazione */
     (ptr->cognome) = malloc (len+1) ;
    /* ora copi */
    strcpy((ptr->cognome),buf) ;
 
    /* prima di uscire */
     free (ptr->cognome) ;
}
 


 
Il punto non ï¿œ solo che il programma ï¿œ "cannato", ma non risolve..
qui usi comunque scanf(), ed ï¿œ quello il problema :)
 
-- 
Vincenzo Mercuri


 
ops, vero!
 


 
Di quanto li vorresti ?
 
 
 

Su un corso di programmazione online (c++) ho visto questo codice:
 
 
#include <stdio.h>
struct Card
{
     char  *nome;
     char  *cognome;
};
int main(void)
{
 
     struct Card  ppp;
 
     ppp.nome = "Vincenzo";
     ppp.cognome = "Biello";
 
}
 
 
 
In questo esempio, la funzione di scanf non serve perchï¿œ il nome e il 
cognome viene inserito direttamente da codice. Se ho capito bene quanto 
scritto da voi, il problema di allocazione non rimane anche in questo 
esempio?
 

 anche in questo esempio?
 
Il problema non c'è perché la lunghezza delle stringhe è
nota e costante, e il compilatore può riservare la memoria
necessaria.