Hadi Rasouli
Hadi Rasouli

Reputation: 2047

how to delete a record from a file in c (saved records are struct )

i have a program to list the students , it can add new one , search and even delete a student from the list by the student number, it contains a struct of student info .all of the information is on a file named REG.DAT . my problem is in the >>DELETE<< part.i want to delete a student from the list by its student number, but when i do this i lost the rest of the list up to the person that must be deleted . please help me to solve this problem .here is my code:

void _remove()
{
    int std_num = 0 , k ;
    int status = 1 , i = -1 , j = 0  ; 
    struct students read[100] ,temp;
    FILE *p ;

    p = fopen("reg.dat","rb");
    if(!p)
    {
        system("cls");
        cout << ">>>>>Register file could not be opened! call the support .<<<<<" << endl;
        _menu();
    }
    while(!feof(p))
    {
        fread(&read[i],sizeof(struct students),1,p) ;
        i++;
    }
    cout << "Enter STD NO. to delete from the list : " << endl ;
    cin >> std_num ;
    for( j = 0 ; j < i ; j++)
    {
        if(std_num == read[j].std_num)
        {
            for( k = j + 1 ; k < i ; k++)
            {
                memcpy(&read[k-1] , &read[k],sizeof (students));
            }
        }
    }
    fclose(p);

    FILE *fp;
    fp = fopen("reg.dat","wb"); 
    for( int l = 0 ; l < i - 2 ; l++)
        fwrite(&read[l], sizeof(struct students), 1 ,fp );
    fclose(fp);
    system("cls") ;
    cout << "STD with NO. " << std_num << " has been removed" << endl ; 
    _menu();
}

Upvotes: 2

Views: 2656

Answers (2)

Bo.
Bo.

Reputation: 2541

You should not be using memcpy for overlapping memory sections. You should use instead memmov. As memmov description states:

Move block of memory Copies the values of num bytes from the location pointed by source to the memory block pointed by destination. Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.

Also:
- You could stop iterating over first loop using break statement after you have found your student number.

Kind regards,
Bo

Upvotes: 3

Jirka Hanika
Jirka Hanika

Reputation: 13547

The usual approach is to

  • Add a bool is_deleted member to struct student.
  • When deleting a student, update the struct with setting is_deleted to true.
  • When reading student records, ignore the deleted ones.
  • Provide a procedure that reads the whole file record by record and copies it to another file, skipping deleted records. Then rename this other file to the original name. Call this procedure periodically, or at program start-up, or only manually as needed.

Upvotes: 1

Related Questions