[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3907
  • Last Modified:

Want to find the highest score per student. Also want average with 2 decimal places

Hi,
I have my program working to read an input file and print it out, add three test scores together and find the average, and then print out the records with a letter grade assigned. I now have to put together a function that finds the highest test score for each stuident. I also would like to print the average with 2 decimal places. I currently get an int with no decimal places. Can someone provide some directrion as to how I would approach these tasks? The input file is below:

Jon                 Schab                96 100 94
David               Jones                94 88  100
Paul                Stevens             88 77  95
Sam                 Waters              77 77  79
Mike                Smith                  69 82  73
Joseph              Mantas             84 84  85
Mary                Sheth                 80 90  91
Susan               Smith                98 100 100
Terry               Bradshaw          89 88  87
Dan                 Marino                75 77  78

The program:

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>


using namespace std;



struct studentType
{
    string studentFName;
    string studentLName;
      int testScore;
      int testScore2;
      int testScore3;
      string grade;
};


void readfile(studentType student[10])
{
            int x = 0;
              ifstream infile;

            char filename[]= "students.txt";
       
        infile.open(filename);

        if (infile.fail())
        {
                cout << "File doesn't exist" << endl;
                exit(0);
        }

     while( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore >> 
               student[x].testScore2 >> student[x].testScore3;
       x++;
       }
     
        infile.close();
}


void printfile(studentType* student)
{
      cout << "Entire Input File" << endl << endl;

    for (int i=0;i<10;i++)
            {
            cout << student[i].studentLName << "," << " ";
        cout << student[i].studentFName  << " ";
        cout << student[i].testScore        << " ";
            cout << student[i].testScore2        << " ";
            cout << student[i].testScore3        << " ";
        cout << student[i].grade        << " " << endl;
            }
            cout << endl;
}

void calcgrade(studentType* student)
{
      double average;
      char grade;
      cout << "Students and Grades" << endl << endl;

    for (int i=0;i<10;i++)
            {
        average = ((student[i].testScore + student[i].testScore2 + student[i].testScore3) / 3);
            
             // convert score to letter grade
                  if (average > 89)
                  grade = 'A';
                  else if (average > 79)
                  grade = 'B';
                  else if (average > 69)
                  grade = 'C';
                  else if (average > 59)
                  grade = 'D';
                  else
                  grade = 'F';
   
            
            // print out student grade line
    cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << student[i].testScore <<
                  " " << student[i].testScore2 << " " << student[i].testScore3 << " " << grade << endl;

            }
}

int main()
{
    studentType student[10];
      readfile(student);
      printfile(student);
      calcgrade(student);
}

0
ghost8067
Asked:
ghost8067
  • 17
  • 9
  • 2
  • +1
1 Solution
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi ghost8067,

This one's a very typical thing to do with one' programming skills.  Fortunately, it's also pretty easy.  :)

Right before your print the student's id and scores, find the highest score.  This is just a couple of lines.

  HighScore = Score1 > Score2 ? Score1 : Score 2;   //  Select the higher of the first two scores
  HighScore = HighScore > Score3 ? HighScore : Score3;  // Check to see if Score3 is higher than the other two.

There are LOTS of ways to write those two lines.  You can write them as a single line with mutliple compares.  You can write them as nested if statements.  You can sort a list and take the top value, etc.

Regarding the average, you'll want to compute the average as a floating point type, not an integer type.  In general, C takes the data type of the first operand in an expression and recasts the other items to be that same type.  If you'll cast the value to be a floating point before you divide, you'll get a real (not integer) value.


  float Average;

  Average = ((float)(Score1 + Score2 + Score3) / 3;


Good Luck,
Kent
0
 
adymonoCommented:
to get the average

you use

 average = ((student[i].testScore + student[i].testScore2 + student[i].testScore3) / 3);

try instead something like

average = ((double)(student[i].testScore + student[i].testScore2 + student[i].testScore3) / 3);

or
average = ((student[i].testScore + student[i].testScore2 + student[i].testScore3) / 3.0);

0
 
adymonoCommented:
sorry kdo... didn't refresh on time...
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
itsmeandnobodyelseCommented:
>>>> I now have to put together a function that finds the
>>>> highest test score for each stuident

You could make it a member function of struct studentType:

struct studentType
{
    string studentFName;
    string studentLName;
      int testScore;
      int testScore2;
      int testScore3;
      string grade;

      int getHighScore();
};

The implementation was shown by Kent.

You would use it in the output statement like

    cout << student[i].studentLName << "," << " " << student[i].studentFName << " " 
            << student[i].testScore << " " << student[i].testScore2 << " " 
            << student[i].testScore3 << " " << grade << " "
            << student[i].getHighScore() << endl;


If you can't make it a member function, you should pass the studentType by reference:

   int getHighScore(studentType& st)
   {
         if (st.testScore > st.testScore2 && st.testScore > st.testScore2)
              return st.testScore;
         else if (...
              ...
   }

The last line of the output line would turn to

            << getHighScore(student[i]) << endl;


The average function can be made accordingly. Don't forget to cast to a double (or assign to a double)  before dividing as adymono showed. Else you would get an integer division which rounds all digits after decimal point.

Regards, Alex

0
 
itsmeandnobodyelseCommented:
>>>> I also would like to print the average with 2 decimal places.

cout << fixed << setprecision(2) << double_variable;

The 'fixed' specifies that you want a fixed number of decimal places while the setprecision(2) defines 2 places after the decimal point if 'fixed'. In 'scientific' notation setprecision would specify the number of significant digits.
0
 
ghost8067Author Commented:
I have all of that working now. Excellent help. Now, one more wrench. I am printing those high scores from the same function where I find the hoghest scores. The last requirement (in addition to the menu I will build), is that the print of the student name and high score be printed from a separate function called from main. Can you give me some direction?

Thanks!!

Code is below:

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>
#include <cmath>


using namespace std;



struct studentType
{
    string studentFName;
    string studentLName;
      int testScore;
      int testScore2;
      int testScore3;
      string grade;
};


void readfile(studentType student[10])
{
            int x = 0;
              ifstream infile;

            char filename[]= "students.txt";
       
        infile.open(filename);

        if (infile.fail())
        {
                cout << "File doesn't exist" << endl;
                exit(0);
        }

     while( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore >> 
               student[x].testScore2 >> student[x].testScore3;
       x++;
       }
     
        infile.close();
}


void printfile(studentType* student)
{
      cout << "Entire Input File" << endl << endl;

    for (int i=0;i<10;i++)
            {
            cout << student[i].studentLName << "," << " ";
        cout << student[i].studentFName  << " ";
        cout << student[i].testScore        << " ";
            cout << student[i].testScore2        << " ";
            cout << student[i].testScore3        << " ";
        cout << student[i].grade        << " " << endl;
            }
            cout << endl;
}

void calcgrade(studentType* student)
{
      double average;
      char grade;
      cout << "Students and Grades" << endl << endl;

    for (int i=0;i<10;i++)
            {
        average = ((student[i].testScore + student[i].testScore2 + student[i].testScore3) / 3.0);

            
             // convert score to letter grade
                  if (average > 89)
                  grade = 'A';
                  else if (average > 79)
                  grade = 'B';
                  else if (average > 69)
                  grade = 'C';
                  else if (average > 59)
                  grade = 'D';
                  else
                  grade = 'F';
   
            
            // print out student grade line
    cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << student[i].testScore <<
                  " " << student[i].testScore2 << " " << student[i].testScore3 << " " << fixed << setprecision(2) << average << " " << grade << endl;

            }
}

void highestScore(studentType* student)
{
      int HighScore;
      cout << endl;
      cout << "Highest Score For Each Student" << endl << endl;

    for (int i=0;i<10;i++)
            {
        HighScore = student[i].testScore > student[i].testScore2 ? student[i].testScore : student[i].testScore2;   //  Select the higher of the first two scores
            HighScore = HighScore > student[i].testScore3 ? HighScore : student[i].testScore3;
            
            // print out student grade line
            cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << HighScore << endl;
            }
}

int main()
{
    studentType student[10];
      readfile(student);
      printfile(student);
      calcgrade(student);
      highestScore(student);
}
0
 
itsmeandnobodyelseCommented:
>>>> Can you give me some direction?
as far as I see you already implemented it correctly. Does anything go wrong?

Some remarks on your prog. Not because it was wrong but because to make it perfect:

1. don't call exit(..) from helper functions.

Instead return a bool true or false. You may later use a helper 'just to test' whether there are values available or a file is available in some folder and maybe want to search at another location if it fails. You won't be able to do so, if the function exits.

For all functions that may fail your main would turn to

int main()
{
      ...
      if (!readfile(student))
      {
           return 1;  
      }
       ...

2. When passing an array always pass the number of items
    as a second (or additional) argument.

That makes it easy to change the number of items at one single point or change to a dynamically allocated array.

3. Make highscore and average a member function of studentType.

That way you can use it like the data members (beside of the parantheses) and may not calculate it explicitly in a loop.

Regards, Alex
0
 
ghost8067Author Commented:
No, nothing is wrong, it is just that my instructor was specific that there be 2 separate functions dealing highest score. One to calculate, and one to do the printing. An additional requirement is that there be nothing in main but function calls. The assignment is below:

1. Write a program that reads students names followed by their test scores. The program
should output each students name followed by the test scores and the relevant grade. It
should also find and print the highest test score and the name of the students having
the highest test score.
Student data should be stored in a struct variable of the type studentType, which
has four components: studentFName and studentLName of the type string,
testScore of the type int (testScore is between 0 and 100), and grade of the
type string. Suppose that the class has 10 students. Use an array of 10 components of
the type studentType.
Your program must contain at least the following functions:
a. A function to read the students data into the array. (file or user input, prefer file)
b. A function to assign the relevant grade to each student. (Calculate the grade)
c. A function to find the highest test score.
d. A function to print the names of the students having the highest test score.
Your program must output each students name in this form: last name followed by
a comma, followed by a space, followed by the first name, and the name must be left justified.
Moreover, other than declaring the variables and opening the input and output
files, the function main should only be a collection of function calls.

I also would like to try to add headings for each of the prints. I can do that, but I am having trouble with the formatting. Since I have the requiement for the format of first name, last name, if I try to use a tab the scores don;t line up because of the differences in the name lengths. Do you have any suggestions for accomplishing this? Also, to print the high scores from a different function, would I have to capture them or pass them back to main in some fashion? As you can see from the assignment, the instructor is very specific about the struct having 4 components. (I will work on your other suggestions.) I know I have test score 3 times, but I am waiting for a response frm the instructor as to whether there should only be one score per student. Thanks!

Current code

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>
#include <cmath>


using namespace std;



struct studentType
{
    string studentFName;
    string studentLName;
      int testScore;
      int testScore2;
      int testScore3;
      char grade;

};


void readfile(studentType student[10])
{
            int x = 0;
              ifstream infile;

            char filename[]= "students.txt";
       
        infile.open(filename);

        if (infile.fail())
        {
                cout << "File doesn't exist" << endl;
                exit(0);
        }

     while( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore >> 
               student[x].testScore2 >> student[x].testScore3;
       x++;
       }
     
        infile.close();
}


void printfile(studentType* student)
{
      cout << "Entire Input File" << endl << endl;
      cout << "Student Name" << "\tStudent Test Scores" << endl;

    for (int i=0;i<10;i++)
            {
            cout << student[i].studentLName << "," << " ";
        cout << student[i].studentFName  << " ";
        cout << student[i].testScore        << " ";
            cout << student[i].testScore2        << " ";
            cout << student[i].testScore3        << " " << endl;
            }
            cout << endl;
}
//cout << setw(15)
void calcgrade(studentType* student)
{
      double average;
      char grade;
      cout << "Students and Grades" << endl << endl;

    for (int i=0;i<10;i++)
            {
        average = ((student[i].testScore + student[i].testScore2 + student[i].testScore3) / 3.0);

            
             // convert score to letter grade
                  if (average > 89)
                  grade = 'A';
                  else if (average > 79)
                  grade = 'B';
                  else if (average > 69)
                  grade = 'C';
                  else if (average > 59)
                  grade = 'D';
                  else
                  grade = 'F';
   
            
            // print out student grade line
    cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << student[i].testScore <<
                  " " << student[i].testScore2 << " " << student[i].testScore3 << " " << fixed << setprecision(2) << average << " " << grade << endl;

            }
}

void highestScore(studentType* student)
{
      int HighScore;
      cout << endl;
      cout << "Highest Score For Each Student" << endl << endl;

    for (int i=0;i<10;i++)
            {
        HighScore = student[i].testScore > student[i].testScore2 ? student[i].testScore : student[i].testScore2;   //  Select the higher of the first two scores
            HighScore = HighScore > student[i].testScore3 ? HighScore : student[i].testScore3;
            
            // print out student grade line
            cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << HighScore << endl;
            }
}

int main()
{
    studentType student[10];
      readfile(student);
      printfile(student);
      calcgrade(student);
      highestScore(student);
}





Current code
0
 
itsmeandnobodyelseCommented:
>>> I am having trouble with the formatting.
use the 'left', 'right' and 'setw' format specifiers to make formatting.

setw(10) makes the next text output (at least) 10 characters. left and right specify the orientation left or right-justified.

    cout << left <<  setw(20) << first_name << right << setw(10) << average << endl;

would make two columns 20 and 10 in width where the first column was left justified and the second right-justified.

0
 
itsmeandnobodyelseCommented:
>>> Also, to print the high scores from a different function,
>>> would I have to capture them or pass them back to main in some fashion?
You could make functions of different level. Level 1 functions were passed the student array (like readFile). Level 2 functions work on 1 student only as I suggested with the highScore function. The latter would be done normally by using member functions of the class or struct. But if you don't have member functions till now you may use global functions and pass a 'studentType' object by reference, e. g.

void highestScore(studentType& student)
{
      int HighScore;
      HighScore = student.testScore > student.testScore2
                          ? student.testScore > student.testScore3
                             ? student.testScore  
                             : student.testScore3
                          : student.testScore2 > student.testScore3
                             ? student.testScore2
                             : student.testScore3;
      return HighScore;
}

void highestScore(studentType* students)
{
      cout << endl;
      cout << "Highest Score For Each Student" << endl << endl;

    for (int i=0;i<10;i++)
            {
                   // print out student grade line
                  cout << students[i].studentLName << "," << " " 
                  << students[i].studentFName << " " << highestScore(students[i]) << endl;
            }
}

Note, I changed 'student' to 'students' in the highestScore that takes the array.

0
 
ghost8067Author Commented:
Having trouble making that work. When I do the following I still can't get the first test score to line up. I am also stck with the lastname <space> <comma> firstname, structure, as it is a requirement. I played with the right an left, but couldn't get it to line up.  The numbers are off of alignment by the difference in length of the name strung together.

       cout << left << student[i].studentLName << "," << " ";
        cout << left << setw(20) << student[i].studentFName;
        cout << left << setw(4) << student[i].testScore;
       cout << left << setw(4) << student[i].testScore2;
        cout << left << setw(4) << student[i].testScore3 << endl;
            }
            cout << endl;
0
 
itsmeandnobodyelseCommented:
>>>> the instructor is very specific about the struct having 4 components.
That is a strong indication that the 'score' should be an array rather than three variables:

struct studentType
{
    string studentFName;
    string studentLName;
    int testScore[3];
    char grade;
};


Then the highestCore(studentType& student)  would turn to

void highestScore(studentType& student)
{
      int HighScore = student.testScore[0] ;
      for (int m = 1; m < 3; ++m)
           if (student.testScore[m] > HighScore)
                  HighScore = student.testScore[m] ;
      return HighScore;
}

what has the advantage that it is much easier ;-)

0
 
itsmeandnobodyelseCommented:
>>>>  cout << left << student[i].studentLName << "," << " ";
You have to use setw for all cout statements or it cannot work. As told setw specifies how many spaces have to eb padded left or right to the next output, here  student[i].studentLName. The problem in that line is the comma cause it is an extra output. You should consider that a comma doesn't fit to a report-like representation. To put the , directly behind the name you would need a temporary string buffer that has the name + the comma as contents. I would suggest to simply omit the comma instead.

>>>>  << " ";
If working with setw forget the extra blanks. Simply specify the width of the column.

so it is like

cout << left   << setw(20) << fname
        << left   << setw(20) << lname
        << right << setw(10) << highScore << endl;

Do you understand?
 
0
 
ghost8067Author Commented:
Sure does seem like the right answer. That change gave ma a compiler error on the following piece of code. Suggestions?

hile( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore >> 
         student[x].testScore2 >> student[x].testScore2;
       x++;
       }
     
        infile.close();
}
0
 
itsmeandnobodyelseCommented:
>>>> hile( infile && x < 10 )
maybe the 'w' is missing? Or what compiler error and what line?


0
 
ghost8067Author Commented:
The problem is I was specifying 3 different variables to load the array. Now that test score is an array of 3 itself, I have to load in a different way. Testscore2 and 3 no longer exist because I had to change it to an array to meet the specific assignment requirements.

Error is:
Wk4_Ex01.cpp(42): error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'int [3]' (or there is no acceptable conversion)


 while( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore >> 
               student[x].testScore2 >> student[x].testScore3;
       x++;
       }
     
        infile.close();
}
0
 
itsmeandnobodyelseCommented:
Use

 infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore[0] >> 
               student[x].testScore[1] >> student[x].testScore[2];
0
 
ghost8067Author Commented:
Okay, I made changes to everywhere I used testscore to reference the array. After the other suggested changes, I now get:
Wk4_Ex01.cpp(115): error C2664: 'highestScore' : cannot convert parameter 1 from 'studentType [10]' to 'studentType &'


int highestScore(studentType& student)
{
      int HighScore = student.testScore[0] ;
      for (int m = 1; m < 3; ++m)
           if (student.testScore[m] > HighScore)
                  HighScore = student.testScore[m] ;
      return HighScore;
}


int main()
{
    studentType student[10];
      readfile(student);
      printfile(student);
      calcgrade(student);
      highestScore(student);
}
0
 
itsmeandnobodyelseCommented:
The input and output statements relying exactly on 3 scores and 10 students are very unflexible. Better use some global constants which specifiy the number of students and the number of scores for each student:

using namespace std;

enum { MAX_STUDENT = 10, MAX_SCORE = 3 };

struct studentType
{
     ...
     testScore[MAX_SCORE];
     ...


You would need a loop for any statement taht handles scores, e. g.

         infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore[0];

         for (int s = 1; s <  MAX_SCORE; ++m)
                infile >> student[x].testScore[m];

0
 
itsmeandnobodyelseCommented:
Correction:      

       for (int s = 1; s <  MAX_SCORE; ++s)
                infile >> student[x].testScore[s];
0
 
itsmeandnobodyelseCommented:
>>> int highestScore(studentType& student)
You need to make the implementation *above* that of the ' int highestScore(studentType* students)' or you need to specify a prototype before using it.

// forward declaration (prototype)
int highestScore(studentType& student);

In C/C++ any function called must be at least declared so taht the compiler can check the arguments.


0
 
itsmeandnobodyelseCommented:
If going the way to make functions for a single studentType, I would strongly recommend to call the array 'students' or 'studentArr' instead of 'student' to avoid mixing things up.
0
 
ghost8067Author Commented:
Unfortunately, I do not understand what is meant by a forward declaration. Can you give me a clue where it goes?

Here is where I am at.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>
#include <cmath>


using namespace std;

enum { MAX_STUDENT = 10, MAX_SCORE = 3 };


struct studentType
{
    string studentFName;
    string studentLName;
      int testScore[MAX_SCORE];
      char grade;

};


void readfile(studentType student[10])
{
            int x = 0;
              ifstream infile;

            char filename[]= "students.txt";
       
        infile.open(filename);

        if (infile.fail())
        {
                cout << "File doesn't exist" << endl;
                exit(0);
        }

     while( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore[0] >> 
               student[x].testScore[1] >> student[x].testScore[2];
       x++;
       }
     
        infile.close();
}


void printfile(studentType* student)
{
      cout << "Entire Input File" << endl << endl;
      cout << "Student Name" << "\tStudent Test Scores" << endl;

    for (int i=0;i<10;i++)
            {
            cout << student[i].studentLName << "," << " ";
        cout << student[i].studentFName  << " ";
        cout << student[i].testScore[0]        << " ";
            cout << student[i].testScore[1]        << " ";
            cout << student[i].testScore[2]        << " " << endl;
            }
            cout << endl;
}
//cout << setw(15)
void calcgrade(studentType* student)
{
      double average;
      char grade;
      cout << "Students and Grades" << endl << endl;

    for (int i=0;i<10;i++)
            {
        average = ((student[i].testScore[0] + student[i].testScore[1] + student[i].testScore[2]) / 3.0);

           
             // convert score to letter grade
                  if (average > 89)
                  grade = 'A';
                  else if (average > 79)
                  grade = 'B';
                  else if (average > 69)
                  grade = 'C';
                  else if (average > 59)
                  grade = 'D';
                  else
                  grade = 'F';
   
           
            // print out student grade line
            cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << student[i].testScore[0] <<
             " " << student[i].testScore[1] << " " << student[i].testScore[2] << " " << fixed << setprecision(2) << average << " " << grade << endl;

            }
}

int highestScore(studentType& student)
{
      int HighScore = student.testScore[0] ;
      for (int m = 1; m < 3; ++m)
           if (student.testScore[m] > HighScore)
                  HighScore = student.testScore[m] ;
      return HighScore;
}


int main()
{
      
    studentType student[10];
      readfile(student);
      printfile(student);
      calcgrade(student);
      highestScore(student);
}
0
 
itsmeandnobodyelseCommented:
>>>> Can you give me a clue where it goes?

A forward declaration or protoptype of a function is a type, a function name and the list of arguments enclosed in parantheses terminated by a semicolon.

int highestScore(studentType& student);

The statement is a forward declaration. It looks like the first line of the 'definition' of the function but has no body {} and is terminated by a ;  (what makes it different to the 'definition' or 'implementation')

If you *call* a function you need to have at least a declaration of the function called *above* the call, e. g.

void g()
{
     f();    // call function f  ==>  error: f was not declared
};

void f()
{
     ...
}

but:

void f();  // forward declaration

void g()
{
     f();    // call function f  ==>  ok.
};

The compiler now is happy as it *knows* how function f  needs to be called.

But if there is no implementation of f() somewhere in the project files, the linker would complain (unresolved function).

So, put the following statement

int highestScore(studentType& student);

above the function definition


void highestScore(studentType* students)
{
     ...
     for (int x = 0; x < 10; ++x)
     {
            int HighScore = highestScore(students[x]);   // here you are calling
                                                                                  // the other function
                                                                                  // which must be declared before
            ...
      }
}



0
 
itsmeandnobodyelseCommented:
Note, you don't need a forward declaration if you simply put all functions in the right order. You didn't need a forward declaration until now cause you implemented all functions *above* main() function and didn't call functions from functions (beside of main).

If you open one of the header files you are including at the top, you will find hundreds of declarations only. The 'implementation' or function bodys of these declarations were not provided as source code but as object code (or machine code) in a so-called library. But for your own functions you may have both a declaration (excluded in a header file or not) and an implementation or an implementation above first calling the function.
0
 
ghost8067Author Commented:
Okay, I have that working now. The one thing I have not done is create a separate function to print out the highest scores as dictated by the instructor. Can you give me some direction on that (I got some earlier from you, but still am unclear. I also cannot add anything else to the struct. I really appreciate the help. At this point, the points should probably be closer to 5000.

Anyway, here is the updated code.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>
#include <cmath>


using namespace std;

enum { MAX_STUDENT = 10, MAX_SCORE = 3 };

struct studentType
{
    string studentFName;
    string studentLName;
      int testScore[MAX_SCORE];
      char grade;


};


void readfile(studentType student[10])
{
            int x = 0;
              ifstream infile;

            char filename[]= "students.txt";
       
        infile.open(filename);

        if (infile.fail())
        {
                cout << "File doesn't exist" << endl;
                exit(0);
        }

     while( infile && x < 10 )
     {
       infile >> student[x].studentFName >> student[x].studentLName >> student[x].testScore[0] >> 
               student[x].testScore[1] >> student[x].testScore[2];
       x++;
       }
     
        infile.close();
}


void printfile(studentType* student)
{
      cout << "Entire Input File" << endl << endl;
      cout << "Student Name" << "\tStudent Test Scores" << endl;

    for (int i=0;i<10;i++)
            {
            cout << student[i].studentLName << "," << " ";
        cout << student[i].studentFName  << " ";
        cout << student[i].testScore[0]        << " ";
            cout << student[i].testScore[1]        << " ";
            cout << student[i].testScore[2]        << " " << endl;
            }
            cout << endl;
}
//cout << setw(15)
void calcgrade(studentType* student)
{
      double average;
      char grade;
      cout << "Students and Grades" << endl << endl;

    for (int i=0;i<10;i++)
            {
        average = ((student[i].testScore[0] + student[i].testScore[1] + student[i].testScore[2]) / 3.0);

           
             // convert score to letter grade
                  if (average > 89)
                  grade = 'A';
                  else if (average > 79)
                  grade = 'B';
                  else if (average > 69)
                  grade = 'C';
                  else if (average > 59)
                  grade = 'D';
                  else
                  grade = 'F';
   
           
            // print out student grade line
            cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << student[i].testScore[0] <<
             " " << student[i].testScore[1] << " " << student[i].testScore[2] << " " << fixed << setprecision(2) << average << " " << grade << endl;

            }
}
int highestScore(studentType& student);

void highestScore(studentType* student)
{
      int HighScore;
      cout << endl;
      cout << "Highest Score For Each Student" << endl << endl;

    for (int i=0;i<10;i++)
            {
        HighScore = student[i].testScore[0] > student[i].testScore[1] ? student[i].testScore[0] : student[i].testScore[1];   //  Select the higher of the first two scores
            HighScore = HighScore > student[i].testScore[2] ? HighScore : student[i].testScore[2];
           
            // print out student grade line
            cout << student[i].studentLName << "," << " " << student[i].studentFName << " " << HighScore << endl;
            }
}



int main()
{


        studentType student[10];
      readfile(student);
      printfile(student);
      calcgrade(student);
      highestScore(student);
}
0
 
itsmeandnobodyelseCommented:
I assume you mean
>>>> d. A function to print the names of the students having the highest test score.

You best would reimplement the function 'void highestScore(studentType* student)' to do that job cause in the current implementation there is no requirement.

Let us assume you should find out the the *three* students who have the the highest score. There are two different approaches possible:

1. Sort the student array with descending high scores and print the first three after sort.
2. Determine the three best student records similar as we found out the high score in 'int highestScore(studentType& student)';

to 1.)
for sorting the students array you could use a bubble sort like that

    for (int i = 0; i < 10-1; ++i)
    {
           for (int j = i + 1; j < 10; ++j)
           {
                 if (highScores(student[j]) > highScores(student[i]))
                 {
                       swapstudent(student[i], student[j]);
                 }
           }
    }

The function swapstudent would take two studentType& arguments, would have a local studentType temp; variable, would assign the first argument to temp, then the second argument to the first, and finally the temp to the second argument. That way student[j] was exchanged with student[i]. The assignments can be made by simply using operator=.

After that you would use your current print loop but only print the first three students.

to 2.)
You would need to find out the *indices* of the three highest highscores.

- make an integer array of size three 'BestScores'
- init the BestScores with the indices of  0,1,2
- (you could 'sort' the indices 0,1,2 that way that the first has the highest score of student[0],student[1] and student[2] and the second has the second best score. That can be done similar as getting the high score out of three).
- all high scores were determined by calling function highScores(student[x]);
- Then make a loop starting with index 3 up to index 9 (< 10).
- Compare the high score of the current student with the three student items
  where the indices are stored in BestScores.
- If any of them was lower, exchange the index in BestScores and 'continue' loop.

Finally you have the indices of the best three students in BestScores. If you sorted these indices initially and compare always starting with index 0 of BestScores you finally have the best three sorted as well. If not you have the best three but they may be in wrong order (what can be repaired just for output accordingly).

Hint: a comparison within the loop from 3 to 9 would look like

          int currentHighScore =  highScores(student[x]);  // x is loop counter
          if (currentHighScore > highScores(student[BestScores[0]]))
                 BestScores[0] = x;
          else if (currentHighScore > highScores(student[BestScores[1]]))
                 BestScores[1] = x;
          ...

Regards, Alex

 
 




0
 
ghost8067Author Commented:
Thanks for all of the help. I will work on the last item and repost if I have issues. You have been great!!
0
 
itsmeandnobodyelseCommented:
>>>> I really appreciate the help
>>>> At this point, the points should probably be closer to 5000

500 is enough. But you could show me your appreciation by not only making the absolute minimum to make it working, but by applying some of the 'suggestions' as well. For instance it is not a big job to replace all occurences of '10' by MAX_STUDENT and have a definition for MAX_STUDENT = 10 at top of your program. You also could make a function double calcAverage(studentType& student); (similar to highScores) instead of calculating it on the scratch in function calcgrade.

0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 17
  • 9
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now