Help with void functions

Hey guys,

I want to preface this by saying I am trying to teach myself C++ from a textbook I bought. I am a complete beginner to programming, and this isn't for any assignment, this is for my own knowledge.

It seems I may be having trouble with a concept that has to do with void functions. I think perhaps I may not be fully understanding the scope of identifiers, or maybe reference parameters.

The question in the book is as follows:

6. For research purposes and to better help students, the admissions office of your local university wants to know how well female and male students perform in certain courses. You receive a file that contains female and male student GPAs for certain courses. Due to confidentiality, the letter code f is used for female students and m for male students. Every file entry consists of a letter code followed by a GPA. Each line has one entry. The number of entries in the file is unknown. Write a program that computes and outputs the average GPA for both female and male students. Format your results to two decimal places. Your program should use the following functions:
a. Function openFiles: This function opens the input and output files, and sets the output of the floating-point numbers to two decimal places in a fixed decimal format with a decimal point and trailing zeros.
b. Function initialize: This function initializes variables such as countFemale, countMale, sumFemaleGPA, and sumMaleGPA.
c. Function sumGrades: This function finds the sum of the female and male students’ GPAs.
d. Function averageGrade: This function finds the average GPA for female and male students.
e. Function printResults: This function outputs the relevant results. f. There can be no global variables. Use the appropriate parameters to pass
information in and out of functions.

And my code is:

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

using namespace std;

void openFiles(ifstream& inFile, ofstream& outFile);
void initialize(double& countMale, double& countFemale, double& sumMaleGPA, double& sumFemaleGPA, double& avgMaleGPA, double& avgFemaleGPA);
void sumGrades(ifstream& inFile, double& countMale, double& countFemale, double& sumMaleGPA, double&sumFemaleGPA);
void averageGrade(double countMale, double countFemale, double sumMaleGPA, double sumFemaleGPA, double& avgMaleGPA, double& avgFemaleGPA);
void printResults(ofstream& outFile, double avgMaleGPA, double avgFemaleGPA);

int main() {
    
    double sumMaleGPA, sumFemaleGPA, avgMaleGPA, avgFemaleGPA, countMale, countFemale;

    ifstream inFile;
    ofstream outFile;
    
    openFiles(inFile, outFile);
    initialize(countMale, countFemale, sumMaleGPA, sumFemaleGPA, avgMaleGPA, avgFemaleGPA);
    sumGrades(inFile, countMale, countFemale, sumMaleGPA, sumFemaleGPA);
    averageGrade(countMale, countFemale, sumMaleGPA, sumFemaleGPA, avgMaleGPA, avgFemaleGPA);
    printResults(outFile, avgMaleGPA, avgFemaleGPA);
    
    inFile.close();
    outFile.close();
    
    return 0;
}

void openFiles(ifstream& inFile, ofstream& outFile)
{
    inFile.open("GPA.txt");
    outFile.open("avgGPA.txt");
    
    outFile << showpoint << fixed << setprecision(2);
}

void initialize(double& countMale, double& countFemale, double& sumMaleGPA, double& sumFemaleGPA, double& avgMaleGPA, double& avgFemaleGPA)
{
    countMale = 0;
    countFemale = 0;
    sumMaleGPA = 0;
    sumFemaleGPA = 0;
    avgMaleGPA = 0;
    avgFemaleGPA = 0;
    
}

void sumGrades(ifstream& inFile, double& countMale, double& countFemale, double& sumMaleGPA, double&sumFemaleGPA)
{
    char gender;
    double gpa;
    
    inFile >> gender;
    
    while (!inFile.eof())
    {
        if (gender == 'm')
        {
            countMale++;
            inFile >> gpa;
            sumMaleGPA += gpa;
            inFile.ignore(5 , '\n');
        }
        else if (gender == 'f')
        {
            countFemale++;
            inFile >> gpa;
            sumFemaleGPA += gpa;
            inFile.ignore(5 , '\n');
        }
        
        inFile >> gender;
    }
}

void averageGrade(double countMale, double countFemale, double sumMaleGPA, double sumFemaleGPA, double& avgMaleGPA, double& avgFemaleGPA)
{
    avgMaleGPA = sumMaleGPA / countMale;
    avgFemaleGPA = sumFemaleGPA / countFemale;
}

void printResults(ofstream& outFile, double avgMaleGPA, double avgFemaleGPA)
{
    outFile << "GENDER GPA ANALYSIS..." << endl << endl << left << setw(15) << "AVG Male GPA:" << right << setw(7) << avgMaleGPA << endl << left << setw(15) << "AVG Female GPA:" << right << setw(7) << avgFemaleGPA;


The input txt file I created reads:

m 3.90
f 4.00
m 3.43
f 2.97
f 3.41
f 2.31
m 2.70
m 3.67
f 3.82
f 3.42
m 3.12
m 2.03
m 3.96
f 2.97
m 2.43
m 3.56
f 2.99
f 3.74
f 3.21
m 3.65
m 3.42
f 3.12
m 3.78

The output comes out formatted correctly but comes out with nan for the average GPA's. I believe this is due to a division by 0 because when I cout countMale and countFemale at the end of main() I get 0 for both (as well as for sumMaleGPA and sumFemaleGPA). I get nan when I cout avgMaleGPA or avgFemaleGPA.

I am clearly not understanding something. Any type of explanation will be appreciated! :)

Thanks!
Last edited on
For reference parameters, first remember what references are. They're an alias, or whatever the term, for another object that give you access to the object it's referencing. So when you have a reference parameter, it means when you call that function with an argument, that ref. parameter is now an alias to the argument and will give you direct access to the original argument object in this called function.

As for the scope, the reference parameter is in scope for the function in which it is declared (local scope), like most variables in a function. Void also has no return type, so references parameters give us a good way to "return" values indiretcly.

There are different types of scope. When you're declaring variables in a function, the variable exists only in that function ("local scope") and once the function block ends, the variable is destroyed (unless it is static). When we call function B from function A passing an argument x, control is transfered to B, the reference is initialized and assigned (linked) to x, now while in B we can edit the x directly through the reference even though x exists in scope only in A. Once B ends, the reference is destroyed, x still exists, and control goes back to A.

I hope I explained that correctly and it helped?
Last edited on
Thanks! That was a really nice way to sum it up! I think I've got it now.

Turns out the program works fine as it is, I just made a dumb mistake in opening up the txt file.
Topic archived. No new replies allowed.