首页 > 解决方案 > 从函数中删除所有数据的问题

问题描述

在我使用 C 创建 CRUD 系统时遇到问题。目前我设法创建和更新,但我没有成功删除一个。

目标:给定用户的 ID,删除包含该 ID 的结构的所有数据。

到目前为止,这是我设法做到的:

#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:我不能把结果放在图像中

这是应该做的:

Codigo funcionario: 1
姓名:布鲁诺
伊达德:33
电话号码:93121
Estado Civil: 卡萨多
家属人数:3

23 号工作人员的所有数据均已删除。

怎么了:

删除 ID 为:1 的员工
odigo funcionario: 1
伊达德:33
电话号码:93121
Estado Civil: 卡萨多
家属人数:3
ÿ

标签: c

解决方案


您在删除给定行时复制数据库文件的循环不正确:

  • 你永远不会复制第一个字节
  • EOF您在读取下一个字节之前进行测试,因此您确实将 写入EOF输出文件,该文件显示为ÿ. ( '\xff')。
  • 在测试是否复制字节之前增加行数,因此不会复制上一行的换行符,而是复制已删除行的换行符。复制测试换行符。
  • 目前尚不清楚在哪里temp初始化为01
  • 你不测试fopen()失败。

为每个任务编写一个单独的函数要好得多。

例如,您可以列出数据库:

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);
}

您可以使用以下命令更改main函数的结尾(从//DELETE):

    //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");
    }

您的代码中还有其他问题,但这里是经过一些改进的修改版本:

#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;
}

推荐阅读