Loss of data?

Hi All,


I am working on a program for class that use's functions and gather's information on students and 3 test scores. When trying to run the program I cannot understand the meaning of loss data? Here is the following code I have written for this program

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <string>

using namespace std;

void getStudInfo(string& fname, string& lname, float& exam1, float& exam2, float& exam3);
float calGPA(int exam1, int exam2, int exam3);
void dispLetterGrade(string fname, string lname, float GPA, char grade);



int main()
{
	int numStud, i;
	float studAvg, exam1, exam2, exam3;
	char grade;
	string fname, lname;
	i = 0;

	cout << "How many students are in the class? ";
	cin >> numStud;
		
	while(i < numStud)
	{
		getStudInfo(fname, lname, exam1, exam2, exam3);
		studAvg = calGPA(exam1, exam2, exam3);
		dispLetterGrade(fname, lname, studAvg, grade);

		i = i + 1;
	}
	
	system("PAUSE");

	return 0;
}


void getStudInfo(string& fname, string& lname, int& exam1, int& exam2, int& exam3)
	
{	

	cout << "Enter student's first name: ";
	cin >> fname;

	cout << "Enter student's last name: ";
	cin >> lname;

	cout << "Enter the score for exam 1: ";
	cin >> exam1;
	if(exam1 >= 0 || exam1 <= 110)
{
	cout << "Sorry that is not a valid entry \n Enter the score for exam 1: ";
	cin >> exam1;
}


	cout << "Enter the score for exam 2: ";
	cin >> exam2;
	if(exam2 >= 0 || exam2 <= 110)
	{
		cout << "Sorry that is not a valid entry \n Enter the score for exam 2: ";
		cin >> exam2;
	}

	
	cout << "Enter the score for exam 3: ";
	cin >> exam3;
	if(exam3 >= 0 || exam3 <= 100)
	{
		cout << "Sorry that is not a valid entry \n Enter the score for exam 3: ";
		cin >> exam3;

	}

}

float calGPA(int exam1, int exam2, int exam3)
{
	float calGPA;
	calGPA = (exam1 + exam2 + exam3)/3;
	return calGPA;
}

void dispLetterGrade(string fname, string lname, float studAvg, char grade)
{
	if (studAvg >= 90)
	{
		grade = 'A';
		
	}

	else if (studAvg >= 80)
	{
		grade = 'B';
	}

	else if (studAvg >= 70)
	{
		grade = 'C';
	}

	else if (studAvg >= 60)
	{
		grade = 'D';
	}

	else if (studAvg >= 59)
	{
		grade = 'F';
	}

	else
		cout << "Invalid test score.\n";

	cout << fname << " " << lname << endl << studAvg << " " << grade << endl;

}


What am I missing? How is this a loss of data going from a int to a float? I thought that int are smaller then floating?
You're actually going from a float to an int here:
studAvg = calGPA(exam1, exam2, exam3);

The floating value is truncated so it is no longer a float and you lose all of that data (you'd go from something like 10.99 to just 10, or 89.99 to 89). This can be an issue for your GPA function.
Ok so I altered the code to work now but once I input the students information it gives this error

Run-Time Check Failure #3 - The variable 'grade' is being used without being initialized.




Here is the code I am using 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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <string>

using namespace std;

void getStudInfo(string& fname, string& lname, int& exam1, int& exam2, int& exam3);
float calGPA(int exam1, int exam2, int exam3);
void dispLetterGrade(string fname, string lname, float GPA, char grade);



int main()
{
	int numStud, i, exam1, exam2, exam3;
	float studAvg;
	char grade;
	string fname, lname;
	i = 0;

	cout << "How many students are in the class? ";
	cin >> numStud;
		
	while(i < numStud)
	{
		getStudInfo(fname, lname, exam1, exam2, exam3);
		studAvg = calGPA(exam1, exam2, exam3);
		dispLetterGrade(fname, lname, studAvg, grade);

		i = i + 1;
	}
	
	system("PAUSE");

	return 0;
}


void getStudInfo(string& fname, string& lname, int& exam1, int& exam2, int& exam3)
	
{	

	cout << "Enter student's first name: ";
	cin >> fname;

	cout << "Enter student's last name: ";
	cin >> lname;

	cout << "Enter the score for exam 1: ";
	cin >> exam1;
	if(exam1 <= 0 || exam1 >= 110)
{
	cout << "Sorry that is not a valid entry \n Enter the score for exam 1: ";
	cin >> exam1;
}


	cout << "Enter the score for exam 2: ";
	cin >> exam2;
	if(exam2 <= 0 || exam2 >= 110)
	{
		cout << "Sorry that is not a valid entry \n Enter the score for exam 2: ";
		cin >> exam2;
	}

	
	cout << "Enter the score for exam 3: ";
	cin >> exam3;
	if(exam3 <= 0 || exam3 >= 100)
	{
		cout << "Sorry that is not a valid entry \n Enter the score for exam 3: ";
		cin >> exam3;

	}

}

float calGPA(int exam1, int exam2, int exam3)
{
	float calGPA;
	calGPA = (exam1 + exam2 + exam3)/3;
	return calGPA;
}

void dispLetterGrade(string fname, string lname, float studAvg, char grade)
{
	if (studAvg >= 90)
	{
		grade = 'A';
		
	}

	else if (studAvg >= 80)
	{
		grade = 'B';
	}

	else if (studAvg >= 70)
	{
		grade = 'C';
	}

	else if (studAvg >= 60)
	{
		grade = 'D';
	}

	else if (studAvg >= 59)
	{
		grade = 'F';
	}

	else
		cout << "Invalid test score.\n";

	cout << fname << " " << lname << endl << studAvg << " " << grade << endl;

}
*facepalm*

It's because you never declare grade in the function dispLetterGrade. Variables in C++ have a lifespan (or scope) for the duration that the variable is allowed to be accessed. Once it reaches the end of the scope, it's removed from the programs memory (still resides in the computers memory, I think) so the program doesn't believe the variable exists anymore. There is a difference between local variables and global variables. Global variables are to be avoided as much as possible (long explanation that isn't need at the moment) while local variables can make code more confusing to understand to a beginner.

For example:
1
2
3
4
5
int main() {
   int myInt = 3;

   return 0;
} // myInt is out of scope 


The first time you see myInt with in a code block { }, that begins it's life span or scope. It's terminated when it reaches the end of that block, noted in the code above. Now, that is considered a local variable since it is only available to the local function, in this case main. Let's say we have another function called in our program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void MyFunc(); // Function Prototype

int main() {
   int myInt = 3;
   MyFunc();
   myValue = 2; // Error! myValue not declared within this scope

   return 0;
} // myInt is out of scope

void MyFunc() { // Function definition
   myInt = 5; // Error! myInt not declared within this scope
   int myValue = 5; // OK! defined as a local variable
} // myValue is out of scope 


So as you can see, each function has to have it's own local variables. This makes sense because you don't want to accidentally modify another function's variable and mess up that code. But we have the option of passing variables one of three ways, by-value, by-reference, and by-pointer.

The most commonly seen one is by-value. This creates a new variable, with whatever name you want, that is local to the function called. This will have the same value as whatever you passed, but nothing will be modified once your function terminates. An example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void MyFunc(int byValue); // Function Prototype

int main() {
   int myInt = 3;
   MyFunc(myInt);
   byValue = 8; // Error! byValue not declared within scope

   return 0;
} // myInt is out of scope

void MyFunc(int byValue) { // Function definition
   // byValue starts with the value of whatever was passed, In this example
   // byValue has the same value as myInt, which is 3
   byValue = 5; // OK! byValue is local to MyFunc
} // myValue is out of scope 


I see you already know how to pass by-reference, and by-pointer is a mix of the two. I hope this has helped you understand what the error means. If you'd like to see more, let me know.
You are such a big help! Ok so what I did was took out the grade portion from the dispLetterGrade and just had the program continue on with the program after it figured out what his studAvg was for the 3 test. Can you offer any advice as to how I can have the calGPA be a floating point value instead of turning it into a integer?

1
2
3
4
5
6
float calGPA(int exam1, int exam2, int exam3)
{
	float calGPA;
	calGPA = (exam1 + exam2 + exam3)/3;
	return calGPA;
}




Here is the code I am now using for this class 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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <string>

using namespace std;

void getStudInfo(string& fname, string& lname, int& exam1, int& exam2, int& exam3);
float calGPA(int exam1, int exam2, int exam3);
void dispLetterGrade(string fname, string lname, float GPA);



int main()
{
	int numStud, i, exam1, exam2, exam3;
	float studAvg;
	char grade;
	string fname, lname;
	i = 0;

	cout << "How many students are in the class? ";
	cin >> numStud;
		
	while(i < numStud)
	{
		getStudInfo(fname, lname, exam1, exam2, exam3);
		studAvg = calGPA(exam1, exam2, exam3);
		dispLetterGrade(fname, lname, studAvg);

	if (studAvg >= 90)
	{
		grade = 'A';
		
	}

	else if (studAvg >= 80)
	{
		grade = 'B';
	}

	else if (studAvg >= 70)
	{
		grade = 'C';
	}

	else if (studAvg >= 60)
	{
		grade = 'D';
	}

	else if (studAvg >= 59)
	{
		grade = 'F';
	}

	else
	{
		cout << "Invalid test score.\n";
	}

	cout << grade << "\n" << "\n";

		i = i + 1;
	}
	
	system("PAUSE");

	return 0;
}


void getStudInfo(string& fname, string& lname, int& exam1, int& exam2, int& exam3)
	
{	

	cout << "Enter student's first name: ";
	cin >> fname;

	cout << "Enter student's last name: ";
	cin >> lname;

	cout << "Enter the score for exam 1: ";
	cin >> exam1;
	if(exam1 <= 0 || exam1 >= 110)
{
	cout << "Sorry that is not a valid entry \n Enter the score for exam 1: ";
	cin >> exam1;
}


	cout << "Enter the score for exam 2: ";
	cin >> exam2;
	if(exam2 <= 0 || exam2 >= 110)
	{
		cout << "Sorry that is not a valid entry \n Enter the score for exam 2: ";
		cin >> exam2;
	}

	
	cout << "Enter the score for exam 3: ";
	cin >> exam3;
	if(exam3 <= 0 || exam3 >= 100)
	{
		cout << "Sorry that is not a valid entry \n Enter the score for exam 3: ";
		cin >> exam3;

	}

}

float calGPA(int exam1, int exam2, int exam3)
{
	float calGPA;
	calGPA = (exam1 + exam2 + exam3)/3;
	return calGPA;
}

void dispLetterGrade(string fname, string lname, float studAvg)
{
	
	cout << fname << " " << lname << endl << studAvg << " ";

}
The reason you're getting an integer back instead of a floating decimal value is because you're (unknowingly) doing something called type casting. Type casting is taking a base variable's data type and converting it into something else. In your case, you're taking three floats and turning them all into ints. This is shown below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Your function prototypes
void getStudInfo(string& fname, string& lname, int& exam1, int& exam2, int& exam3);
float calGPA(int exam1, int exam2, int exam3);
// Skipping a few lines
// ...
// exam1, exam2, and exam3 are all floats in main
// They can accept floating decimal values

// Looking at the protocol for getStudInfo, the function accepts certain parameters
// (string &, string &, int &, int &, int&)
// When you call the function, any decimal value for the last three parameters
//    will be converted to itegers
// This is where you're typing cast (again, unknowingly)
		getStudInfo(fname, lname, exam1, exam2, exam3);
// Same applies to studAvg
		studAvg = calGPA(exam1, exam2, exam3);
		dispLetterGrade(fname, lname, studAvg);


The solution to this: Have you functions accept floats so you're not "losing" information (having the decimal value truncated).

As for the grade issue, you went about it the wrong way. Your function was good before, I didn't read your function correctly and assumed you didn't pass grade, I apologize. The reason you got that error (I believe) is because of your else statement (any value less than 59) doesn't assign grade with a value.

The fix for that would to either have a return statement in there (which effectively will prevent the cout from being displayed) or to assign grade some obscure value (like 'Z'). The first option is ideal, but if you don't understand it, the second one might be a better option.
Last edited on
I just looked into return statements but don't understand what I would return.

I tried to type in just a return but it said it did not match the return type. I went and assigned an X to the value but would like to learn more about the return statement. Where can I find some examples of how to better use this?
I'm referring to your code you posted a bit ago for the dispLetterGrade 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
void dispLetterGrade(string fname, string lname, float studAvg, char grade)
{
	if (studAvg >= 90)
	{
		grade = 'A';
		
	}

	else if (studAvg >= 80)
	{
		grade = 'B';
	}

	else if (studAvg >= 70)
	{
		grade = 'C';
	}

	else if (studAvg >= 60)
	{
		grade = 'D';
	}

	else if (studAvg >= 59)
	{
		grade = 'F';
	}

	else
		cout << "Invalid test score.\n";

	cout << fname << " " << lname << endl << studAvg << " " << grade << endl;

}


You would have to change the else to support more than one statement (bracketless conditionals only support one statement) and add return;.

Every function can return something. That something is identified as the datatype in the function prototype/definition. The datatype is what is before the function's name. In this example, it's void. You can return void, but since void is nothing anyways (rather a place holder for nothing), it's simpler to just write return;

Something to remember though; if your function "returns" anything (even void), the code following the return statement in that function is not ran. Here is a quick example that you'd understand a little better:
1
2
3
4
5
6
7
8
9
10
// Sample function definition
int CalculateSum(int a, int b, int c) {
   int sum = a + b + c;

   return sum; // Function stops here

   // This is never displayed since the function has returned to whatever
   //    function originally called it
   cout << "The sum is " << sum;
}
Ahh this makes perfect sense! I was on the code I had altered and thought the same thing for the return not going any further in the code.
Topic archived. No new replies allowed.