Dev M
Dev M

Reputation: 21

C Programming: How to delete a single record from a file

I'm trying to delete a record from a file, by copying all of the records to a temporary file, except the one to be deleted. Then I delete the old file and rename the temporary file. Before renaming, I'm testing to see if the data actually transfers, but when I enter the prompted date and details, the program just freezes, even though the data I enter is from a record in the file. Can anyone help?

Here's the code:

void del_income() {
    Income I;
    Delete D;
    FILE *INCOME = fopen("C:\\income.txt", "a");
    FILE *TEMP = fopen("C:\\temporary.txt", "a");
    printf("Enter date of record to be deleted:");
    scanf("%s", D.date);
    printf("Enter job details of records to be deleted:");
    scanf("%s", D.details);
    while (1) {
        fscanf(INCOME, "%s %s %s %d %d %d %d %d",
               I.date, I.details, I.vehicleno, &I.rate, &I.hours, &I.subtotal,
               &I.vat, &I.total);
        if (feof(INCOME))
            break;
        if (strcmp(I.date, D.date) == 1 && strcmp(I.details, D.details) == 1)
            fprintf(TEMP, "%s %s %s %d %d %d %d %d",
                    I.date, I.details, I.vehicleno, I.rate, I.hours, I.subtotal,
                    I.vat, I.total);
    }
    fclose(INCOME);
    fclose(TEMP);
    system("cls");
}

Upvotes: 1

Views: 128

Answers (1)

chqrlie
chqrlie

Reputation: 145307

There are multiple problems in your code:

  • INCOME should be open with mode "r", not "a"
  • TEMP should be open with mode "w", not "a"
  • return values from fopen and scanf should be tested to avoid undefined behavior on errors.
  • if (feof(INCOME)) is not the proper way to test for end of file, you should instead check if fscanf() succeeded at converting 8 values: it should return 8. Any other return value is either a format error, missing fields or the end of file.
  • strcmp(I.date, D.date) == 1 is incorrect: strcmp() returns 0 for identical strings, < 0 if I.date is lexicographically before D.date and > 0 if it compares greater. You should change your tests to:

    if (strcmp(I.date, D.date) != 0 || strcmp(I.details, D.details) != 0)
    
  • you should add a trailing newline in fprintf(TEMP, "%s %s %s %d %d %d %d %d", ...)

  • conversion formats for strings %s should specify the maximum number of characters to store to the destination arrays to avoid undefined behavior on invalid input. For example if D.date is an array of 50 bytes, you should write:

    if (scanf("%49s", D.date) != 1) { /* handle input error */ }
    

Upvotes: 2

Related Questions