Newsgroup: it.comp.lang.c++
Titolo: File Dati 2 - Il ritorno!

Salve, sono di nuovo io. Rileggendo il mio messaggio, mi sono accorto di non
essermi spiegato in maniera molto chiara. Dunque, devo scrivere un programma
che simuli un agenda telefonica tascabile, e questo, + o - l'ho fatto....
Mi sono reso conto però che, per renderla + realistica dovrei utilizzare dei
file dati. Cosa che inizialmente poteva anche sembrarmi semplice ma che allo
stato attuale, dopo innumerevoli e vani tentativi, mi risulta impossibile.
Il problema riguarda soprattutto le funzioni di ricerca: come fare per far
si che il programma "esplori" sequenzialmente il file e trovi le
informazioni cercate? Mi sorge un dubbio: dovrei forse modificare
l'impostazione generale del programma? O in qualche modo è possibile usare
dei file dati in maniera efficente anche allo stato attuale del programma?
Questo è quello che sono riuscito a fare:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#include <stdlib.h>
#define MAXELE 200
#define MENU 0
#define INS 1
#define CAN 2
#define RIC 3
#define MOD 4
#define OUT 100
#define DIM 31
/* semplice struttura che modella una persona */
struct per {
   char cognome[DIM];
   char nome[DIM];
   char ind[DIM];
   int long tel[DIM];
   };
   /* numero di elementi allocati nel vettore anag */
   int index;
   /* array di persone */
   struct per agen[MAXELE];
   int men_per(void);
   int ins_per(int);
   void can_per(void);
   void ric_per(void);
   void mod_per(void);
   void cam_per(struct per *p);
   void main()
   {
       int scelta = MENU;
   /* presentazione del menu e lancio della corrispondente funzione */
   while(scelta != OUT) {
       switch (scelta) {
       case MENU:
          scelta = men_per();
          if(scelta == MENU)
             scelta = OUT;
             break;
       case INS:
          index = ins_per(index);
          scelta = MENU;
          break;
       case CAN:
          can_per();
          scelta = MENU;
          break;
       case RIC:
          ric_per();
          scelta = MENU;
          break;
       case MOD:
          mod_per();
          scelta = MENU;
          break;
       }
   }
   }
   /* visualizza il menu di scelta e controlla la scelta effettuata */
   int men_per(void)
   {
      int scelta;
      char invio;
      int True = 1;
      while(True) {
      clrscr();
      printf("\n\n\n\n\n");
      printf("\t\t\t AGENDA TELEFONICA");
      printf("\n\n\n\t\t\t 1. Immissione Persona");
      printf("\n\n\t\t\t 2. Cancellazione Persona");
      printf("\n\n\t\t\t 3. Ricerca Persona");
      printf("\n\n\t\t\t 4. Modifica dati");
      printf("\n\n\t\t\t 0. Fine");
      printf("\n\n\n\t\t\t Scegliere un opzione: ");
      scanf("%d", &scelta);
      scanf("%c", &invio);
      printf("\n\n\n\n\n");
      switch(scelta) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
          return(scelta);
        default:
         break;
      }
      }
      fflush(stdin);
      return(0);
    }
    /* effettua l'inserimento di una persona nell'agenda */
    int ins_per(int pos)
    {
        char invio;
        FILE *fptold;
        /* apre un file in modalità scrittura alla fine */
        fptold = fopen("c:\\Dati\\Dati.bin", "a");
        if(pos >= MAXELE) {
        printf(" Non si possono inserire altri nomi");
        scanf("%c", &invio);
        return(pos);
        }
        printf("\n\t\tINSERIMENTO PERSONA");
        printf("\n\t\t-------------------\n\n");
        printf("\nCognome : ");
        gets(agen[pos].cognome);
        printf("\nNome : ");
        gets(agen[pos].nome);
        printf("\nIndirizzo : ");
        gets(agen[pos].ind);
        printf("\nTelefono : ");
        scanf(" %[0123456789/]", agen[pos].tel);
        fwrite(&agen[pos], sizeof(per), 1, fptold);
        scanf("%c", &invio);
        /*chiude il file */
        fclose(fptold);
        pos++;
        return(pos);
    }
    /* effettua una scansione sequenziale dell'array agen alla ricerca di
una
       persona che abbia un determinato nome e cognome */
    struct per *cer_per(char *cg, char *nm)
    {
        int i;
        for (i = 0; i <= index; i++) {
            if(strcmp(cg, agen[i].cognome) == 0)
            if(strcmp(nm, agen[i].nome) == 0)
                return(&agen[i]);
        }
        return(NULL);
    }
    /* effettua una scansione sequenziale dell'array agen alla ricerca di
una
       persona che abbia un determinato cognome */
    struct per *cer_per1(char *cg)
    {
       int i;
       for (i = 0; i <= index; i++) {
            if(strcmp(cg, agen[i].cognome) == 0)
            return(&agen[i]);
       }
       return(NULL);
    }
    /* effettua una scansione sequenziale dell'array agen alla ricerca di
una
       persona che abbia un determinato nome */
    struct per *cer_per2(char *nm)
    {
       int i;
       for (i = 0; i <= index; i++) {
            if(strcmp(nm, agen[i].nome) == 0)
            return(&agen[i]);
       }
       return(NULL);
    }
    /* effettua una scansione sequenziale dell'array agen alla ricerca della
       persona che occupa la posizione data */
    struct per *cer_per3(int ps, int pos)
    {
        if (ps > (pos - 1))  {
          printf("\nLa posizione indicata non esiste!");
          return(NULL);
        }
          else
          return(&agen[ps]);
    }
    /* visualizza i dati di una persona */
    void vis_per(struct per *p)
    {
        char pausa;
        printf("\n\n---------------\n");
        printf("\n\t\tCognome : %s", p -> cognome);
        printf("\n\t\tNome : %s", p -> nome);
        printf("\n\t\tIndirizzo : %s", p -> ind);
        printf("\n\t\tTelefono : %s", p -> tel);
        printf("\n\n---------------\n");
        scanf("%c", &pausa);
    }
    /* effettua la ricerca di una persona, se presente nell' elenco */
    void ric_per(void)
    {
        char pausa;
        char cognome[DIM], nome[DIM];
        struct per *ps;
        int scelta1, pos;
        /* scelta del tipo di ricerca ed inserimento dati persona da
ricercare */
        printf("\n\t\tRICERCA PERSONA");
        printf("\n\t\t---------------\n\n");
        printf("\n1. per cognome");
        printf("\n2. per nome");
        printf("\n3. per posizione");
        printf("\n\nScegliere un opzione: ");
        scanf(" %d", &scelta1);
        switch(scelta1)  {
           case 1:
               printf("\nCognome : ");
               scanf(" %s", cognome);
               ps = cer_per1(cognome);
               break;
           case 2:
               printf("\nNome : ");
               scanf(" %s", nome);
               ps = cer_per2(nome);
               break;
           case 3:
               printf("\nPosizione : ");
               scanf(" %d", &pos);
               ps = cer_per3(pos, index);
               break;
           default:
               fflush(stdin);
               printf("\nErrore - Opzione non disponibile!");
               scanf("%c", &pausa);
               return;
        }
        scanf("%c", &pausa);
        if(ps == NULL) {
        printf("\n\nPersona non presente nell'elenco");
        scanf("%c", &pausa);
        return;
        }
        vis_per(ps);
    }
    /* elimina i dati di una persona dall'elenco */
    void eli_per(struct per *p)
    {
       strcpy(p -> cognome, "");
       strcpy(p -> nome, "");
       strcpy(p -> ind, "");
       *(p -> tel) = 0;
    }
    /* cancella una persona dall'anagrafico, se presente */
    void can_per(void)
    {
        char pausa;
        char cognome[DIM], nome[DIM];
        struct per *ps;
        printf("\n\t\tCANCELLA PERSONA");
        printf("\n\t\t----------------\n\n");
        printf("\nCognome : ");
        gets(cognome);
        printf("\nNome : ");
        gets(nome);
        scanf("%c", &pausa);
        ps = cer_per(cognome, nome);
        if (ps == NULL) {
           printf("\nPersona non presente nell'elenco");
           scanf("%c", &pausa);
           return;
           }
           vis_per(ps);
           printf("\nConfermi cancellazione? (S/N)");
           scanf("%c", &pausa);
           if (pausa == 'S' || pausa == 's') {
               eli_per(ps);
               return;
               }
        }
    /* modifica i dati di una persona, se presente */
    void mod_per(void)
    {
        char pausa;
        char cognome[DIM], nome[DIM];
        struct per *ps;
        printf("\n\t\tMODIFICA DATI ");
        printf("\n\t\t------------- ");
        printf("\nCognome: ");
        gets(cognome);
        printf("\nNome: ");
        gets(nome);
        ps = cer_per(cognome, nome);
        if(ps == NULL)  {
           printf("\nPersona non presente nell'elenco");
           scanf("%c", &pausa);
           return;
        }
        vis_per(ps);
        printf("\nSei sicuro di voler modificare i dati? (S/N)");
        scanf("%c", &pausa);
        if (pausa == 's' || pausa == 'S') {
           cam_per(ps);
           return;
           }
    }
    void cam_per(struct per *p)
    {
       FILE *fptold, *fptnew;
       fptold = fopen("c:\\Dati\\Dati.bin", "a");
       fptnew = fopen("c:\\Dati\\N_Dati.bin", "a");
       fread(p, sizeof(per), 1, fptold);
       printf("\nDigitare nuovo cognome: ");
       scanf("%s", p -> cognome);
       printf("\nDigitare nuovo nome: ");
       scanf("%s", p -> nome);
       printf("\nDigitare nuovo indirizzo: ");
       scanf(" %[^\n]", p -> ind);
       *(p -> tel) = 0;
       printf("\nDigitare nuovo numero di telefono: ");
       scanf("%ld", p -> tel);
       fwrite(p, sizeof(per), 1, fptnew);
       fclose(fptold);
       fflush(stdin);
       getchar();
       return;
    }
Ringrazio sin d'ora chiunque sappia darmi una mano.
Roberto

Questo è quello che sono riuscito a fare:
Ci sono due possibilita': o il tuo programma carica tutti i dati
all'inizio, lavora in memoria e poi salva tutti i dati al momento
dell'uscita oppure ogni singola operazione deve essere fatta
sul file.
La prima soluzione e' sicuramente la piu' semplice da implementare
mentre la seconda lascia aperta la strada ad implementazioni
piu' sofisticate (es. archivi piu' grossi della memoria disponibile,
accesso contemporaneo da parte di piu' utenti allo stesso archivio).
Un sistema semplice e' il seguente: ogni persona e' mantenuta in
una struttura
   struct per
   {
     char cognome[DIM];
     char nome[DIM];
     char ind[DIM];
     long tel; // Perche' tu hai usato "int long tel[DIM]" ?
   };
ma queste strutture sono tenute su FILE e non in memoria.
Consideriamo ad esempio la ricerca per cognome:
   //
   // Funzione di ricerca; ritorna 1 se la persona
   // e' stata trovata (e compila i campi della struttura).
   // Ritorna 0 altrimenti.
   //
   int Ricerca(char *cg, per *persona)
   {
     fseek(f,0,SEEK_SET); // Ritorna a inizio file
     for(;;)
     {
       // Prova a leggere il prossimo record da file
       if (fread(persona,sizeof(per),1,f)!=1)
       {
         // Errore di lettura; loop di ricerca terminato
         break;
       }
       if (strcmp(persona->cognome,cg)==0)
       {
         // Persona trovata!
         return 1;
       }
     }
     return 0; // la persona non e' stata trovata
   }
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

      char ind[DIM];
