I need to delete the last struct written in the file file.dat and flag it with the word deleted
.
This is the code:
#include <stdio.h>
#include <string.h>
struct s_cliente {
int codice;
char nome[10];
char merce[10];
float prezzo;
};
typedef struct s_cliente cliente;
cliente inserisciCliente(cliente c1);
void inserisciOrdine();
void stampaFile();
float calcolaPrezzo(char nome[10]);
void eliminaLast();
int main() {
char nome[10];
float prezzotot = 0;
int opz = 0;
do {
printf("\nInserisci un'opzione: \n1)Inserisci un cliente\n2)Stampa i clienti all'interno del file\n3)Ricerca un cliente e calcola l'importo dovuto\n");
scanf("%d", &opz);
switch (opz) {
case 1:
inserisciOrdine();
break;
case 2:
stampaFile();
break;
case 3:
getchar();
scanf("%s", nome);
prezzotot = calcolaPrezzo(nome);
if (prezzotot != 0) {
printf("\nImporto dovuto dal cliente %s: %2.f euro", nome, prezzotot);
} else {
printf("\nCliente non trovato");
}
break;
default:
printf("\nOpzione non valida");
break;
}
} while (opz != 5);
return 0;
}
cliente inserisciCliente(cliente c1) {
printf("\nInserisci il codice: ");
scanf("%d", &c1.codice);
getchar();
printf("Inserisci il nome: ");
scanf("%s", c1.nome);
getchar();
printf("Inserisci la merce: ");
scanf("%s", c1.merce);
printf("Inserisci prezzo: ");
scanf("%f", &c1.prezzo);
return c1;
}
void inserisciOrdine() {
FILE *foutput = fopen("file.dat", "ab");
cliente c1;
c1 = inserisciCliente(c1);
fwrite(&c1, sizeof(c1), 1, foutput);
fclose(foutput);
}
void stampaFile() {
FILE *file_lettura = fopen("file.dat", "rb");
if (file_lettura != NULL) {
cliente c1;
while (fread(&c1, sizeof(cliente), 1, file_lettura) == 1) {
printf("Codice: %d, Nome: %s, Merce: %s, Prezzo: %.2f\n", c1.codice, c1.nome, c1.merce, c1.prezzo);
}
fclose(file_lettura);
} else {
printf("Errore nell'apertura del file per la lettura.\n");
}
}
float calcolaPrezzo(char nome[10]) {
float prezzotot = 0;
FILE *file_lettura = fopen("file.dat", "rb");
cliente c1;
if (file_lettura != NULL) {
while (fread(&c1, sizeof(cliente), 1, file_lettura) == 1) {
if (strcmp(nome, c1.nome) == 0) {
prezzotot += c1.prezzo;
}
}
fclose(file_lettura);
} else {
printf("\nErrore nella lettura");
}
return prezzotot;
}
I know that I can use the function fseek();
, I just don't really understand how to flag the struct as deleted.
Google translate tells me int codice;
means "code" in English so you can possible use that field to encode your flag. For example using -1 for delete? This means your question is wrong as you indicated that you wanted use the word "delete". If you go this route then you have to audit your code and handle this flag. You probably don't want to print deleted records, and if you want to delete subsequent records then you want to skip ones already deleted. Do you want to retain or overwrite deleted records when you subsequently add a new record?
I suggest you delete the record by truncating the file instead and with these other issues:
struct
name as you don't use it.scanf()
to avoid buffer overflow.fopen()
. You missed it one place so combined it one place and pass file handle to the functions that need it.c1
to inserisciCliente()
and returning it by copy. Just use a local variable.switch
to it's own function.scanf()
otherwise you may be operating on uninitialized variables. See for example how I handled the opz
variable which I also moved to reduce it's scope.#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define LEN 9
#define DAT "file.dat"
#define str(s) str2(s)
#define str2(s) #s
typedef struct {
int codice;
char nome[LEN+1];
char merce[LEN+1];
float prezzo;
} cliente;
cliente inserisciCliente() {
cliente c1;
printf("Inserisci il codice: ");
scanf("%d", &c1.codice);
getchar();
printf("Inserisci il nome: ");
scanf("%" str(LEN) "s", c1.nome);
getchar();
printf("Inserisci la merce: ");
scanf("%" str(LEN) "s", c1.merce);
printf("Inserisci prezzo: ");
scanf("%f", &c1.prezzo);
return c1;
}
void inserisciOrdine(FILE *lettura) {
fseek(lettura, 0, SEEK_END);
cliente c1 = inserisciCliente();
fwrite(&c1, sizeof(c1), 1, lettura);
}
void stampaFile(FILE *lettura) {
fseek(lettura, 0, SEEK_SET);
cliente c1;
while (fread(&c1, sizeof(cliente), 1, lettura) == 1) {
printf("Codice: %d, Nome: %s, Merce: %s, Prezzo: %.2f\n", c1.codice, c1.nome, c1.merce, c1.prezzo);
}
}
float calcolaPrezzo(FILE *lettura, char nome[10]) {
fseek(lettura, 0, SEEK_SET);
float prezzotot = 0;
cliente c1;
while (fread(&c1, sizeof(cliente), 1, lettura) == 1) {
if (strcmp(nome, c1.nome) == 0) {
prezzotot += c1.prezzo;
}
}
return prezzotot;
}
void delete(FILE **lettura) {
if(fseek(*lettura, 0, SEEK_END)) {
perror("");
return;
}
long end = ftell(*lettura);
if(!end) return; // empty
if(ftruncate(fileno(*lettura), end - sizeof(cliente))) {
perror("");
return;
}
*lettura = freopen(NULL, "a+r", *lettura);
if(!*lettura) {
perror("");
return;
}
}
int main() {
FILE *lettura = fopen(DAT, "a+b");
if(!lettura) {
perror("Errore nell'apertura del file per la lettura.\n");
return 1;
}
printf(
"Inserisci un'opzione:\n"
"1)Inserisci un cliente\n"
"2)Stampa i clienti all'interno del file\n"
"3)Ricerca un cliente e calcola l'importo dovuto\n"
"4)Delete\n"
"5)Exit\n"
);
for(;;) {
printf("> ");
enum { INSERT=1, SHOW, CALC, DELETE, EXIT=5 } opz;
int rv = scanf("%d", &opz);
if(rv == EOF)
break;
if(rv != 1)
continue;
switch (opz) {
case INSERT:
inserisciOrdine(lettura);
break;
case SHOW:
stampaFile(lettura);
break;
case CALC: {
char nome[LEN+1];
float prezzotot = 0;
getchar();
scanf("%" str(LEN) "s", nome);
prezzotot = calcolaPrezzo(lettura, nome);
if (prezzotot)
printf("\nCliente non trovato");
else
printf("\nImporto dovuto dal cliente %s: %2.f euro", nome, prezzotot);
break;
}
case DELETE:
delete(&lettura);
break;
case EXIT:
goto done;
default:
printf("\nOpzione non valida");
break;
}
}
done:
fclose(lettura);
return 0;
}
Inserisci un'opzione:
1)Inserisci un cliente
2)Stampa i clienti all'interno del file
3)Ricerca un cliente e calcola l'importo dovuto
4)Delete
5)Exit
> 1
Inserisci il codice: 1
Inserisci il nome: 2
Inserisci la merce: 3
Inserisci prezzo: 4
> 1
Inserisci il codice: 2
Inserisci il nome: 3
Inserisci la merce: 4
Inserisci prezzo: 5
> 2
Codice: 1, Nome: 2, Merce: 3, Prezzo: 4.00
Codice: 2, Nome: 3, Merce: 4, Prezzo: 5.00
> 4
> 2
Codice: 1, Nome: 2, Merce: 3, Prezzo: 4.00
> 5