Problem deleting all data from a functionary

Viewed 81

After I am having problems with the creation of a CRUD system using C. Currently I managed to creating and updating, but I'm not being successful deleting one.

Objective: given an ID by the user, delete all the data of the struct containing that ID.

This is what I managed to do so far:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FILENAME "funcionarios.txt"
#define BUFFER_SIZE 1000

int main() {
    //int codigo1[100], idade[100], numero_telefone[100], numero_dependentes[100];
    //char nome[100], estado_civil[100];
    char buffer[BUFFER_SIZE];
    char funcname[100];
    int totalRead = 0;
    char another = 'S';

    struct funcionario {
        int codigo1[100], idade[100], numero_telefone[100], numero_dependentes[100];
        char nome[100], estado_civil[100];
    };

    struct funcionario e;
    long int recsize;
    recsize = sizeof (e);

    //CREATE
    FILE *fp;

    // Abre o ficheiro txt e acrescenta os dados no final do arquivo e verifica se existe conexão 
    if ((fp = fopen(FILENAME, "a")) != NULL) {
        
        printf("Indique o seu codigo de funcionario [0-100]: ");
        scanf("%d", e.codigo1);
        fprintf(fp, "Codigo funcionario: %d \n", e.codigo1[0]);

        printf("Inroduduza o seu nome: ");
        scanf(" %s", e.nome);
        fprintf(fp, "Nome: %s \n", e.nome);

        printf("Insira a sua idade: ");
        scanf("%d", e.idade);
        fprintf(fp, "Idade: %d \n", e.idade[0]);

        printf("Insira o seu numero de telefone: ");
        scanf("%d", e.numero_telefone);
        fprintf(fp, "Numero de telefone: %d \n", e.numero_telefone[0]);

        printf("Indique o seu estado civil: ");
        scanf(" %s", e.estado_civil);
        fprintf(fp, "Estado civil: %s \n", e.estado_civil);

        printf("Indique o numero de dependentes: ");
        scanf("%d", e.numero_dependentes);
        fprintf(fp, "Numero dependentes: %d \n", e.numero_dependentes[0]);
    }

    fclose(fp);

    //READ
    FILE *fp1;

    //Abre o ficheiro txt em modo de leitura   
    fp1 = fopen(FILENAME, "r");

    //Verificar se existe conexão
    if (fp1 == NULL) {
        printf("\nConexão falhada!\n");
    }

    printf("\nConexão efetuada!\n");

    //Repete o ciclo enquanto tiver linhas para ler
    while (fgets(buffer, BUFFER_SIZE, fp1) != NULL) {

        //Leitura de caracteres em cada linha
        totalRead = strlen(buffer);

        buffer[totalRead - 1] = buffer[totalRead - 1] == '\n'
                ? '\0'
                : buffer[totalRead - 1];

        printf("%s\n", buffer);
    }
    
    printf("\n");
    
    //Fechar conexão com o ficheiro
    fclose(fp1);

    //UPDATE
    FILE *fp2;
    
    //Abre o ficheiro txt em modo de leitura   
    fp2 = fopen(FILENAME, "r+");

    while (another == 'S') {

        printf("\nIndique o codigo de funcionario que desja alterar [0-100]: ");
        scanf(" %s", funcname);
        rewind(fp2);

        while (fread(&e, sizeof(e), 1, fp2) == 1) {
            
            //Verificar se o nome de funcionario existe (funcname) para dar update ao dados do funcionario em questao
            if (strcmp(e.nome, funcname) == 0) {

                //printf("\nIndique o novo codigo, nome, idade, numero de telefone, estado civil e numero de dependentes:\n");
                //scanf("%d %s %d %d %s %d", &e.codigo1[0], &e.nome, &e.idade[0], &e.numero_telefone[0], &e.estado_civil, &e.numero_dependentes[0]);
                
                printf("\nAlterar codigo de funcionario [0-100]: ");
                scanf("%d", &e.codigo1);
                //fprintf(fp2, "Codigo funcionario: %d \n", e.codigo1[0]);
                
                printf("Alterar nome: ");
                scanf("%s", &e.nome);
                //fprintf(fp2, "Nome: %s \n", e.nome);
                
                printf("Alterar a idade: ");
                scanf("%d", &e.idade);
                //fprintf(fp2, "Idade: %d \n", e.idade[0]);
                
                printf("Alterar numero de telefone: ");
                scanf("%d", &e.numero_telefone);
                //fprintf(fp2, "Numero de telefone: %d \n", e.numero_telefone[0]);
                
                printf("Alterar o estado civil: ");
                scanf("%s", &e.estado_civil);
                //fprintf(fp2, "Estado civil: %s \n", e.estado_civil);
                
                printf("Alterar numero de dependentes: ");
                scanf("%d", &e.numero_dependentes);
                //fprintf(fp2, "Numero dependentes: %d \n", e.numero_dependentes[0]);
                
                //fseek(fp2, sizeof(e), SEEK_CUR);
                fseek (ptr, -sizeof e, SEEK_CUR);
                //fwrite(&e, sizeof, 1, fp2);
                fprintf(fp2, "%d %s %d %d %s %d", e.codigo1, e.nome, e.idade, e.numero_telefone, e.estado_civil, e.numero_dependentes);
                
                break;
            }
        }

        printf("\nDeseja efetuar mais alguma alteracao (S/N)");
        //fflush(stdin);
        scanf(" %c", &another);
    }    
    
    //Fechar conexões com o ficheiro
    fclose(fp2);
      
    //DELETE
    FILE *fRead, *fWrite;
    
    char c;
    int Delete_Id, temp = 1;

    fRead = fopen(FILENAME, "r");
    c = getc(fRead);

    while (c != EOF) {
        printf("%c", c);
        c = getc(fRead);
    }

    rewind(fRead);

    printf("\nDelete Staff with ID: ");
    scanf("%d", &Delete_Id);

    Delete_Id = Delete_Id + 1;

    fWrite = fopen("temporary.tmp", "w");
    c = getc(fRead);
    
    while (c != EOF) {
        c = getc(fRead);
        if (c == '\n')
            temp++;
        if (temp != Delete_Id) {
            putc(c, fWrite);
        }
    }

    fclose(fRead);
    fclose(fWrite);

    remove(FILENAME);

    rename("temporary.tmp", FILENAME);
    printf("\nThe contents of file after being modified are as follows:\n");

    fRead = fopen(FILENAME, "r");
    c = getc(fRead);
    while (c != EOF) {
        printf("%c", c);
        c = getc(fRead);
    }

    fclose(fRead);
}

Ps: i cant put the result in images

This is what is supposed to do:

Codigo funcionario: 1
Nome: Bruno
Idade: 33 
Numero de telefone: 93121 
Estado civil: casado 
Numero dependentes: 3

All data from functionary 23 as been deleted.

What is happening:

Delete Staff with ID: 1
odigo funcionario: 1
Idade: 33 
Numero de telefone: 93121 
Estado civil: casado 
Numero dependentes: 3
ÿ
1 Answers

Your loop to copy the database file while deleting a given line is incorrect:

  • you never copy the first byte
  • you test for EOF before reading the next byte, so you do write the EOF to the output file, which appears as ÿ. ('\xff').
  • you increment the line count before testing whether to copy the byte, so the newline of the previous line is not copied but the newline of the deleted line is. Test for newline after copying.
  • it is unclear where temp is initialized to 0 or 1.
  • you do not test for fopen() failure.

It is much better to write a separate function for each task.

For example you can list the database with:

void list_records(const char *filename) {
    FILE *fRead = fopen(filename, "r");
    if (fRead != NULL) {
        int c;
        while ((c = getc(fRead)) != EOF) {
            putchar(c);
        }
    }
    fclose(fRead);
}

And you can delete a record with:

int delete_record(const char *filename, int Delete_Id) {
    const char *temp_name = "temporary.tmp";
    FILE *fRead, *fWrite;
    int line_num, c;

    fRead = fopen(filename, "r");
    if (fRead == NULL) {
        // cannot open database
        return -1;
    }
    fWrite = fopen(temp_name, "w");
    if (fWrite == NULL) {
        // cannot open temporary file
        fclose(fRead);
        return -2;
    }

    line_num = 1;
    while ((c = getc(fRead)) != EOF) {
        if (line_num != Delete_Id) {
            putc(c, fWrite);
        }
        if (c == '\n')
            line_num++;
    }
    fclose(fRead);
    if (fclose(fWrite)) {
        // write error: discard temporary file, return error
        remove(temp_name);
        return -3;
    }
    if (remove(filename)) {
        // cannot remove database: discard temporary file, return error
        remove(temp_name);
        return -4;
    }
    return rename(temp_name, filename);
}

You would change the end of the main function (from //DELETE) with:

    //DELETE
    list_records(FILENAME);

    printf("\nDelete Staff with ID: ");
    if (scanf("%d", &Delete_Id) == 1) {
        delete_record(FILENAME, Delete_Id + 1);
        printf("\nThe contents of file after being modified are as follows:\n");
        list_records(FILENAME);
    } else {
        printf("Invalid input\n");
    }

There are other problems in your code, but here is a modified version with some improvements:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FILENAME "funcionarios.txt"
#define BUFFER_SIZE 1000

void list_records(const char *filename) {
    FILE *fRead = fopen(filename, "r");
    if (fRead != NULL) {
        int c;
        while ((c = getc(fRead)) != EOF) {
            putchar(c);
        }
    }
    fclose(fRead);
}

int delete_record(const char *filename, int Delete_Id) {
    const char *temp_name = "temporary.tmp";
    FILE *fRead, *fWrite;
    int line_num, c;

    fRead = fopen(filename, "r");
    if (fRead == NULL) {
        // cannot open database
        return -1;
    }
    fWrite = fopen(temp_name, "w");
    if (fWrite == NULL) {
        // cannot open temporary file
        fclose(fRead);
        return -2;
    }

    line_num = 1;
    while ((c = getc(fRead)) != EOF) {
        if (line_num != Delete_Id) {
            putc(c, fWrite);
        }
        if (c == '\n')
            line_num++;
    }
    fclose(fRead);
    if (fclose(fWrite)) {
        // write error: discard temporary file, return error
        remove(temp_name);
        return -3;
    }
    if (remove(filename)) {
        // cannot remove database: discard temporary file, return error
        remove(temp_name);
        return -4;
    }
    return rename(temp_name, filename);
}

int main() {
    //int codigo1[100], idade[100], numero_telefone[100], numero_dependentes[100];
    //char nome[100], estado_civil[100];
    char buffer[BUFFER_SIZE];
    char funcname[100];
    int totalRead = 0;
    char another = 'S';

    struct funcionario {
        int codigo1[100], idade[100], numero_telefone[100], numero_dependentes[100];
        char nome[100], estado_civil[100];
    };

    struct funcionario e;
    long int recsize;
    recsize = sizeof (e);

    //CREATE
    FILE *fp;

    // Abre o ficheiro txt e acrescenta os dados no final do arquivo e verifica se existe conexão 
    if ((fp = fopen(FILENAME, "a")) != NULL) {
        
        printf("Indique o seu codigo de funcionario [0-100]: ");
        scanf("%d", e.codigo1);
        fprintf(fp, "Codigo funcionario: %d \n", e.codigo1[0]);

        printf("Inroduduza o seu nome: ");
        scanf(" %s", e.nome);
        fprintf(fp, "Nome: %s \n", e.nome);

        printf("Insira a sua idade: ");
        scanf("%d", e.idade);
        fprintf(fp, "Idade: %d \n", e.idade[0]);

        printf("Insira o seu numero de telefone: ");
        scanf("%d", e.numero_telefone);
        fprintf(fp, "Numero de telefone: %d \n", e.numero_telefone[0]);

        printf("Indique o seu estado civil: ");
        scanf(" %s", e.estado_civil);
        fprintf(fp, "Estado civil: %s \n", e.estado_civil);

        printf("Indique o numero de dependentes: ");
        scanf("%d", e.numero_dependentes);
        fprintf(fp, "Numero dependentes: %d \n", e.numero_dependentes[0]);
    }

    fclose(fp);

    //READ
    FILE *fp1;

    //Abre o ficheiro txt em modo de leitura   
    fp1 = fopen(FILENAME, "r");

    //Verificar se existe conexão
    if (fp1 == NULL) {
        printf("\nConexão falhada!\n");
        exit(1);
    }

    printf("\nConexão efetuada!\n");

    //Repete o ciclo enquanto tiver linhas para ler
    while (fgets(buffer, BUFFER_SIZE, fp1) != NULL) {

        // strip the tailing newline if any
        buffer[strcspn(buffer, "\n")] = '\0'; 
        printf("%s\n", buffer);
    }
    
    printf("\n");
    
    //Fechar conexão com o ficheiro
    fclose(fp1);

    //UPDATE
    FILE *fp2;
    
    //Abre o ficheiro txt em modo de leitura   
    fp2 = fopen(FILENAME, "r+");

    while (another == 'S') {

        printf("\nIndique o codigo de funcionario que desja alterar [0-100]: ");
        scanf(" %s", funcname);
        rewind(fp2);

        while (fread(&e, sizeof(e), 1, fp2) == 1) {
            
            //Verificar se o nome de funcionario existe (funcname) para dar update ao dados do funcionario em questao
            if (strcmp(e.nome, funcname) == 0) {

                //printf("\nIndique o novo codigo, nome, idade, numero de telefone, estado civil e numero de dependentes:\n");
                //scanf("%d %s %d %d %s %d", &e.codigo1[0], &e.nome, &e.idade[0], &e.numero_telefone[0], &e.estado_civil, &e.numero_dependentes[0]);
                
                printf("\nAlterar codigo de funcionario [0-100]: ");
                scanf("%d", &e.codigo1);
                //fprintf(fp2, "Codigo funcionario: %d \n", e.codigo1[0]);
                
                printf("Alterar nome: ");
                scanf("%s", &e.nome);
                //fprintf(fp2, "Nome: %s \n", e.nome);
                
                printf("Alterar a idade: ");
                scanf("%d", &e.idade);
                //fprintf(fp2, "Idade: %d \n", e.idade[0]);
                
                printf("Alterar numero de telefone: ");
                scanf("%d", &e.numero_telefone);
                //fprintf(fp2, "Numero de telefone: %d \n", e.numero_telefone[0]);
                
                printf("Alterar o estado civil: ");
                scanf("%s", &e.estado_civil);
                //fprintf(fp2, "Estado civil: %s \n", e.estado_civil);
                
                printf("Alterar numero de dependentes: ");
                scanf("%d", &e.numero_dependentes);
                //fprintf(fp2, "Numero dependentes: %d \n", e.numero_dependentes[0]);
                
                //fseek(fp2, sizeof(e), SEEK_CUR);
                fseek (ptr, -sizeof e, SEEK_CUR);
                //fwrite(&e, sizeof, 1, fp2);
                fprintf(fp2, "%d %s %d %d %s %d", e.codigo1, e.nome, e.idade, e.numero_telefone, e.estado_civil, e.numero_dependentes);
                
                break;
            }
        }

        printf("\nDeseja efetuar mais alguma alteracao (S/N)");
        scanf(" %c", &another);
    }    
    
    //Fechar conexões com o ficheiro
    fclose(fp2);
      
    //DELETE
    list_records(FILENAME);

    printf("\nDelete Staff with ID: ");
    if (scanf("%d", &Delete_Id) == 1) {
        delete_record(FILENAME, Delete_Id + 1);
        printf("\nThe contents of file after being modified are as follows:\n");
        list_records(FILENAME);
    } else {
        printf("Invalid input\n");
    }
    return 0;
}
Related