-1

Try as I might to solve this riddle, I think I'm losing my mind! Can anyone help understand why this program crashes when I run through the loop a 2nd time?

I can run through the interactive loop one time and have the values entered written to a file. However, when I attempt to pass through the a loop a 2nd time, the program chokes.

// C Libraries Used

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

// Constant definitions

const float OTPAYFACTOR = 1.5;
const float REGWORKWKHRS = 40;
FILE *payfile;                // report file (for output)

// Variable declerations
char deptname [21];
char firstname [10];
char lastname [10];
char fullname [47];
float hrsworked;
float hrwage;
float reghrsworked;
float othrsworked;
float otwage;
float grosswage;
int count;
char again;

// Function Prototypes

//**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~
// M A I N   F U N C T I O N
//**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~**~~

int main (void){
    payfile = fopen("c:\\class\\mod6\\ethan-pay.txt","w");     // Open disk file
    printf("Mountain Pacific Corporation\nDepartment Salary Program\n\n");
    printf("Please enter the name of the department: ");
    scanf("%s", deptname);
    count = 0;    // Initialize this "counting" variable to zero to start
    printf("%s", deptname);
    printf("\n");
do {

      printf("Enter employee #%d: ", count+1);
      scanf("%s %s", firstname, lastname);
      fscanf(payfile,"%s %s", firstname, lastname);
      strcpy(fullname, firstname);
      strcat(fullname, " ");
      strcat(fullname, lastname);
      printf("Enter the hourly wage of %s: ", fullname);
      scanf("%f", &hrwage);
      fscanf(payfile,"%f", &hrwage);
      printf("Enter total number of hours: ");
      scanf("%f", &hrsworked);
      fscanf(payfile,"%f", &hrsworked);

    if (hrsworked <= REGWORKWKHRS){     //
        reghrsworked = hrsworked;
        othrsworked = 0;
        otwage = hrwage * OTPAYFACTOR;
        grosswage = hrwage*reghrsworked;
    }
        else{

            reghrsworked = REGWORKWKHRS;
            othrsworked = hrsworked - REGWORKWKHRS;
            otwage = hrwage * OTPAYFACTOR;
            grosswage = (reghrsworked * hrwage) + (othrsworked * otwage);
        }
       fprintf(payfile,"%-22s%0.1f ($%0.2f) %6.1f ($%0.2f) $%-4.2f\n", fullname, reghrsworked, hrwage, othrsworked, otwage, grosswage);
       printf("\nThank you. Process another employee? ");
       scanf ("%s", &again);
       printf("\n");

       count++; // Increment the counting variable


} while (again == 'Y'|| again == 'y' || again != 'N' && again != 'n');


      printf("End of processing.\n");

    fclose(payfile);
return 0;
}
davidw
  • 45
  • 7
  • `again` is a `char`, so you should use `scanf ("%c", &again);`. Also, `... } while (again == 'Y' || again == 'y'); ...` would be enough. – Bob__ Nov 12 '17 at 22:39
  • What did your debugger say? – melpomene Nov 12 '17 at 22:42
  • 1
    Please note that all your variables are global for no valid reson and that you should always check the return values of `fopen`, `scanf` and `fscanf`, which you are using, but I can't understand why. Shouldn't you have to write the data read from stdin to the file? – Bob__ Nov 12 '17 at 22:48
  • 1
    thx for yours comment that tell me that it's the main function, it was very useful for understand your code ;) – Stargateur Nov 12 '17 at 23:12
  • What do you mean by "chokes"? Error message? Why are you reading from the file? firstname and lastname are only 10 chars, with terminator that limits you to 9 chars, fullname is declared as length 47 which is largely going to be unused but you may as well just output first/last separately to the file vs copying to another buffer first. You should really be guarding against buffer overruns everywhere (strncpy vs strcpy, also see https://stackoverflow.com/questions/1621394/how-to-prevent-scanf-causing-a-buffer-overflow-in-c). – Greg H Nov 13 '17 at 00:07

1 Answers1

2

I don't understand why are you scanning your file that you use for save the result:

scanf("%s %s", firstname, lastname);
fscanf(payfile,"%s %s", firstname, lastname);
// ...
scanf("%f", &hrwage);
fscanf(payfile,"%f", &hrwage);
// ...
scanf("%f", &hrsworked);
fscanf(payfile,"%f", &hrsworked);

What you do erase previous value. Just remove all call to fscanf().

I strongly advice you to change your code practice, global should be avoid, only declare variable when you need them, don't ignore error code from function, provide to scanf() the max size that it can use, etc...

example probably not perfect:

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

#define OTPAYFACTOR 1.5
#define REGWORKWKHRS 40

int main(void) {
  printf("Mountain Pacific Corporation\nDepartment Salary Program\n\n"
         "Please enter the name of the department: ");
  char deptname[21];
  if (scanf("%20s", deptname) != 1) {
    return 1;
  }
  printf("%s\n", deptname);

  FILE *payfile = fopen("c:\\class\\mod6\\ethan-pay.txt", "w");
  if (!payfile) {
    return 1;
  }
  for (int count = 0;; count++) {
    printf("Enter employee #%d: ", count + 1);
    char firstname[10];
    char lastname[10];
    if (scanf("%9s %9s", firstname, lastname) != 2) {
      return 1;
    }
    char fullname[19];
    sprintf(fullname, "%s %s", firstname, lastname);
    printf("Enter the hourly wage of %s: ", fullname);
    float hrwage;
    if (scanf("%f", &hrwage) != 1) {
      return 1;
    }
    printf("Enter total number of hours: ");
    float hrsworked;
    if (scanf("%f", &hrsworked) != 1) {
      return 1;
    }
    if (hrsworked <= REGWORKWKHRS) {
      float reghrsworked = hrsworked;
      float othrsworked = 0;
      float otwage = hrwage * OTPAYFACTOR;
      float grosswage = hrwage * reghrsworked;
      fprintf(stdout, "%-22s%0.1f ($%0.2f) %6.1f ($%0.2f) $%-4.2f\n", fullname,
              reghrsworked, hrwage, othrsworked, otwage, grosswage);
    } else {
      float reghrsworked = REGWORKWKHRS;
      float othrsworked = hrsworked - REGWORKWKHRS;
      float otwage = hrwage * OTPAYFACTOR;
      float grosswage = (reghrsworked * hrwage) + (othrsworked * otwage);
      fprintf(stdout, "%-22s%0.1f ($%0.2f) %6.1f ($%0.2f) $%-4.2f\n", fullname,
              reghrsworked, hrwage, othrsworked, otwage, grosswage);
    }

    printf("\nThank you. Process another employee? ");
    char again;
    if (scanf(" %c", &again) != 1) {
      return 1;
    }
    if (again != 'Y' && again != 'y') {
      break;
    }
    printf("\n");
  }
  fclose(payfile);
  printf("End of processing.\n");
}

example input:

jurasickpark
sarah connor 5 42
y
bob lennon 9 12
n

output file:

sarah connor          40.0 ($5.00)    2.0 ($7.50) $215.00
bob lennon            12.0 ($9.00)    0.0 ($13.50) $108.00
Stargateur
  • 24,473
  • 8
  • 65
  • 91