Summary : Write a program that determines letter grades for students in a class,
ID: 3738297 • Letter: S
Question
Summary : Write a program that determines letter grades for students in a class, using control flow, arrays, pointers, structures, disk files, and error conditions in C Programming.
Description : Program accepts two command line arguments.The first argument is the name of a disk file that contains the names of students, and their scores, separated by commas, followed by one or more spaces. Each line contains score for one student. The second argument is the name of an output disk file. The program creates a new output file using that name. Write the grade information of all student whose information was read from the input file in a sorted order into the output file. Write one line per student in the output file. Write the name of a student and the letter grade they received in a formatted style in an output file. The format of data in the input file is fixed but the number of student at the compiling time is unknown. Name of input and output file could be anything and only known during the compiling time. Besides writing to output file, display the average scores along the minimum and maximum scores for each test in the screen.
Calculation: The test scores are weighed. There are 4 quizzes, 40% total, midterm 1 is 20%, midterm 2 is 15% and the final is 25%. All scores in the input file are recorded out of 100. You need to apply the weight for each score in the program to calculate the final score. The final score is tabulated as follows:
Final Score = (quiz1 * .10) + (quiz2 * .10) + (quiz3 * .10) + (quiz4 * .10) + (midterm1 * 0.20) + (midterm2 * 0.15) + (final * 0.25)
Determination of letter grade is according to the following logic:
Final Score >= 90% then letter grade is A, 80% - 89% B, 70% - 79% C, 60% - 69% D, <= 59% F
Sample input data file: input_data.txt (the input data format is: name, quiz1, quiz2, quiz3, quiz4, midterm1, midterm2, final) E.g.:
Thui Bhu, 100, 90, 80, 100, 89, 99, 88
Ariana B. Smith, 90, 90, 100, 100, 99, 100, 95
Emily Gonzales, 100, 90, 100, 70, 78, 78, 80
Jennifer L, 80, 90, 90, 100, 89, 99, 85
Maria Jones, 65, 72, 77, 68, 62, 70, 65
Bill Gates, 60, 54, 38, 62, 65, 60, 50
Escobar Morris, 83, 77, 88, 76, 79, 72, 76
Anne Latner, 80, 80, 85, 95, 90, 95, 90
...
<<more if there are more students>>
Sample output data file: output_data.txt (the input data format is: Name: letter grade, sorted by full name "first name + middle initial + last name") E.g.:
Letter grade for 8 students given in input_data.txt file is:
Anne Lather: B
Ariana B. Smith: A
Bill Gates: F
Emily Gonzales: B
Escobar Morris: C
Jennifer L: B
Maria Jones: D
Thui Bhu: A
...
<<more if there are more students>>
Sample Run of the program (name of your program is Lettergrader): Remember that there are two sets of outputs. Letter grade is written into the output disk file (which is not shown on the screen), only score averages are displayed on the screen (and are not written into the disk file).
Example Run 1:
C:>lettergrader input_data.txt output.data.txt
Letter grade has been calculated for 8 students listed in input file input.data.txt and are written to output file output_data.txt
Here is the class averages:
Q1 Q2 Q3 Q4 Mid1 Mid2 Final
Average: 82.25 80.38 82.25 83.88 81.38 84.13 78.63
Minimum: 60 54 38 62 62 60 50
Maximum: 100 90 100 100 99 100 95
Press any key to continue ...
C:>_
Example Run 2 (it will have different set of data and so will be the output):
C:>lettergrader data1.txt data2.txt
Letter grade has been calculated for 20 students listed in input file data1.txt and are written to output file data2.txt
Here is the class averages:
Q1 Q2 Q3 Q4 Mid1 Mid2 Final
Average: 85.21 88.32 84.89 85.88 90.38 74.23 77.73
Minimum: 90 60 50 78 70 80 76
Maximum: 100 95 100 100 100 98 95
Press any key to continue ...
C:>_
Note:
1) You will be able to run this application with your choice of IDE as well, including Visual Studio by providing command line arguments in the settings. All IDEs allow you to enter the command line arguments.
2) The disk output for different input file will be different, however, the format of the output should be similar as shown in the example above (output_data.txt)
Design Hint: Here is a guide to make it modular design:
1) Storing data into memory using suitable data structures will help you write code, which will be modular. You then need to calculate the averages by going through all the data for each test score for all the students and divide by the number of students.
2) You are free to use any data structures you want. Parallel arrays for all the scores is one easy way (assuming that maximum number of students to be 100).
3) Assume, first name do not exceed 40 chars and last name 60 chars. Names may have middle initial (with a period). Data elements will be coma separated with unknown number of spaces after comma.
4) If you want to explore pointers, then a linked list would be the best choice. This is especially helpful, as you do not know how many student records are in the input file until you have read all the data in it.
5) If you assume 100 to be the maximum number of students, as long as make sure to calculate the average using the actual number of students during run time.
Submission requirement: You can write your application spread out in multiple .c and .h files. Remember that there is only one main in any application, even if you have multiple .c and .h files for that application. Follow this naming convention for your files: If functions are written separate file then give it a name: utility_johndoe.c file and then write a driver program as testlettergrader_johndoe.c file which uses functions from utility file, by replacing johndoe with your name.
I do NOT need your test data files, I will write my own data and will compile and run your code using my data file with different names. Your code needs to handle the sample data shown above. You can be certain that the data file will not have junk and it will have correct data.
It is better to have a code: well formated, commented. Understanding code is easy. It has good error trapping as well. Classes are designed following what was covered in lectures with the use of classses, inheritance, and/or interface. All instance variables are declared private, methods are private as well with only few declared public.
Explanation / Answer
//TestLetterGrade.c
#include <stdio.h>
#include "utility.h"
int main(int argc, char *argv[])
{
//Create an array of structures
struct info studentInfo[100] = {0};
//Create a structure to hold the total scores of each quiz/test
struct data total = {0};
//Create a structure to hold the max scores of each quiz/test
struct data max = {0};
//Create a structure to hold the min scores of each quiz/test
struct data min = {100, 100, 100, 100, 100, 100, 100};
FILE *pClassInfo; //File pointer for input file
FILE *pOutput; //File pointer for output file
int count = 0; //Create a counter to account for the amount of records taken from input
if (argc != 3)
{
printf(" Error, need the following file usage: %s inputFileName outputFileName ", argv[0]);
exit(1);
}
else
{
printf(" Input will be read from: %s ", argv[1]);
printf("Output will be written into: %s ", argv[2]);
}
//Open the input file..
if ((pClassInfo = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s. ", argv[1]);
exit(1);
}
//studentInfo does not need the & operator because it is an array (of structures)
//gatherInput() returns the number of students in the class
count = gatherInput(pClassInfo, studentInfo);
calculateClassStats(count, &total, &max, &min, studentInfo);
//Open the output file
if ((pOutput = fopen(argv[2], "w")) == NULL)
{
printf("Can't open %s. ", argv[2]);
exit(1);
}
//Sort the class results that will be printed to the output file.
qsort(studentInfo, count, sizeof(struct info), myComp);
calculateGrades(count, studentInfo);
printToOutputFile(pOutput, count, studentInfo);
showClassData(count, &total, &max, &min);
//Close the files
fclose(pClassInfo);
fclose(pOutput);
return 0;
}
---------------------------------------------------------------------------------
//utility.c
#include <printf.h>
#include <memory.h>
#include "utility.h"
//Function: gatherInput
int gatherInput(FILE *fp, struct info *pStruct)
{
int i = 0;
char pInBuffer[MAXLINE];
//Place the file position pointer at the start of the file.
rewind(fp);
while (i < 100 && (fgets(pInBuffer, MAXLINE, fp)) != NULL)
{
//%[^, ] means read every character in the string until ',' or ' ' is found
sscanf(pInBuffer, "%[^, ], %d, %d, %d, %d, %d, %d, %d", pStruct[i].name,
&pStruct[i].quiz1, &pStruct[i].quiz2, &pStruct[i].quiz3,
&pStruct[i].quiz4, &pStruct[i].mid1, &pStruct[i].mid2,
&pStruct[i].final);
//Check for invalid scores
if ((pStruct[i].quiz1 > 100 || pStruct[i].quiz1 < 0) ||
(pStruct[i].quiz2 > 100 || pStruct[i].quiz2 < 0) ||
(pStruct[i].quiz3 > 100 || pStruct[i].quiz3 < 0) ||
(pStruct[i].quiz4 > 100 || pStruct[i].quiz4 < 0) ||
(pStruct[i].mid1 > 100 || pStruct[i].mid1 < 0) ||
(pStruct[i].mid2 > 100 || pStruct[i].mid2 < 0) ||
(pStruct[i].final > 100 || pStruct[i].final < 0))
{
printf("Invalid score in row %d for %s. ", i+1, pStruct[i].name);
exit(1);
}
//Each loop cycle is recorded to calculate the number of students in the class
i++;
}
//Return the number of students in the class
return i;
}
//Function: calculateClassStats
void calculateClassStats(int numStudents, struct data *pTotal, struct data *pMax, struct data *pMin, struct info *pStudents)
{
int i = 0;
//Calculate total for each quiz/test
//This will be used to print the average to the console
for (i = 0; i < numStudents; i++)
{
pTotal->quiz1 += pStudents[i].quiz1;
pTotal->quiz2 += pStudents[i].quiz2;
pTotal->quiz3 += pStudents[i].quiz3;
pTotal->quiz4 += pStudents[i].quiz4;
pTotal->mid1 += pStudents[i].mid1;
pTotal->mid2 += pStudents[i].mid2;
pTotal->final += pStudents[i].final;
}
//Calculate the max for each quiz/test
//This will be used to print the maximum scores to the console
for (i = 0; i < numStudents; i++)
{
if(pStudents[i].quiz1 > pMax->quiz1)
pMax->quiz1 = pStudents[i].quiz1;
if(pStudents[i].quiz2 > pMax->quiz2)
pMax->quiz2 = pStudents[i].quiz2;
if(pStudents[i].quiz3 > pMax->quiz3)
pMax->quiz3 = pStudents[i].quiz3;
if(pStudents[i].quiz4 > pMax->quiz4)
pMax->quiz4 = pStudents[i].quiz4;
if(pStudents[i].mid1 > pMax->mid1)
pMax->mid1 = pStudents[i].mid1;
if(pStudents[i].mid2 > pMax->mid2)
pMax->mid2 = pStudents[i].mid2;
if(pStudents[i].final > pMax->final)
pMax->final = pStudents[i].final;
}
//Calculate the min for each quiz/test
//This will be used to print the minimum scores to the console
for (i = 0; i < numStudents; i++)
{
if(pStudents[i].quiz1 < pMin->quiz1)
pMin->quiz1 = pStudents[i].quiz1;
if(pStudents[i].quiz2 < pMin->quiz2)
pMin->quiz2 = pStudents[i].quiz2;
if(pStudents[i].quiz3 < pMin->quiz3)
pMin->quiz3 = pStudents[i].quiz3;
if(pStudents[i].quiz4 < pMin->quiz4)
pMin->quiz4 = pStudents[i].quiz4;
if(pStudents[i].mid1 < pMin->mid1)
pMin->mid1 = pStudents[i].mid1;
if(pStudents[i].mid2 < pMin->mid2)
pMin->mid2 = pStudents[i].mid2;
if(pStudents[i].final < pMin->final)
pMin->final = pStudents[i].final;
}
}
//Function: calculateGrades
void calculateGrades(int numStudents, struct info *pStudents)
{
int i = 0;
//Determine each student's overall score in the class
for (i = 0; i < numStudents; i++)
{
pStudents[i].classScore = (.10)*(pStudents[i].quiz1 + pStudents[i].quiz2 + pStudents[i].quiz3 + pStudents[i].quiz4)
+ (.20)*pStudents[i].mid1 + (.15)*pStudents[i].mid2
+ (.25)*pStudents[i].final;
}
//Determine letter grades
for (i = 0; i < numStudents; i++)
{
if (pStudents[i].classScore >= 90)
pStudents[i].letterGrade = 'A';
else if (pStudents[i].classScore >= 80 && pStudents[i].classScore < 90)
pStudents[i].letterGrade = 'B';
else if (pStudents[i].classScore >= 70 && pStudents[i].classScore < 80)
pStudents[i].letterGrade = 'C';
else if (pStudents[i].classScore >= 60 && pStudents[i].classScore < 70)
pStudents[i].letterGrade = 'D';
else
pStudents[i].letterGrade = 'F';
}
}
//Function: printToOutputFile
void printToOutputFile(FILE *pOut, int numStudents, struct info *pStudents)
{
int i = 0;
//Append a colon to the end of each name
for (i = 0; i < numStudents; i++)
{
int len = strlen(pStudents[i].name);
pStudents[i].name[len] = ':';
pStudents[i].name[len+1] = '';
}
//Place names and grades into output file
for (i = 0; i < numStudents; i++)
{
fprintf(pOut, "%-25s %c ", pStudents[i].name, pStudents[i].letterGrade);
}
}
//Function: showClassData
void showClassData(int numStudents, const struct data *pTotal, struct data *pMax, struct data *pMin)
{
//Console class data output formatting
printf("Here are the class averages: ");
printf(" Q1 Q2 Q3 Q4 Mid1 Mid2 Final ");
//Print average for each quiz or test
printf("Average: %5.2lf %5.2lf %5.2lf %5.2lf %5.2lf %5.2lf %5.2lf ",
(double)pTotal->quiz1/numStudents, (double)pTotal->quiz2/numStudents, (double)pTotal->quiz3/numStudents,
(double)pTotal->quiz4/numStudents, (double)pTotal->mid1/numStudents, (double)pTotal->mid2/numStudents,
(double)pTotal->final/numStudents);
//Print maximum scores
printf("Maximum: %d %d %d %d %d %d %d ",
pMax->quiz1, pMax->quiz2, pMax->quiz3,
pMax->quiz4, pMax->mid1, pMax->mid2,
pMax->final);
//Print minimum scores
printf("Minimum: %d %d %d %d %d %d %d ",
pMin->quiz1, pMin->quiz2, pMin->quiz3,
pMin->quiz4, pMin->mid1, pMin->mid2,
pMin->final);
printf(" ");
}
//Function: myComp
int myComp(const void *p1, const void *p2)
{
struct info *a1 = (struct info *) p1;
struct info *a2 = (struct info *) p2;
return strcmp(a1->name, a2->name);
}
-----------------------------------------------------------------------
//utility.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef _UTILITY_KEVINGEISZLER__H
#define _UTILITY_KEVINGEISZLER__H
#define MAX 40
#define MAXLINE 256
struct info {
char name[MAX];
int quiz1;
int quiz2;
int quiz3;
int quiz4;
int mid1;
int mid2;
int final;
int classScore;
char letterGrade;
};
//Create a structure to hold overall records for the class
struct data {
int quiz1;
int quiz2;
int quiz3;
int quiz4;
int mid1;
int mid2;
int final;
};
//Function prototypes
int gatherInput(FILE *fp, struct info *pStruct);
void calculateClassStats(int numStudents, struct data *pTotal, struct data *pMax, struct data *pMin, struct info *pStudents);
void calculateGrades(int numStudents, struct info *pStudents);
void printToOutputFile(FILE *pOut, int numStudents, struct info *pStudents);
void showClassData(int numStudents, const struct data *pTotal, struct data *pMax, struct data *pMin);
int myComp(const void *p1, const void *p2);
#endif
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.