Question

I need your help for sequential file access in c programming. Following code is the part of the code I've written.

I can insert a record, search a record, display all records But when it comes for modify and delete I'm unable to get required results. Can you direct me in this case please ?

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

int c,i,id;
char name[20];
FILE *fp;
int n;
int search(FILE *fp,int id);
void display(FILE *fp);

typedef struct details
{
    int id;
    char name[20];
}details;

details d;


void main()
{
    printf("\nHow many records you would like to insert ? : ");
    scanf("%d",&n);
    fp=fopen("one.txt","a");
    for(i=0;i<n;i++)
    {
        printf("\nEnter id and name");
        scanf("%d%s",&d.id,d.name);
        fwrite(&d,sizeof(d),1,fp);
    }
    fclose(fp);


    while(1)
    {
        printf("\nWhat would you like to do now ? : \n");
        printf("\n1.Display \t2.Search \t3.Modify \t4.Delete \t5.Exit");
        scanf("%d",&c);
        switch(c)
        {
            case 1:
                fp=fopen("one.txt","r+");
                display(fp);
                fclose(fp);
                break;
            case 2:
                fp=fopen("one.txt","r+");
                printf("\nEnter ID to search : ");
                scanf("%d",&id);
                if(search(fp,id))
                {
                    printf("\nThe record is as follows : ");
                    printf("\n%d\t%s",d.id,d.name);
                }
                else
                    printf("\nRecord not found");
                fclose(fp);
                break;
            case 3:
                fp=fopen("one.txt","r+");
                printf("\nEnter ID to modify d record : ");
                scanf("%d",&id);

                if(search(fp,id))
                {
                    printf("\nEnter new name");
                    scanf("%s",d.name);
                    fwrite(&d,sizeof(d),1,fp);
                }
                else
                    printf("\nSpecified record not found ");
                fclose(fp);
                break;              
        }
    }
}                           

int search(FILE *fp,int id)
{
    rewind(fp);
    while(fread(&d,sizeof(d),1,fp))
    {
        if(id==d.id)
        return 1;
    }
    return 0;
}

void display(FILE *fp)
{
    rewind(fp);
    while(fread(&d,sizeof(d),1,fp))
    {
        printf("\n%d\t%s",d.id,d.name); 
    }
}
Was it helpful?

Solution 2

Thank-you for this question. Have modified your code to remember its file position as the code scans the file by id. Refer to the field curr_pos and how it is used by ftell and fseek. Also, added a few fflush statements to get it to work on the Eclipse IDE.

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

int c,i,id;
char name[20];
FILE *fp;
int n;

long curr_pos;

int search(FILE *fp,int id);
void display(FILE *fp);

typedef struct details
{
    int id;
    char name[20];
}details;

details d;


void main()
{
    printf("\nHow many records you would like to insert ? : "); fflush(stdout);

    scanf("%d",&n);
    fp=fopen("one.txt","a");
    for(i=0;i<n;i++)
    {
        printf("\nEnter id and name"); fflush(stdout);
        scanf("%d%s",&d.id,d.name);
        fwrite(&d,sizeof(d),1,fp);
    }
    fclose(fp);

    while(1)
    {
        printf("\nWhat would you like to do now ? : \n");
        printf("\n1.Display \t2.Search \t3.Modify \t4.Delete \t5.Exit\n");
        fflush(stdout);

        scanf("%d",&c);
        switch(c)
        {
            case 1:
                fp=fopen("one.txt","r+");
                display(fp);
                fclose(fp);
                break;
            case 2:
                fp=fopen("one.txt","r+");
                printf("\nEnter ID to search : "); fflush(stdout);
                scanf("%d",&id);
                if(search(fp,id))
                {
                    printf("\nThe record is as follows : ");
                    printf("\n%d\t%s",d.id,d.name); fflush(stdout);
                }
                else
                    printf("\nRecord not found");
                fclose(fp);
                break;
            case 3:
                fp=fopen("one.txt","r+");
                printf("\nEnter ID to modify d record : "); fflush(stdout);
                scanf("%d",&id);

                if(search(fp,id))
                {
                    printf("\nEnter new name : "); fflush(stdout);
                    scanf("%s",d.name);

                    // back-up one record, to get to start of current record
                    fseek(fp, curr_pos, 0);
                    fwrite(&d,sizeof(d),1,fp);
                }
                else
                    printf("\nSpecified record not found ");
                fclose(fp);
                break;
        }
    }
}

int search(FILE *fp,int id)
{
    rewind(fp);
    curr_pos = ftell(fp);
    while(fread(&d,sizeof(d),1,fp))
    {
        if(id==d.id) {return 1;}

        curr_pos = ftell(fp);
    }
    return 0;
}

void display(FILE *fp)
{
    rewind(fp);
    while(fread(&d,sizeof(d),1,fp))
    {
        printf("\n%d\t%s",d.id,d.name);
    }
}

Hope this helps.

OTHER TIPS

Since you are using fixed-sized records, it's easy to modify. Just search for the entry and write the new record over the old one. Just remember that after you searched for the record you have to seek backward to the beginning of the record.

As for deleting records, it's harder. Here you actually have to write all records except the one you want to remove to a temporary file, and then rename the temporary file as the original data file. Or do it all in memory, and then rewrite the file from scratch with the records from memory.

The problem is that you can not remove data from the middle of a file. So the only thing you can do is, to rewrite the entire file from scratch (either directly or using a copy) or you can mark the records as deleted. This will leave the file size as it is of course. From time to time you can rewrite the file removing all deleted records, thus compacting the file again.

Wether this is a feasble approach depends on how often you really delete a record, and of course, if a record is deleted, you can overwrite it with a new one, later, when you insert one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top