c - 从函数中删除所有数据的问题
问题描述
在我使用 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 ÿ
解决方案
您在删除给定行时复制数据库文件的循环不正确:
- 你永远不会复制第一个字节
EOF
您在读取下一个字节之前进行测试,因此您确实将 写入EOF
输出文件,该文件显示为ÿ
. ('\xff'
)。- 在测试是否复制字节之前增加行数,因此不会复制上一行的换行符,而是复制已删除行的换行符。复制后测试换行符。
- 目前尚不清楚在哪里
temp
初始化为0
或1
。 - 你不测试
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;
}
推荐阅读
- android - Android / iOS 中的免费 FMX 组件
- c++ - 一个读取整数的程序,只要它们交替正负。C++
- sql-server - .Net Core Worker Service 作为 Windows 服务有时不起作用
- shell - 使用 databricks cli 创建配置文件而不传递参数
- git - CI/CD 的 Git 分支和环境开发流程
- python-3.x - 所有素数之和
- python - 如何在没有 for 循环的情况下将 itertools 组合作为列表列表
- linux - asm 中系统调用的引用
- python - 如何使用 Python 解析 Redis Streams 数据?
- r - 跨分组行使用 case_when() 并选择项目何时出现 - tidyverse/R 解决方案