-1

I'm having trouble populating an array with data I'm trying to read from a txt file. So I used the following code to try and read from the following txt file.

txt file:

Smith, Susan
B
80.0
17.76

Sanders, Fred
M
87.25
23.45

Kerr, Heidi
M
80.0
47.86

Russo, Rick
B
83.75
12.15

code i used:


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


typedef struct employee

{

    char name[100];      // employee's name - last, first

    char title;          // title 'B' or 'M'

    double hours_worked; // total number of hours worked

    double payrate;      // pay rate per hour

    double payment;      // total payment for the pay period 

} Employee;

int main()
{
    Employee payroll[200];
    int i = 0;
    FILE*infile;
    infile = fopen("payroll.txt", "r");
    //fscanf loop that will fill payroll array with data from file
    while (!feof(infile))
    {

        fscanf(infile, " %s", &payroll[i].name); //Reading name
        fscanf(infile, "%c", &payroll[i].title); //Reading title
        fscanf(infile, "%lf", &payroll[i].hours_worked); //Reading hours worked
        fscanf(infile, "%lf", &payroll[i].payrate); //Reading pay rate
        ++i;
    }
    printf("%d\n", i);
//loop that tests to make sure array was correctly filled
    for (i = 0; i < 4; ++i)
    {
        printf("%s\n", payroll[i].name);
        printf("%c\n", payroll[i].title);
        printf("%lf\n", payroll[i].hours_worked);
        printf("%lf\n", payroll[i].payrate);

    }





    fclose(infile);
    system("pause");
    return 0;
}

So I realized that my issue had to be the first fscanf that's reading the string name because fscanf is stopping once it reads the white space where it reads the names so I switched to fgets():


        fgets(payroll[i].name, 100, infile);


But that still doesn't give me a correct result.

Please help

edit: So there's obviously something else wrong with my fscanfs because If I edited the txt file to this to eliminate the whitespace so fscanf can be used:


Smith,Susan
B
80.0
17.76
Sanders,Fred
M
87.25
23.45
Kerr,Heidi
M
80.0
47.86
Russo,Rick
B
83.75
12.15

where I'm using this code:


while (!feof(infile))
    {   
        fscanf(infile, " %s", &payroll[i].name); //Reading name
        fscanf(infile, "%c", &payroll[i].title); //Reading title
        fscanf(infile, "%lf", &payroll[i].hours_worked); //Reading hours worked
        fscanf(infile, "%lf", &payroll[i].payrate); //Reading pay rate
        ++i;
    }

I'll still get an error where the printresults are something crazy like this: https://i.stack.imgur.com/x6l7a.png

Ely Meyers
  • 11
  • 5

1 Answers1

2

It is easier to control the input and data extraction by using fgets and sscanf than with fscanf, like this, with some other commented changes and additions.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define RECORDS 200             // better not to hard-code inline
#define NAMELEN 99

typedef struct employee {
    char name[NAMELEN+1];       // employee's name - last, first
    char title;                 // title 'B' or 'M'
    double hours_worked;        // total number of hours worked
    double payrate;             // pay rate per hour
    double payment;             // total payment for the pay period 
} Employee;

int main(void)
{
    char instr[256];
    Employee payroll[RECORDS];
    int records = 0;                            // `i` was a poor choice of name
    FILE *infile;
    infile = fopen("payroll.txt", "r");
    if(infile == NULL) {
        perror("Could not open file");
        exit(1);                                // check file opened
    }

    // loop that will fill payroll array with data from file
    while(fgets(instr, sizeof instr, infile) != NULL) {
        // name
        if(records >= RECORDS) {
            perror("Too many records");
            exit(1);
        }
        instr[ strcspn(instr, "\r\n") ] = 0;    // remove trailing newline etc
        instr[NAMELEN] = 0;                     // truncate long name 
        strcpy(payroll[records].name, instr);

        // title
        if(fgets(instr, sizeof instr, infile) == NULL) {
            perror("Incomplete data");
            exit(1);
        }
        payroll[records].title = instr[0];

        // hours worked
        if(fgets(instr, sizeof instr, infile) == NULL) {
            perror("Incomplete data");
            exit(1);
        }
        if(sscanf(instr, "%lf", &payroll[records].hours_worked) != 1) {
            perror("Error in hours worked");
            exit(1);
        }

        // pay rate
        if(fgets(instr, sizeof instr, infile) == NULL) {
            perror("Incomplete data");
            exit(1);
        }
        if(sscanf(instr, "%lf", &payroll[records].payrate) != 1) {
            perror("Error in pay rate");
            exit(1);
        }

        ++records;
    }
    printf("%d records\n", records);

    //loop that tests to make sure array was correctly filled
    for (int i = 0; i < records; ++i) {                 // use the variable
        printf("%s\n", payroll[i].name);
        printf("%c\n", payroll[i].title);
        printf("%.2f\n", payroll[i].hours_worked);      // %f not %lf
        printf("%.2f\n", payroll[i].payrate);           // specify dec places
        printf("\n");
    }

    fclose(infile);
    return 0;
}

Program output:

4 records
Smith,Susan
B
80.00
17.76
Sanders,Fred M 87.25 23.45
Kerr,Heidi M 80.00 47.86
Russo,Rick B 83.75 12.15

Note that feof does not check for end-of-file. It checks whether you made an error by previously reading past the end-of-file (where there is no data).


Edit: Alternatively, if you do want the solution to use fscanf here is
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define RECORDS 200             // better not to hard-code inline
#define NAMELEN 99

typedef struct employee {
    char name[NAMELEN+1];       // employee's name - last, first
    char title;                 // title 'B' or 'M'
    double hours_worked;        // total number of hours worked
    double payrate;             // pay rate per hour
    double payment;             // total payment for the pay period 
} Employee;

int main(void)
{
    Employee payroll[RECORDS];
    int records = 0;                                // `i` was a poor choice of name
    FILE *infile;
    infile = fopen("payroll.txt", "r");
    if(infile == NULL) {
        perror("Could not open file");
        exit(1);                                    // check file opened
    }

    // loop that will fill payroll array with data from file
    while(fscanf(infile, " %99[^\n] %c%lf%lf",      // spaces remove the newlines
             payroll[records].name,                 // no `&`
            &payroll[records].title,
            &payroll[records].hours_worked, 
            &payroll[records].payrate) == 4) {
        ++records;
    }
    printf("%d records\n", records);

    //loop that tests to make sure array was correctly filled
    for (int i = 0; i < records; ++i) {             // use the variable
        printf("%s\n", payroll[i].name);
        printf("%c\n", payroll[i].title);
        printf("%.2f\n", payroll[i].hours_worked);  // %f not %lf
        printf("%.2f\n", payroll[i].payrate);       // specify dec places
        printf("\n");
    }

    fclose(infile);
    return 0;
}
Weather Vane
  • 33,872
  • 7
  • 36
  • 56