I'm trying to scan a txt file and based on if some conditions are met, I want to print it out into another txt file. Here is my main function:
#include "Header.h"
int main(void) {
int payment=0, hours_worked = 0, rate_per_hour = 0, overtime = 0, total_payment, min = 0, max = 0, average = 0;
total_payment=0;
double total = 0;
Employee payroll[200];
FILE* infile = fopen("payroll.txt", "r");
FILE* outfile = fopen("paid.txt", "w");
int i = 0;
while (!feof(infile)) {
fscanf(infile, "%s", &payroll[i].name);
fscanf(infile, "%s", &payroll[i].title);
fscanf(infile, "%s", &payroll[i].hours_worked);
fscanf(infile, "%s", &payroll[i].payrate);
if (payroll[i].title == 'B') {
if (payroll[i].hours_worked > 40) {
payroll[i].payment = 40 * payroll[i].payrate;
payroll[i].payment = (1.5 * payroll[i].payrate * (payroll[i].hours_worked - 40));
}
else
payroll[i].payment = payroll[i].hours_worked * payroll[i].payrate;
}
else {
if (payroll[i].hours_worked > 40) {
payroll[i].payment = 40 * payroll[i].payrate;
payroll[i].payment = (1.8 * payroll[i].payrate * (payroll[i].hours_worked - 40));
}
else
payroll[i].payment = payroll[i].hours_worked * payroll[i].payrate;
}
if (i == 0)
min = payroll[i].payment;
total = payroll[i].payment;
if (min > payroll[i].payment)
min = payroll[i].payment;
if (max < payroll[i].payment)
max = payroll[i].payment;
i ;
}
average = total / i;
fprintf(outfile, "total: $%.2lf\n average: $%.3lf\nMAx: $%.3lf\n Min: $%.2lf", total, average, max, min);
fclose(infile);
fclose(outfile);
return 0;
}
Header file:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.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 – you will compute!
} Employee;
#endif
payroll.txt, scanning this 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
outputing to paid.txt:
total: $8098405204118553210089249756384123022462475737784054204141978203412550137716411406580975068756992904139218004071573362835456.00
average: $0.000
MAx: $0.000
Min: $0.00
problem is I wasn't expecting it to print out the total that much and the average, max, and min are all 0s.
CodePudding user response:
Off topic, but...
Why do you want to "bulk-up" your code with copy/paste/adapt of codeblocks?
All of this:
if (payroll[i].title == 'B') {
if (payroll[i].hours_worked > 40) {
payroll[i].payment = 40 * payroll[i].payrate;
payroll[i].payment = (1.5 * payroll[i].payrate * (payroll[i].hours_worked - 40));
}
else
payroll[i].payment = payroll[i].hours_worked * payroll[i].payrate;
}
else {
if (payroll[i].hours_worked > 40) {
payroll[i].payment = 40 * payroll[i].payrate;
payroll[i].payment = (1.8 * payroll[i].payrate * (payroll[i].hours_worked - 40));
}
else
}
exists only to use ONE different constant multiplier. It can be reduced to:
Employee *e = payroll i;
e->payment = e->hours_worked * e->payrate;
if (e->hours_worked > 40)
e->payment = (e->title == 'B') ? 0.5 : 0.8 * e->payrate * (e->hours_worked - 40);
Employees are paid their standard rate for all hours worked.
Overtime hours (above 40) are paid at the appropriate overtime rate.
Write less, but more effective, code.
The reader shouldn't be forced to scan large blocks of duplicate code trying to spot the tiny difference(s) between them.
(In fact, the calculation should be factored-out into a separate function, isolating that calculation from the "flow" of reading records and tabulating other values.)
CodePudding user response:
many many errors (your compiler should have warned you about at least some of them)
fscanf(infile, "%s", &payroll[i].name) )
do not pass a pointer to the string for %s , should be
fscanf(infile, "%s", payroll[i].name) )
use %c for a char , so this
fscanf(infile, "%s", &payroll[i].title);
should be
fscanf(infile, " %c", &payroll[i].title);
notice the leading space to eat up the crlf in the buffer
fscanf(infile, "%s", &payroll[i].hours_worked);
you use %s here to say you want a string , but read it into a double, same on next like, should be
fscanf(infile, "%lf", &payroll[i].hours_worked);
here
fprintf(outfile, "total: $%.2lf\n average: $%.2lf\nMAx: $%.2lf\n Min: $%.2lf", total, average, max, min);
you output ints using %lf, should be
fprintf(outfile, "total: $%.2lf\n average: $%d\nMAx: $%d\n Min: $%d", total, average, max, min);
always test the return value of functions , especially io (fscanf)
also read this about while !eof
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
next, when readin a string using %s fscanf
reads up to the first whitespace
so this
if (fscanf(infile, "%s", payroll[i].name) == NULL)
break;
when fed
Smith, Susan
(note the space after the ',') actually reads
"Smith,"
into the name
the next read (of a char) picks up 'S', and then the read of doubles tries to read 'mith', that wont work.
You should use fgets
instead, that read the whole line
if (fgets(payroll[i].name, 100, infile) == NULL)
break;
note the change to correctly detect eof (I have while(1)
for the loop)
also need to add fgetc(infile)
after the last double read in order to eat up the cr lf before the next fgets
now get
total: $1283.34
average: $320
MAx: $5360
Min: $1283