/*
 * This program reads student data from a specified input file.
 * Each student has a last name, first name, homework scores,
 * one test score, and ultimately a weighted average.
 * After computing the average for each student, the program
 * displays the names and averages to a specified output file.
 *
 * Written by: Carl Sable
 */

#include <stdio.h>
#include <stdlib.h>

#define NUM_HW 3
#define TEST_PCT 0.4

struct student
{
  char lastname[50];        // student's lat name
  char firstname[50];       // student's first name
  int homeworks[NUM_HW];    // scores on homeworks
  int test;                 // score on test
  float ave;                // final average
};

typedef struct student STUDENT;

STUDENT *input_students(char *, int *);
void compute_averages(STUDENT [], int);
int display_students(char *, STUDENT [], int);

int main(void)
{
  STUDENT *pStudents;
  char inputFile[50], outputFile[50];
  int numStudents;
  int writeFailed;

  // Prompt use for input file name
  printf("Enter name of input file: ");
  scanf("%49s", inputFile);
  while (getchar() != '\n'); // clear input buffer

  // Read the input data from the file
  pStudents = input_students(inputFile, &numStudents);
  if (pStudents == NULL)
  {
    fprintf(stderr, "Error: Did not successfully read student data.\n");
    exit(1);
  }

  // Compute the student averages
  compute_averages(pStudents, numStudents);

  // Prompt use for input file name
  printf("Enter name of output file: ");
  scanf("%49s", outputFile);
  while (getchar() != '\n');

  // Create the output file
  writeFailed = display_students(outputFile, pStudents, numStudents);
  if (writeFailed)
  {
    fprintf(stderr, "Error: Did not successfully write student data.\n");
    exit(1);
  }

  return 0;
}

/*
 * Read student data from input file.
 * Fill in the number of students (first line of file).
 *
 * Return pointer to dynamically allocated student array,
 * or NULL if there is an error.
 */
STUDENT *input_students(char *fnInput, int *numStudents)
{
  int x, y;
  FILE *fpInput;
  STUDENT *arrStud;
  
  fpInput = fopen(fnInput, "r");
  if (fpInput == NULL) // error opening file
    return NULL;

  // Top row of file indicats number of students
  fscanf(fpInput, "%d", numStudents);

  // Dynamically allocate student array
  arrStud = (STUDENT *) malloc(sizeof(STUDENT) * (*numStudents));

  // Input information about students
  for (x = 0; x < *numStudents; x++)
  {
    fscanf(fpInput, "%49s", arrStud[x].lastname);
    fscanf(fpInput, "%49s", arrStud[x].firstname);
    for (y = 0; y < NUM_HW; y++)
      fscanf(fpInput, "%d", &arrStud[x].homeworks[y]);
    fscanf(fpInput, "%d", &arrStud[x].test);
  }

  return arrStud;

  fclose(fpInput);
}

/*
 * Computes final average for each student.
 * Assumes all homeworks are weighted equally.
 */
void compute_averages(STUDENT arrStud [], int numStudents)
{
  int x, y;
  int h_tot;

  for (x = 0; x < numStudents; x++)
  {
    h_tot = 0;
    for (y = 0; y < NUM_HW; y++)
      h_tot = h_tot + arrStud[x].homeworks[y];
		
    arrStud[x].ave = ((1 - TEST_PCT) * h_tot / NUM_HW +
			TEST_PCT * arrStud[x].test);
  }

  return;
}

/*
 * Displays name and final average of each student to output file.
 *
 * Returns 1 if error, 0 otherwise.
 */
int display_students(char *fnOutput, STUDENT arrStud[], int numStudents)
{
  FILE *fpOutput;
  int x;
  
  fpOutput = fopen(fnOutput, "w");
  if (fpOutput == NULL) // error opening file
    return 1;

  for (x = 0; x < numStudents; x++)
    {
      fprintf(fpOutput, "Student #%d:\n", x+1);
      fprintf(fpOutput, "\tName: %s, %s\n",
	      arrStud[x].lastname, arrStud[x].firstname);
      fprintf(fpOutput, "\tFinal Average: %.1f\n", arrStud[x].ave);
    }

  fclose(fpOutput);

  return 0;
}
