Come cancellare un record da un file

di il
12 risposte

Come cancellare un record da un file

Salve a tutti. Sto cercando di scrivere una funzione in grado di cancellare un record da un file di tipo .dat SENZA dover riscrivere tutto su un nuovo file. Pensavo di cavarmela con la quarantina di righe qui sotto. Semplicemente, faccio inserire all'utente l'id del record da cancellare, lo confronto con gli id presenti nel file tramite la funzione fread+if, uso strcpy per svuotare tutti gli elementi del record e poi scrivo sul file con fwrite. Le dichiarazioni di struttura, puntatori ecc si trovano in un file header. Ecco quindi il codice:

void deleteUser(FILE *scrittura){

scrittura = fopen ("dati_utente.dat", "r+");
if (scrittura == NULL){

fprintf(stderr, "\nError opening file\n");
exit (1);
}else{
puts("Inserire ID dell'account da cancellare.");
int idDelete;
scanf("%d", &idDelete);

while(fread(&user, sizeof(struct generalUser), 1, scrittura)){
if(idDelete==user.id){
strcpy(user.fName, "Utente_eliminato");
strcpy(user.lName, "");
user.id=0;
strcpy(user.password, "");
user.bDay=0;
user.bMonth=0;
user.bYear=0;
strcpy(user.site.type, "");
strcpy(user.site.wName, "");
strcpy(user.site.city, "");
strcpy(user.site.district, "");
strcpy(user.role, "");
strcpy(user.specialization, "");
fwrite (&user, sizeof(struct generalUser), 1, scrittura);
puts("Eliminazione completata.");
}
}
}
if(fwrite != 0){
puts("\nDati salvati con successo!");
}else{
printf("\nErrore durante il salvataggio dei dati!");
}
fclose(scrittura);
}


Il codice in questione compila e sembra funzionare ma, nel momento in cui vado a controllare il file oppure scrivo una funzione per stampare tutti i record, il record che volevo cancellare è ancora lì e nulla sembra essere cambiato. Dove ho sbagliato?

12 Risposte

  • Re: Come cancellare un record da un file

    Che intendi con cancellare? Intendi solamente riempire con spazi o eliminare fisicamente dal file?
  • Re: Come cancellare un record da un file

    @oregon beh, in questo caso ho provato a riempire il record di spazi vuoti tranne per il nome che avrebbe riportato il valore "utente_eliminato". Ma come ho detto, non funziona. Comunque, mi andrebbe bene anche eliminarlo fisicamente.
  • Re: Come cancellare un record da un file

    Non mi pare che tu stia aprendo il file in modalità binaria. È una dimenticanza oppure hai proprio sbagliato la fopen?
  • Re: Come cancellare un record da un file

    Avevo aperto in modalità rb+ ma mi dava lo stesso identico risultato, cioè niente
  • Re: Come cancellare un record da un file

    Intanto deve essere sicuramente aperto in rb+

    E poi perché usi un argomento FILE * passato dall'esterno se l'apertura la fai all'interno? In questo caso dovresti scrivere
    
    void deleteUser()
    {
        FILE* scrittura= fopen("c:\\dati.bin", "rb+");
    
    anche se non è (solo) questo il problema (ad esempio quel if (fwrite != 0) non ha senso)

    Fornisci anche la struttura

    struct generalUser

    così faciliti la ricerca del problema.
  • Re: Come cancellare un record da un file

    Certo. Questa è la struttura generalUser:

    struct generalUser{
    char fName[20];
    char lName[20];
    int id;
    char password[50];
    int bDay;
    int bMonth;
    int bYear;
    struct workplace site;
    char role[20];
    char specialization[40];
    };

    Questa è la sottostruttura workplace:

    struct workplace{//struttura per specificare la sede lavorativa di ogni utente autorizzato registrato
    char type[16];
    char wName[30];
    char city[30];
    char district[30];
    };
  • Re: Come cancellare un record da un file

    Se lasci la fopen nella funzione allora questa deve essere corretta così
    
    void deleteUser()
    {
        FILE *scrittura = fopen("dati_utente.dat", "rb+");
        if (scrittura == NULL) {
    
            fprintf(stderr, "\nError opening file\n");
            exit(1);
        }
        else {
            puts("Inserire ID dell'account da cancellare.");
            int idDelete;
            scanf("%d", &idDelete);
    
            int fnd = 0;
            int elsw, chsz = sizeof(struct generalUser);
            while (fread(&user, chsz, 1, scrittura))
            {
                if (idDelete == user.id)
                {
                    memset(&user, 0, sizeof(user));
                    strcpy(user.fName, "Utente_eliminato");
                    fseek(scrittura, -chsz, SEEK_CUR);
                    elsw = fwrite(&user, chsz, 1, scrittura);
                    fnd = 1;
                    break;
                }
            }
    
            if (!fnd)
                puts("Id non trovato\n");
            else
            {
                if (1 == elsw)
                    puts("Utente eliminato\n");
                else
                    puts("ERRORE durante la scrittura\n");
            }
        }
    
        fclose(scrittura);
    }
    
    Considera che il file deve essere aperto in binario rb+ ed è necessaria la chiamata alla fseek quando si passa dalla fread alla fwrite (ricorda che la fread sposta il puntatore al prossimo record e quindi, prima della fwrite, devi tornare indietro al record precedente).

    Per provare, ti consiglio prima di cancellare il file .dat e ricrearlo in modo da essere certo di cosa contenga.
  • Re: Come cancellare un record da un file

    @Oregon ti ringrazio moltissimo, il codice funziona benissimo. Mannaggia, ne ho di strada da fare :facepalm:
    Non è che potresti perdere un paio di minuti per spiegarmi la tua soluzione? In ogni caso, ti ringrazio di nuovo!
  • Re: Come cancellare un record da un file

    Cosa non capisci?
  • Re: Come cancellare un record da un file

    Praticamente da memset fino a break
  • Re: Come cancellare un record da un file

    Memset: riempie il record puntato da &user con il valore 0 in tutti i byte (vedi documentazione della memset)
    strcpy: copia nel campo fName la stringa "Utente_cancellato"
    fseek: sposta il puntatore del file al record precedente (vedi documentazione della fseek)
    fwrite: scrive nel file il record appena modificato e restituisce in elsw 0 se c'è stato un errore, 1 se è andata bene (vedi documentazione della fwrite)
    fnd: imposta la variabile fnd a 1 per indicare che l'id ricercato è stato trovato
    break: termina la ricerca ed esce dal ciclo
  • Re: Come cancellare un record da un file

    Capisco, ti ringrazio ancora!
Devi accedere o registrarti per scrivere nel forum
12 risposte