Need help with class average program!(Started something...)

Pages: 12
I need to write a program that takes the number of tests, assignments, labs, and
quizzes taken in a given class and calculates the student’s class average. The program will read the number of tests, assignments, labs and quizzes as command line input, and then read the specific number of grades for each by prompting the user for the correct number of items.

The user can supply these arguments in any order, and therefore you need to preface each argument with an option to know what the argument is. For example:
class_average –q 5 –a 8 –l 10 –t 2 -f

This means that there are 5 quizzes, 8 assignments, 10 labs, and 2 tests. Next, I have to prompt the user for the specific number of scores for each item. Labs are graded on a 10 point scale, and these labs are added together to determine your overall lab grade, whereas the other scores are out of 100 and averaged to give you your overall quiz, assignment, and test grade.
Quiz 1:
Quiz 2:

Quiz 5:
Assignment 1:
Assignment 2:

Assignment 8:

Final Exam:

This program also needs to determine the overall class average based on the following weights for each item, which should be declared as constants/macros for ease of change.
Labs – 10%
Quizzes – 10%
Assignments – 40%
Exams – 25%
Final – 15%

The tricky part:
I need to try to make your main function as small as possible by decomposing the
problem into smaller subtasks. To do this I need to define and use functions in this program. The number of functions is not specified, but you must make each
function, including main, contain under 20 lines of code.

Then there is the basic Error Handling:
 Print an error message if the user doesn’t supply all the command line arguments, excluding the –f option, which is optional
 Print an error message if the user doesn’t supply a number value for any one of the options, this excludes the –f option, which doesn’t have a number value
 Print an error message if the user enters a zero for any of the command line
arguments.
 Print an error message if the user doesn’t enter an integer value for the command line arguments.
 Print an error message if the user doesn’t supply a number for the scores for the items.

I feel confident I can do the error handling.

Program example:
Program Input:
- Command line options for tests, quizzes, assignments, labs, and a final (optional), in
any order
- Score for each number of items.
- If the –f option is supplied, then read a score for final exam
Program Output:
- Proper error message for each case listed above.
- Class average for the student

I would really like some help to get this program off the ground. Please if anyone can help me with this I would be very grateful. thank you.

Last edited on
Well, post your code (attempts) so more people can help you.
okay, I will post what I try but the major problem I am having is beginning this thing. This is the first time I am using command lines.
Could someone show me how to start this? Or just how to do it with just the quizzes or just the tests? Just something to start with?
Well the assignment is pretty clear.

Try writing psuedo code, start with general ideas of what you want to do in order. Keep going back and refine these ideas into more & more into detailed tasks. Write all these as comments in your .cpp file, leave the comments there, as they serve as documentation. When you are happy translate your comments into code.

This approach will help organise your thoughts, identify what should be in a function, switch etc.

Hopefully you know about argument processing using argv[] and argc.

Hope all goes well.
Okay! So I got something to work finally and I am understanding command line arguments a little better.
here is what I have and it just has them enter a grade and gives the grade back but how should I implement this in my assignment?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<stdlib.h>
  
  using namespace std;
  using std::cin;
  using std::cout;
  using std::endl;
 
 
  int main (int argc, char *argv[]){
 
     int *grades;
 
     if(argc > 1){
 
     grades = new int[atoi(argv[1])];
 
     for(int i=0; i < atoi(argv[1]); i++){
        cout << "Enter grade: ";
        cin >> grades[i];
 
        cout << "You entered: " << grades[i] << endl;
 
     }
 
     delete []grades;
 
     }
  return 0;
  }


And the psuedo code I mentioned - how are you going with that. I don't see any comments at all.

Also, you should comment what you are expecting as arguments to main, so a reader can figure out what is happening. You have a call to atoi - what is that about? I know what atoi does.

You don't need line 7, if you have lines 8 - 10, just remember to put std:: before any other std thing you might use in the future.
Yes I am sorry about line 7 it is just habit to put all of that stuff on their, I know it is not necessary. And what I was trying to ask if would this be a good building block for the program that i need to create? Can I do this same kind of thing but with tests, quizzes, and the overall average calculation separate and call them into main?
Does anyone know how to get this started please? sorry for the begging, just need a boost.
No need to read it in from a file. If the assignment is to read in grades from the command line, all you have to do is to prepare to run your code as an executable, then use command line redirection to provide a file to read from. So there is no need to use fstream and all that jazz because you can just use input redirection.

$ ./MyProg < File_To_Read_From
I have read about that but I have to use command lines for this. I just need a good structure.
Brute forced it

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <cstdlib>

using std::cout;
using std::cin;
using std::endl;

struct Student
{
  Student();
  int Quiz;
  int Assign;
  int Labs;
  int Tests;
  void GetNumEvals();
};

Student::Student()
{
  Quiz = Assign = Labs = Tests = 0;
}

void Student::GetNumEvals()
{
  std::string myStr;
  
  getline(cin, myStr, '-');//ignore the string at the start
  char symbol;
  
  cin >> symbol;//first letter
  for (int k = 0 ; k < 4; ++k)
  {
    if (cin.good())
    {
      symbol = tolower(symbol);//convert everything to lowercase
      switch(symbol)
      {
	case 'q':
	  cin >> Quiz;
	  break;
	  
	case 'a':
	  cin >> Assign;
	  break;
	  
	case 'l':
	  cin >> Labs;
	  break;
	  
	case 't':
	  cin >> Tests;
	  break;
	  
	default:
	  break;	  
      }
      cin >> symbol; //-
      cin >> symbol; //letter
    }
  }
}

int main()
{
  Student myStu;
  
  myStu.GetNumEvals();
  
  cout <<endl << myStu.Quiz << " Quizzes, " << myStu.Assign << " Assignments, " 
  << myStu.Labs << " Labs, " << myStu.Tests << " Tests" << endl;
  
  
  return 0;
}



E: In keeping with 20 lines min per function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <cstdio>
#include <cstdlib>

using std::cout;
using std::cin;
using std::endl;

struct Student
{
  void AssignEvals(char);
public:
  Student();
  int Quiz;
  int Assign;
  int Labs;
  int Tests;
  void GetEvals();
};

void Student::AssignEvals(char Letter)
{
  switch(Letter)
  {
    case 'q':
      scanf("%d", &Quiz);
      break;
      
    case 'a':
      scanf("%d", &Assign);
      break;
      
    case 'l':
      scanf("%d", &Labs);
      break;
      
    case 't':
      scanf("%d", &Tests);
      break;
      
    default:
      break;	  
  }
}

Student::Student()
{
  Quiz = Assign = Labs = Tests = 0;
}

void Student::GetEvals()
{
  char symbol;
  do
  {
    scanf("%c", &symbol);
    symbol = tolower(symbol);//convert everything to lowercase
    AssignEvals(symbol);
    
  } while (symbol != 'f');
  
}

int main()
{
  Student myStu;
  
  myStu.GetEvals();
  
  cout <<endl << myStu.Quiz << " Quizzes, " << myStu.Assign << " Assignments, " 
  << myStu.Labs << " Labs, " << myStu.Tests << " Tests" << endl;
  
  
  return 0;
}




File containing grades looks like
class_average -q 5 -a 8 -l 10 -t 2 -f



Compile with and output:

$ g++ -Wall -W -o tempStu Test.cc
$ ./tempStu < Grades

5 Quizzes, 8 Assignments, 10 Labs, 2 Tests
Last edited on
Okay, so when I try to run this code it does nothing. It compiles just fine but still does not work.
I did this:

flip3 ~/assignments/assignment5 157% g++ CA_Calculator.cpp -o calc
fflip3 ~/assignments/assignment5 159% ./calc -q 5 -a 8 -l 10 -t 2 -f

and it just gave me a blank.
I also need to ask for the user to input the scores of each of the quizzes and such he/she has said they have. Then I need to calculate the average.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
  #include <iostream>
  #include <string>
  #include <cstring>
  #include <stdlib.h>
 
  using namespace std;
  
  int main(int argc, char* argv[])
  {
     int scores[5], temp;
     do {
        cout << "Please enter a score: ";
        cin >> scores[0];
     } while(scores[0] < 0 || scores[0] > 100);
 
     for(int i = 1; i < 5; i++){
        do {
           cout << "\n\nPlease enter a score: ";
           cin >> scores[i];
        } while(scores[i] < 0 || scores[i] > 100);
 
        if(scores[i] < scores[0]) {
           temp = scores[i];
           scores[i] = scores[0];
           scores[0] = temp;
        }
     }
 
     double average = (scores[1] + scores[2] + scores[3] + scores[4]) / 4;
     cout << "\n\nAverage of the four highest scores: " << double(average) << "\n\n";
 
     return 0;
  }


I have come up with this so far and I need to use int main(int argc, char* argv[]) command line arguments. I need to get all requirements done above. Can some please help me transform my code so it meets the criteria listed at the top of this page?
anyone?
lines 17 to 21 won't put anything in the first position in the array. Arrays start at zero, Get used to doing this:

1
2
3
4
5
for(int i = 0; i < 5; i++){
        do {
           cout << "\n\nPlease enter a score: ";
           cin >> scores[i];
        } while(scores[i] < 0 || scores[i] > 100);


With line 30, use a for loop to do that. What if you had 1000 numbers?

lines 24 to 26 should be in a swap function, although you will have to name it something else, because there is already a std::swap. This can be a problem because of line 7. You are better off without line 7, and put std:: before each std thing.

Sorting at the same time as input is bound to cause problems - have another for loop to do the sorting after input is finished.

For sorting the subscripts should be i and i-1, not 0. At the moment you are overwriting your data.

On line 11, rather than have the magic number 5, which appears in multiple places, declare the array size as a const:

const int SIZE = 5;

Then use the variable SIZE wherever the 5 appears. This way if you want to change the size, you can change it in 1 place only.

With the command line arguments, you need to do something similar to what Smac89 had (are you allowed to use classes?), but reference the argv array. You teachers must have shown how to do that if it is a requirement of the assignment.

Also, my earlier advice - sounds boring but it works:

TheIdeasMan wrote:
Try writing psuedo code, start with general ideas of what you want to do in order. Keep going back and refine these ideas into more & more into detailed tasks. Write all these as comments in your .cpp file, leave the comments there, as they serve as documentation. When you are happy translate your comments into code.

This approach will help organise your thoughts, identify what should be in a function, switch etc.


With compiling, use the maximum warning level:

-Wall -Wextra -pedantic


or even -Werror which promotes warnings to errors.

Hope all goes well.
I thought your code was to be run using a file so that is what I had in mind when designing that one. Not saying it can't be run normally. When it runs, the first thing it looks for is a character corresponding to either q (quiz), a (assignments), l (labs), t(tests)*. After reading each symbol, it will require you to enter a number indicating the number of that type you have done in the class. You keep doing this until you have entered everything.

You can also change number of each by typing the symbol again and inputting a value. The program will loop until you type the letter f in which case it will exit and print out how many quiz, assign, tests, and labs you have put in.

The reason it was not working for you is because you are giving it a command line arguement. It DOES NOT TAKE COMMAND LINE ARGUEMENTS. It uses input redirection or in most basic terms, it takes user input. But since this is the terminal, and computers have never been known to complain when you don't do exactly as you say, you can have the shell feed all the input to the program by pre-writting all your input in a file and using the '<' command, you can direct all input needed for the program from whatever source you have it in. http://www.ucblueash.edu/thomas/Intro_Unix_Text/IO_Redir_Pipes.html


For it to work the way you are doing it, you do something like this (Another form of input redirection):
./calc <<< "-q 5 -a 8 -l 10 -t 2 -f"


Output:
5 Quizzes, 8 Assignments, 10 Labs, 2 Tests


*Upper or lower case doesn't matter



This one uses files since that is what you want:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <cstdio>

struct Student
{
  void AssignEvals(char, FILE*);
public:
  Student();
  int Quiz;
  int Assign;
  int Labs;
  int Tests;
  void GetEvals(FILE*);
};

void Student::AssignEvals(char Letter, FILE* ReadFrom)
{
  switch(Letter)
  {
    case 'q':
      fscanf(ReadFrom, "%d", &Quiz);
      break;
      
    case 'a':
      fscanf(ReadFrom, "%d", &Assign);
      break;
      
    case 'l':
      fscanf(ReadFrom, "%d", &Labs);
      break;
      
    case 't':
      fscanf(ReadFrom, "%d", &Tests);
      break;
      
    default:
      break;	  
  }
}

Student::Student()
{
  Quiz = Assign = Labs = Tests = 0;
}

void Student::GetEvals(FILE* ReadFrom)
{
  char symbol;
  do
  {
    fscanf(ReadFrom, "%c", &symbol);
    symbol = tolower(symbol);//convert everything to lowercase
    AssignEvals(symbol, ReadFrom);
    
  } while (symbol != 'f' && !feof(ReadFrom));
  
}

int main(int argc, char *argv[])
{
  if (argc < 2)
  {
    std::cerr << "Format for running program: " << *argv << " filename\n";
    return 1;
  }
  
  FILE* readStream;
  readStream = fopen(argv[1], "r+");
  
  if (NULL == readStream)
  {
    std::cerr << "Corrupt file. Aborting\n";
    return 1;    
  }
  else
  {
    Student myStu;
    
    myStu.GetEvals(readStream);
    
    cout <<endl << myStu.Quiz << " Quizzes, " << myStu.Assign << " Assignments, " 
    << myStu.Labs << " Labs, " << myStu.Tests << " Tests" << endl;
  }
  
  return 0;
}
Last edited on
flip3 ~/assignments/assignment5 167% ./CA_Calculator -q 5 -a 8 -l 10 -t 2 -f
Corrupt file. Aborting


Why does it do this?
Pages: 12