Ciao, per tua utilità ti dico che non sono un programmatore ma uno a cui piace scrivere tre righe di codice per puro diletto
intanto se dovrai aumentare di volta in volta la dimensione di un puntatore, non userai la malloc, ma la realloc.
secondo punto, il tuo scopo è risparmiare memoria anche sui campi nome della struct, di conseguenza dovranno essere puntatori allocati dinamicamente.
come accennato in precedenza, non sono un professionista che vorrebbe farti fare un percorso per cui tu arriveresti da solo alla soluzione, io ho sempre imparato da esempi di codice e quindi ti offro un esempio non completo, in modo che tu possa lavorarci sopra.
codice:
struct tipo_dato
{
float f;
char *nome1; //nome1 e nome2 sono puntatori, per poterli utilizzare occorre
// allocare memoria necessaria
char *nome2;
};
struct tipo_dato *dati=NULL; //importante che il puntatore sia inizializzato a NULL
// perché la relloc() in presenza di un puntatore NULL
// si comporta come la malloc()
........
.......
......
.......
while(!feof(f))
{
if(feof(f))break;
i++;
/* occorra dichiarare nel programma la variabile contatore i
che conta le righe lette e quindi il numero di record necessari
e gli array di char stringa1 e stringa2, di dimensioni adeguare
come contenitori temporanei */
//alloca spazio per un record "i = numero record" a puntantore nullo si comporta come malloc
dati=(struct tipo_dato*)realloc(dati,sizeof(struct tipo_dato)*i);
if(dati==NULL)printf("errore");
fscanf(f, "%f %s %s", &dati[i-1].f, stringa1, stringa2); // acquisisce i dati da file
printf("%f %s %s\n", dati[i-1].f, stringa1, stringa2);
/*
prima di utilizzare i campi nome, occorre allocare memoria sufficiente
lunghezza stringa +1, carattere terminatore */
dati[i-1].nome1=(char*)malloc(sizeof(char)*(strlen(stringa1)+1));
dati[i-1].nome2=(char*)malloc(sizeof(char)*(strlen(stringa2)+1));
//copio i dati nei puntatori allocati ...
strcpy(dati[i-1].nome1,stringa1);
strcpy(dati[i-1].nome2,stringa2);
}