Редактировать / Изменить & Удалить запись из файла произвольного доступа в C
Программа должна изменить или удалить конкретную запись в соответствии с идентификатором сотрудника, при изменении части она записывает измененную запись как новую в конец файла, удаляющая часть работает только один раз, а затем вызывает ошибку сегментации.
Модификация:
Как я могу изменить код, чтобы переписать отредактированную запись в той же позиции?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
struct record_em{
int id;
char name[20];
int salary;
int age;
};
int main( void )
{
struct record_em employee;
FILE *fp;
int n;
int ch;
fp = fopen("empRecord.dat","rb+");
printf("Enter Id Number:\n");
scanf("%d",&n);
rewind(fp);
while (!feof(fp)){
fscanf(fp,"%d %s %d %d", &employee.id, employee.name, &employee.salary, &employee.age);
if (employee.id==n){
printf("%d %s %d %d \n",employee.id, employee.name, employee.salary,employee.age);
printf("\n Do you want to change the name ?\n");
scanf("%d",&ch);
if (ch==1){
printf("Enter new name:\n");
scanf("%s",employee.name);
}
printf("\n Do you want to change the salary ?(y/n)\n");
scanf("%d",&ch);
if ( ch==2 ){
printf("Enter new salary:\n");
scanf("%d",&employee.salary);
}
printf("\n Do you want to change the age ?(y/n)\n");
scanf("%d",&ch);
if ( ch==3 ){
printf("Enter new age:\n");
scanf("%d",&employee.age);
}
fseek(fp,-sizeof(employee),SEEK_CUR);
fprintf(fp, "%d %s %d %d\n", employee.id, employee.name, employee.salary, employee.age);
exit(0);
}
}
printf("Record Not Found \n");
return 0;
}
Удаление:
Как я могу изменить код, чтобы он удалял записи столько раз, сколько я хочу?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
struct record_em{
int id;
char name[20];
int salary;
int age;
};
int main()
{
struct record_em employee;
FILE *fp, *ft;
int n;
fp = fopen("empRecord.dat","r");
ft = fopen("Temp.dat","wb+");
printf("\nEnter ID of employee to delete ");
scanf("%d",&n);
rewind(fp);
while (!feof(fp)){
fscanf(fp,"%d %s %d %d", &employee.id, employee.name, &employee.salary, &employee.age);
if(employee.id!=n){
fprintf(ft, "%d %s %d %d\n", employee.id, employee.name, employee.salary, employee.age);
}
}
fclose(fp);
fclose(ft);
remove("empRecord.dat");
rename("Temp.dat","EempRecord.dat");
return 0;
}
4 ответа
Вот ключевой пункт кода:
void update(char filename[],char name[])
{
int records=0;
FILE *fp = fopen(filename,"rb+");
while(fread(&st,sizeof(st),1,fp)==1)
{
if(strcmp(name,st.name)==0)
{
printf("\nEnter new name: ");
scanf("%s",st.name);
printf("\nEnter new roll no.: ");
scanf("%d",&st.roll);
fseek(fp,sizeof(struct student)*records,SEEK_SET);//This is key line..
fwrite(&st,sizeof(st),1,fp);
}
records++; // in the while loop...
}
fclose(fp);
}
Ниже приведена структура студента:
struct student{
int roll;
char name[20];
}st;
Это общий метод для изменения / обновления записи. Вы можете использовать тот же синтаксис для вашей структуры сотрудников.
SEEK_CUR
смещение относительно текущей позиции указателя файла. Таким образом, вы можете сказать: "Перейти к моей текущей позиции плюс 30 байтов" или "перейти к моей текущей позиции минус 20 байтов". например. fseek(fp, -30, SEEK_CUR)
ссылка http://beej.us/guide/bgc/output/html/multipage/fseek.html
Я не думаю, что он не прав в использовании негатива sizeof()
функция. Но вам лучше использовать sizeof(struct record_em)
вместо!
Я думаю, что это ваша проблема, сначала у вас есть знак минус до sizeof
это немного странно видеть, и второе SEEK_CUR
заставляет вас двигаться дальше, чем ваш текущий файл, поэтому посмотрите здесь fseek(), rewind()
fseek(fp,-sizeof(employee),SEEK_CUR); //This is not the definitive read below.
^------minus symbol. ^------- the type of seek.
Я рекомендую Вам сделать несколько модификаций:
Используйте общий
Formatted File
чтобы сделать вашу жизнь проще, помните: "Совершенство - это простота".использование
SEEK_SET
чтобы использовать относительную позицию от начала файла, второй используйтеstruct's size
в качестве параметра дляsizeof
,fseek( fp, sizeof( struct record_em), SEEK_SET );
Использовать
member
Идентификатор в качестве ключа вашего приемника и использовать последовательные серии чисел, но, очевидно, вы должны были создать файл с 100, 1000 работодателей.1 Andrew 20000 27 ^ ^ ^ ^_____ age | | |__________ salary ( I would have used double here) | |_________________ name |_____________________ id ( Key for the relative position from the beginning)
Вам придется передумать, и когда вы представите, что "удалите" запись, вы напишите пробел (за исключением ключа). Пример. Представьте, что бедного Эндрю уволили, а вы удалите его запись.
1 "Empty space" 0 0 ^ ^ ^ ^______ age (0 = nothing) | | |__________ salary (0 = nothing) | |____________________ name ("" = nothing) |____________________________ id ( Key for the relative position from the beginning)
PD: в настоящее время добавление дополнительной информации.
Не хорошо манипулировать двоичным файлом, используя функции C, которые предназначены для работы с текстовыми файлами fprintf.
Например, в вашем коде я вижу:
fseek(fp,-sizeof(employee),SEEK_CUR);
fprintf(fp, "%d %s %d %d\n", employee.id, employee.name, employee.salary, employee.age);
Это принесет вам проблемы, поскольку вы путешествуете внутри своего файла в виде двоичного файла, а затем пишете на нем символы. Вместо этого вы должны использовать функцию fwrite.
Моя рекомендация: проверь всю свою программу, определи стратегию постоянства и соблюдай ее.