Need help with a grade processor assignment using arrays..

Pages: 1234
Dmtg93, you're in good hands with Andy but I'll add a couple of things:

First, if you're still putting the code into wordpad, you should move it to a compiler and get the code that you have so far working. For example, try to make the program prompt for the number of scores and print them out. Then add the code to compute the average (with and without dropping the lowest score) and print out those values. Keep adding more and more functionality until you have everything, and then it's just a question of making sure that your main program produces the output in the required format.

Second is this:
I dont really have time to read all the material in the text. Ive been skimming it.

Programming is a skilled craft, like woodworking, playing an instrument, or playing a sport. It takes lots of practice at actually doing it.

The good news is that I can see from your posts that you're pretty smart and you're picking it up quickly with Andy's help. Going forward, I urge you to read the material carefully. This isn't like a literature class where you can fake your way though it. It's more like football where if you don't practice, you're going to get killed on the field.

Oh, one more thing, for calcAverage, I'd do it a little differently than I think Andy is suggesting. In pseudocode:
1
2
3
4
5
6
Compute the sum of all items
if (drop) {
    subtract findlowest(list,n) from the sum
    subtract 1 from n
}
return sum / n;

@dhayden,

Thank you for the kind words. It is nice to know that I make a difference and that I am doing something right.

I like your idea for using "drop". Sometimes its the simple things that elude me when my min get fixed on something else.

I have always found your posts informative and instructive even is I can not use the information right away.

Andy
Hi dhayden,

The good news is that I can see from your posts that you're pretty smart and you're picking it up quickly with Andy's help. Going forward, I urge you to read the material carefully. This isn't like a literature class where you can fake your way though it. It's more like football where if you don't practice, you're going to get killed on the field.


Understood, thank you for the kind words. I actually am taking an accelerated class online and my teacher is strict in the sense that if an assignment isnt turned in on time we get dropped from the class. I can't really afford to do that right now so I am anxious about turning everything in on time. I have the downloaded copy of the book though so I do plan on reading more into it and practicing more once the class is over so I can understand better.

Also, for your pseudocode, are you suggesting that I sum everything in list[i] before the if statement? I'm assuming that if statement has to be followed by an else statement?
I did this
 
sum+=list[i];

Is that not summing everything in list[i]? Or do I need to change something? How would I sum all the items in list[i] ?

Here's the updated..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 double calcAverage (int list[], int n, bool drop){
int sum=0;
double average=0.0;
int min =  findLowest(list,n);
int max=findHighest(list,n);
sum+=list[i];
for (int i = 0; i < n; i++) {
if(drop){
sum-min // or do I need to actually call it findLowest(list,n) in this case?
n-1
}
return sum/n;
}
}

If I am doing it like this, do I still need
1
2
3
4
 
average= double(sum)/n;

return average; 
?
I'm assuming I don't and that I can also delete double average=0.0;


Hi Andy, thank you for the input on the last post! We are at chapter 8 in the text and haven't gotten to '?' yet. We can't include anything we haven't gone over yet..

Also any suggestions on how to start a histogram? Description is here

Function: void displayHistogram( int list[], int n )
Description: Displays a histogram of all scores in terms of the letter grade for each score. The display heading states how many scores ( n ) are in the histogram, then displays one star for each score that is an A on line one of the histogram. On line two there should be one star for each score that is a B. Proceed this way for all five letter grades (A, B, C, D, F). Each line should begin with a label containing the letter grade for that line. See several examples in the example output. Make sure your output is exactly the same.

I was going to do a cout in main for each letter and increment how many of each grade there was but I'm not sure how that ties in the sense that I need an * for each in this function..

EDIT: I have this so far
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
{

cout << "\nA's  : ";
      for(int i=0;i<minA;i++){
        cout << "*";
      }
      cout << endl;    

      cout << "\nB's  : ";
      for(int i=0;i<minB;i++){
        cout << "*";
      }
      cout << endl;    

      cout << "\nC's  : ";
      for(int i=0;i<minC;i++){
        cout << "*";
      }
      cout << endl;    

      cout << "\nD's  : ";
      for(int i=0;i<minD;i++){
        cout << "*";
      }
      cout << endl;    

      cout << "\nF's  : ";
      for(int i=0;i<minF;i++){
        cout << "*";
      }
      cout << endl;    


}

My only problem is, is that I need to make use of int list[] and int n. I have also updated generateOneScore to increment now..

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
int generateOneScore() {
   const int A = 14;  // ~14% of scores are A
   const int B = 39;  // ~25% of scores are B
   const int C = 75;  // ~36% of scores are C
   const int D = 89;  // ~14% of scores are D
   const int F = 100; // ~11% of scores are F
   const int MIN_A = 90;
   const int MIN_B = 80;
   const int MIN_C = 70;
   const int MIN_D = 60;
   
   // generate a number bewteen 1 and 100, inclusive
   // to determine which letter grade to generate
   int whichLetter = rand() % 100 + 1;  // 1..100
   
   // Set min and max based on the letter grade
   int min, max;
   if (whichLetter <= A) {
      min = MIN_A;
      max = 101;
minA++;
   }
   else if (whichLetter <= B) {
      min = MIN_B;
      max = MIN_A;
minB++;
   }
   else if (whichLetter <= C) {
      min = MIN_C;
      max = MIN_B;
minC++;
   }
   else if (whichLetter <= D) {
      min = MIN_D;
      max = MIN_C;
minD++;
   }
   else {
      min = 0;
      max = MIN_D;
minF++;
   }
   // Generate a random score for the chosen letter grade
   int score = rand() % (max-min) + min;
   return score;
}

Last edited on
Hello Dmtg93,

Lines 1 and 2 you only need one and it needs to be a double because the function returns a double. I would suggest "sum" because it is more descriptive of what it is for.

Line 4 is OK, but not really needed here. This can be accomplished later in the program without the need for an extra variable.

Line 5 is not needed at all. You do not have a need here for "max",

Line 6 needs to be in the for loop.

Lines 8 - 10 go after the closing } of the for loop. his way you can adjust "sum" and "n" before the "return".

Line 9 would be better written as sum -= findLowest(list, n); and line 10 could be n--; for the short way of doing this.

Line 12 will work, but I would suggest this return sum / static_cast<double>(n);. The "static_cast" is the more up to date usage. This maybe ahead of where you are at but something to think about. http://www.cplusplus.com/doc/tutorial/typecasting/#implicit_in_classes and http://www.cplusplus.com/doc/tutorial/typecasting/#static_cast .

Just because you have not learned something in class does not mean that you can not use something you have learned outside of class. I believe these new typr of type casting started with C++11 and your compiler may not be up to these new standards. If not use what you have used.

Hope that helps,

Andy
Awesome here is what I have now..

1
2
3
4
5
6
7
8
9
10
11
12
 double calcAverage (int list[], int n, bool drop){
int sum=0;
int min =  findLowest(list,n);
for (int i = 0; i < n; i++) {
sum+=list[i];
}
if(drop){
sum -=  findLowest(list,n);
n--;
return sum/n;
}
}


Also did you happen to see my histogram attempt?
So close!

- Indent your code to match the block structure. That would make your code look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double
calcAverage(int list[], int n, bool drop)
{
    int sum = 0;
    int min = findLowest(list, n);
    for (int i = 0; i < n; i++) {
	sum += list[i];
    }
    if (drop) {
	sum -= findLowest(list, n);
	n--;
	return sum / n;
    }
}


Also, if you compile the code as you go and enable compiler warnings, you'll get something like this warning:
foo.cxx:14:1: warning: control reaches end of non-void function [-Wreturn-type]

What that means is that you can run off the end of the function without returning a value. That's always bad. Looking at the code, you can see that the only return statement is inside the if statement. If the if condition isn't true, then no return statement executes. That points to the bug: the return statement is in the wrong place. You'll also get a warning that variable min is never used. Finally, you need Andy's point about casting the sum to a double. So the result should be :
1
2
3
4
5
6
7
8
9
10
11
12
13
double
calcAverage(int list[], int n, bool drop)
{
    int sum = 0;
    for (int i = 0; i < n; i++) {
	sum += list[i];
    }
    if (drop) {
	sum -= findLowest(list, n);
	n--;
    }
    return static_cast<double>(sum) / n;
}

hi dhayden,


What that means is that you can run off the end of the function without returning a value. That's always bad. Looking at the code, you can see that the only return statement is inside the if statement. If the if condition isn't true, then no return statement executes. That points to the bug: the return statement is in the wrong place. You'll also get a warning that variable min is never used. Finally, you need Andy's point about casting the sum to a double. So the result should be :


Ohh, I didn't even notice that! That makes more sense haha. Thank you!

All I have left to work on before I work on my main function is void displayHistogram( int list[], int n )
, void displayDuplicateScores( int list[], int n ) , and int countAboveAverage (int list[], int n, double average) .

I think I am doing okay thanks to everyone's help. I have a countAboveAverage code I have been messing with. But the other 2 I could use some help with.

Here's my countAboveAverage:
1
2
3
4
5
6
7
8
9
10
int countAboveAverage (int list[], int n, double average) 
{
 int count=0, i;

 for(i=0; i<n; i++) {
  if(list[i]>average)
   count++;
 }
 return count;
}
Hello Dmtg93,

For the "displayHistogram" function you will need to use the "list" array to figure which letter grade each element of the array will fit into.

The first time I wrote this function I used the long approach. Then today I had a better idea.

I started with an array of five to hold a value I will add one to. Think of it as n array of counters.

The first for loop will check each element of "list" and use that value to determine which letter grade to add one to. I used a series of if statements to place the number in the proper letter grade, i.e., "arrayName[0]" for a grade of A and so on for the rest of the array.

Then I shrunk five different for loops down to one nested for loop. I setup the outer for loop this way:for (char lco = 'A', ss = 0; lco < 'G'; lco++, ss++) where "lco" is my shorthand for Loop Counter and here "ss" is short for "sub script". Although "ss" is most often seen used with stringstreams. As you can see "lco" can be defined as any type you need. And yes, even-though "ss" is defined as a char it still works. You could even define "ss" outside of the for loop an increase "ss" inside the outer for loop and it will work the same.

The inner for loop is a simple loop to print the desired amount of '*'.

The end the outer for loop I checked the value of "lco" to see if it is equal to 'D' and if so add one to "lco" to bypass the letter 'E'. This i the reason I used the "ss" in the inner for loop: for (int lci = 0; lci < aCounters[ss]; lci++).

I hope my thoughts and explanations are not to far apart, my thoughts keep getting interrupted.

When you get to the function for "DisplayDuplicateScores" several concepts used here can be used in that function. Differences would be the extra array you will use will need to have a size of 100 and the final for loop will need to work backwards.

Hope that helps,

Andy
Hello Dmtg93,

Your code for the function "countAboveAverage" will work.

You changed the "generateOneScore" function. Change it back you do not need to make any changes or call it more than you need at the beginning of the program. This function was given to you and you do not need to change it. This function has one use at the beginning of the program and that is it.

Your code:

1
2
3
4
5
cout << "\nA's  : ";
      for(int i=0;i<minA;i++){
        cout << "*";
      }
      cout << endl;    

really does not make any sense partly because it is out of context. You posted this before I could finish my last post, so take a look at that.

Also line 1 is wrong. The given output says "A: ***..." not the "A's :" that you have. Keep in mind the the instructions say to make your program match the given output.

Hope that helps,

Andy
All I have left to work on before I work on my main function

I want to stress again that you should already have a main function that you're using to test these other functions as you go along. It's extremely important.

Why? Because if you wait until you have all the code written, you might be like the Titanic steaming full speed into the iceberg. I've seen it several times here on the forum. A beginner writes hundreds of lines of code, only to find that they have the wrong approach and need to start over from scratch. Please please, test your code as you write it, creating a main program that does one part of the assignment at a time.
closed account (48T7M4Gy)
@OP This is how you build up the solution and test as you go. Sweat the little stuff first by getting the values in and displaying them without concern for making it look pretty with formatting. This exercise revolves around processing the array of scores, get that right first.

You've also got a problem with the generateOneScore() function above because minA isn't defined. Is that a copy of what you were supplied with?

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
#include <iostream>

using namespace std;

void getNumberOfScores( int& );
int generateOneScore();
void generateScores( int [], int );
void displayScores(int [], int );

int main()
{
    int no_of_scores = 0;
    
    getNumberOfScores(no_of_scores);
    cout << "No. of scores: " << no_of_scores << '\n';
    
    int* scores  = new int[no_of_scores];
    generateScores(scores, no_of_scores);
    displayScores(scores, no_of_scores);
    // etc etc etc
    
    return 0;
}

void getNumberOfScores( int& number)
{
    cout << "Pls enter number of scores: ";
    cin >> number;
}

int generateOneScore()
{
    return rand() % 100;
}

void generateScores( int list[], int n )
{
    for(int i = 0; i < n; ++i)
    {
        list[i] = generateOneScore();
    }
    return;
}

void displayScores(int list[], int n)
{
    for(int i = 0; i < n; ++i)
    {
        cout << "Score no: " << i << '\t' << list[i] << '\n';
    }
    return;
}
Pls enter number of scores: 8
No. of scores: 8
Score no: 0	7
Score no: 1	49
Score no: 2	73
Score no: 3	58
Score no: 4	30
Score no: 5	72
Score no: 6	44
Score no: 7	78
Program ended with exit code: 0
Hi Andy,

Im not sure what you mean with your formatting for the Histogram. for (char lco = 'A', ss = 0; lco < 'G'; lco++, ss++) looks kind of confusing to me. Is there an easier way to format the histogram so i could read it easier? I know I'll need a couple nested loops.. I'm just not sure what you mean.

kemort,
generateOneScore was give to us. I defined minA etc before main.
As it stands I am having trouble with generateScores as well
1
2
3
4
5
6
7
8
void generateScores(int list[], int n) {

	generateOneScore();

	for (i = 0; i < n; i++) {
		cout << list[i] = generateOneScore << endl;
	}
}

It's giving me this error error: invalid operands of types 'int()' and '<unresolved overloaded function type>' to binary 'operator<<'

As well as findLowest and findHighest

1
2
3
4
5
6
7
8
9
 int findLowest(int list[], int n) {
	int smallest = list[];
	for (int i = 0; i < n; i++) {
		if (list[i] < smallest)
			smallest = list[i];
	}
	return smallest;

}


1
2
3
4
5
6
7
8
int findHighest(int list[], int n) {
	int largest= list[];
	for (int i = 0; i < n; i++) {
		if (list[i] < largest)
			largest = list[i];
	}
	return largest;
}


I am getting error error: expected primary-expression before ']' token for both
closed account (48T7M4Gy)
cout << list[i] = generateOneScore << endl;

You are combining two things. You need to 1) generate the score, place it in the list and then 2) separately print it out.
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
int findLowest(int list[], int n) {
	int smallest = list[0]; // <---
	for (int i = 1; i < n; i++) { // <--
		if (list[i] < smallest)
			smallest = list[i];
	}
	return smallest;

}
Hi kemort,

You are combining two things. You need to 1) generate the score, place it in the list and then 2) separately print it out.


So like this?
1
2
3
4
5
6
7
8
9
void generateScores(int list[], int n) {

	generateOneScore();
        list[i]=generateOneScore();

	for (i = 0; i < n; i++) {
		cout << list[i] = generateOneScore << endl;
	}
}

Thanks for your help as well!
Last edited on
Hello Dmtg93,

In your code:

1
2
3
4
5
6
7
8
9
void generateScores(int list[], int n) {

	generateOneScore();
        list[i]=generateOneScore();

	for (i = 0; i < n; i++) {
		cout << list[i] = generateOneScore << endl;
	}
}

Please explain what the "cout" is for? This should only be a simple assignment.

And line 3 and 4 what is the purpose of this? At this point "i" is not defined and will produce an error.

This function only needs two lines of code.

Andy
closed account (48T7M4Gy)
No, you haven't got it.

What you should do is avoid coding as the first step and use pseudocode to get your thinking straight.

So, the process is you are trying to fill up an array given that you have decided on the size of the array and how to make one score.

1. for each element i of the array
2. generate a score and store it in element i of the array
3. loop until finished

That's all that function does unless you want to add another step 2a which would be:
2a. print the value of the element i,

which is still inside the same loop and is there just for checking and testing purposes to be deleted later on.

Otherwise just use the displayScores function separately, which prints out all scores when the whole list has been passed to it, ie when the score generator has completed its job.

Read carefully my two functions.

Last edited on
1
2
3
4
5
6
7
8
void generateScores( int list[], int n )
{
    for(int i = 0; i < n; ++i)
    {
        list[i] = generateOneScore();
    }
    return;
}


Here is what I have for main right now
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {
	srand(time(0));

	cout << "Welcome to the Grade Processor Application " << endl;
	cout << "This app will generate the number of scores desired by the user" << endl;
	cout << "and then perform and display several functions on this data"<< endl;


	    void getNumberOfScores(int &userNum);
		int generateOneScore();
		void generateScores(int list[], int n);
		void displayScores(int*, int);




}


I'm having trouble calling the functions and having them operate..
Pages: 1234