Program does not enter the while loop

127 Views Asked by At
#include <stdio.h>
#include <string.h>

struct Employee {
    int id;
    char name[50];
    float salary;
};

int main() {
    FILE *file;
    char filename[] = "employee.txt";
    int dataFound = 0;
    int recordno = 0;

    // Step 1: Open the file in read and write mode
    file = fopen(filename, "r+");

    // Step 2: Check if the file opened successfully
    if (file == NULL) {
        printf("Could not open file %s for reading and writing.\n", filename);
        return 1;  // Exit with an error code
    }
    char name[15];
    // Step 3: Get the name of the employee to be updated
    printf("Enter the name of the employee to be updated: ");
    gets(name);

    // Step 4: Search for the employee with the specified name
    struct Employee emp;

    while (fread(&emp, sizeof(emp), 1, file) == 1) {
        if (strcmp(emp.name, name) == 0) {\
            dataFound = 1;
            // Employee found, update the details
            printf("Enter the new details for employee %d:\n", emp.id);
            printf("Id: ");
            scanf("%d", &emp.id);
            printf("Salary: ");
            scanf("%f", &emp.salary);

            // Move the file pointer to the beginning of the current record
            fseek(file, sizeof(struct Employee), SEEK_CUR);

            // Write the updated details to the file
            if (fwrite(&emp, sizeof(struct Employee), 1, file) == 1) {
                printf("Employee details updated successfully.\n");
            }
            recordno++;
        }
    }
    if (dataFound == 0) {
        printf("\nData not found\n");
    }

    // Step 5: Close the file
    fclose(file);

    return 0;
}

I am trying to update data that is stored in a txt file. I stored the data using structure. When I reach step 4 the program enters the while loop but the if statement inside the while loop does not return true. (I checked it using if else) Can anyone help me out?

This is how the data is stored in the employee.txt file:

Id : 1 
Name : aayush
Salary : 4000 
Id : 2 
Name : aashish
Salary : 3000 
2

There are 2 best solutions below

0
chqrlie On

There are multiple problems

  • If the text file employee.txt indeed has the posted contents, you cannot load a record with fread, you would need to read and parse the contents to extract the record fields according to the syntax and you couldn't update it in place as seems to be the goal of your program because the updated id and/or the salary could use a different number of characters, corrupting the text file. The employee file must be in binary format with fixed size records for this program and you must open it in binary mode with "rb".

  • The reason the if test is always false is emp.name read via fread(&emp, ...) is not the employee name, nor is it a null terminated C string, given the contents of the file, emp.name should contain " 1\nName : aayush\nSalary : 4000\nId : 2\nName : aashi" without a null terminator (bytes 5 to 54 of the file).

  • gets() must not be used. This function cannot test for buffer overflow so it cannot be used safely for user supplied contents. It has been removed from recent versions of the C Standard. Use fgets() to read a line and strip the newline.

  • the array name into which you read the name is too short: 15 bytes, whereas the name field of the Employee structure has 50 bytes, allowing for names up to 49 characters.

  • You seek forward when you have a match instead of seeking backward.

  • you must use fseek again after writing to the file to allow switching back to reading from it.

Here is a modified version:

#include <stdio.h>
#include <string.h>

struct Employee {
    int id;
    char name[50];
    float salary;
};

int main() {
    char filename[] = "employee.txt";
    int dataFound = 0;
    int recordno = 0;

    // Step 1: Open the file in read and write mode
    FILE *file = fopen(filename, "rb+");

    // Step 2: Check if the file opened successfully
    if (file == NULL) {
        printf("Could not open file %s for reading and writing.\n", filename);
        return 1;  // Exit with an error code
    }
    char name[80];
    // Step 3: Get the name of the employee to be updated
    printf("Enter the name of the employee to be updated: ");
    if (!fgets(name, sizeof name, stdin)) {
        printf("missing name\n");
        fclose(file);
        return 1;
    }

    // strip the newline if any
    name[strcspn(name, "\n")] = '\0';

    // Step 4: Search for the employee with the specified name
    struct Employee emp;

    while (fread(&emp, sizeof(emp), 1, file) == 1) {
        if (strcmp(emp.name, name) == 0) {
            dataFound = 1;
            // Employee found, update the details
            printf("Enter the new details for employee %d:\n", emp.id);
            printf("Id: ");
            scanf("%d", &emp.id);
            printf("Salary: ");
            scanf("%f", &emp.salary);

            // Move the file pointer to the beginning of the current record
            fseek(file, -sizeof(struct Employee), SEEK_CUR);

            // Write the updated details to the file
            if (fwrite(&emp, sizeof(struct Employee), 1, file) == 1) {
                printf("Employee details updated successfully.\n");
            } else {
                printf("write error\n");
                fclose(file);
                return 1;
            }

            // seek to the current position before reading from the file
            fseek(file, 0L, SEEK_CUR);

            recordno++;
        }
    }
    if (dataFound == 0) {
        printf("\nData not found\n");
    }

    // Step 5: Close the file
    fclose(file);

    return 0;
}
0
lechatbleu On

You try to read a struct Employee but your data isn't in a good format, you need to read the data in the same way where they are written, try to write your struct and you will see that the fill contain strange character it's because we write each bytes of your struct one per one, for exemple a int is 4 bytes and a char is 1 bytes so a int can by write in 4 character.

Use this 2 functions to test how it works :

// write to file
int main(void) {
    struct Employee emp;
    emp.id = 1;
    strcpy(emp.name, "John");
    emp.salary = 10000.0;

    FILE *file = fopen("employee.txt", "w");
    if (file == NULL) {
        printf("Could not open file employee.txt.\n");
        return 1;
    }

    if (fwrite(&emp, sizeof(struct Employee), 1, file) == 1) {
        printf("Employee details written successfully.\n");
    }

    fclose(file);
}

// read from file
int main(void) {
    struct Employee emp;

    FILE *file = fopen("employee.txt", "r");
    if (file == NULL) {
        printf("Could not open file employee.txt.\n");
        return 1;
    }

    while (fread(&emp, sizeof(struct Employee), 1, file) == 1) {
        printf("Id: %d\n", emp.id);
        printf("Name: %s\n", emp.name);
        printf("Salary: %.2f\n", emp.salary);
    }

    fclose(file);
}