Pass by reference/Pass by value/Parameters/Functions

I cannot figure out how to use parameters with functions. In the code, I have a functions for getting data, displaying a menu, processing the menu choice, and then depending on what option you selected in the menu, it will perform a test on the user's input from the getting data function, such as determining whether it is positive or negative, or determining if it is odd or even. My question is related specifically related passing by value and passing by reference. I am not sure how to think about these things in the context of a menu. All of the examples I've seen involve random assignment operators and similar things. In my displayMenu function, I am supposed to have a variable that holds the menu choice (using pass by reference). In processMenuChoice, I am supposed to pass by value the variable that holds the menuchoice, and then pass by reference the variable that holds the number. I included all of my code so far for context, but my main question is related to the parameters in the 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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <iostream>
#include <iomanip>

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

int getData();
void displayMenu();
void processMenuChoice();
void isPosNeg();
void isOddEven();


int main()
{
	cout << "You entered " << getData(); 
	displayMenu();
	 processMenuChoice();
	
	return 0;
}

int getData()
{
	int number;
	cout << "Please enter a number: ";
		cin >> number;
		while (number < -1000000 || number > 1000000) {
			cout << "Error. Please enter a valid number."
			     << "\nPlease enter a number: ";
			cin >> number;
		}
	return number;
}

void displayMenu (int & menuChoice)
{
   cout << "\n1) Is the number odd or even?\n"                          
		<< "2) Is the number positive or negative?\n"                 
		<< "3) What is the square root of the number?\n"
		<< "4) How many digits are in the number?\n"
		<< "5) Digit Extraction.\n"
		<< "6) Display Addition Table.\n"
		<< "7) Display Multiplication Table.\n"
		<< "8) Exit\n";
}

void processMenuChoice(int & choice)
{
	int choice = 0;
	cout << "\nEnter a menu choice: ";
	cin >> choice;

	switch (choice)
	{
	case 1:
		isPosNeg();
		break;
	case 2:
		isOddEven();
	case 3:
		cout << "You chose option 3." << endl;
		break;
	}
}

	void isPosNeg()
	{
		if (getData > 0)                                    
			cout << "The number is positive!\n";
		else if (getData < 0)                                 
			cout << "The number is negative!\n";
		else if (getData == 0)
			cout << "The number you entered was a zero and is neither positive or negative\n";
	}

	void isOddEven()
	{
		if (getData % 2 == 0 && getData != 0)                    
			cout << "The number is even.\n";
		else if (getData % 2 == 1)                              
			cout << "The number is odd.\n";
		else if (getData == 0)
			cout << "The number you entered is a 0 and is not even or odd.\n";
	}



Last edited on
Like this.
1
2
3
4
5
6
7
8
9
10
	void isPosNeg()
	{
		int answer = getData();  // call it, once
		if (answer > 0)                                    
			cout << "The number is positive!\n";
		else if (answer < 0)                                 
			cout << "The number is negative!\n";
		else if (answer == 0)
			cout << "The number you entered was a zero and is neither positive or negative\n";
	}

1
2
3
int choice = 0;
	cout << "\nEnter a menu choice: ";
	cin >> choice;



From your description, this should be in displayMenu() (with choice replaced by menuChocie) - that's why menuChoice is passed by ref. Then in processMenuChoice(), choice is passed by value as required.

Also case 2: requires a break; statement.
Last edited on
Hello runningbear,


My question is related specifically related passing by value and passing by reference. I am not sure how to think about these things in the context of a menu.


It tends to work like this.

As an example void processMenuChoice(int choice) is pass by value. This makes a copy of the variable to use in the function. This is fine for things like "char"s, "int"s or "double"s. Making a copy is not that expensive to do. Things like "string"s, "vector"s and other containers can take a lot of memory to make a copy.

The pass by reference is, If I have this correct, is passing the address of a variable, so if you make any change to this variable it is changed back where the function was called from and the variable defined.

I made these changes to "main" to demonstrate the pass by reference.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
    int choice{};  // <--- Defined here to pass by reference.

    //cout << "You entered " << getData();

    displayMenu();

    std::cout << "\n   choice B4 function call - " << choice << "\n\n";

    processMenuChoice(choice);

    std::cout << "\n   choice after function call - " << choice << '\n';

    return 0;  // <--- Not required, but makes a good break point.
}

One thing to make this work is that the prototype and function must match. When you call the function only the variable name is needed.

The 2 "cout" statements are for demonstration and need to be removed later as they are not needed.

As seeplus pointed out the function "displayMenu":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void displayMenu()  // <--- Needs variable passed by reference.
{
    std::cout << '\n' << std::string((41 / 2) - (9 / 2), ' ') << "MAIN MENU\n" << std::string(41, '-') << "\n";

    cout << "\n"
        "1) Is the number odd or even?\n"
        "2) Is the number positive or negative?\n"
        "3) What is the square root of the number?\n"
        "4) How many digits are in the number?\n"
        "5) Digit Extraction.\n"
        "6) Display Addition Table.\n"
        "7) Display Multiplication Table.\n"
        "8) Exit\n";
    // <--- Needs the input from "processMenuChoice".
}

void processMenuChoice(int & choice)  // <--- This should be "const int& choice" or just passed by value. And you still
                                      // could make that a "const" as the function should not change its value.
{
    //int choice = 0;  // <--- This is a redefinition of the parameter passed to the function. And an error.

    cout << " Enter a menu choice: ";  // <--- These would be better in "displayMenu" function.
    cin >> choice;


In your 2 "is" functions: if (getData > 0) the compiler is looking for the variable "getData", but you have not defined it in the function. You could do what salem c suggested, I found that making them function calls did not work. "getData()" was called to many times.

Andy

Ok so this is my reasoning right now. I think what's going on is I'm trying to read in from the keyboard a value for a variable menuChoice, and then (this is where I am lost) pass an alias that represents that variable. So I tried to define an alias to the variable and then use that in the parameter list, but it does not work. If I put (int & alias) as parameters the & alias is greyed out. The parameter needs to be initialized within main but I really have no idea how to do that.
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
#include <iostream>
#include <iomanip>

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

int getData();
void displayMenu(int & val);
void processMenuChoice();
void isPosNeg();
void isOddEven();
	
int main()
{
	
	int val = 0;
	int result = displayMenu(val);
	cout << "You entered " << getData();
	cout << "You selected" << result;

	return 0;
}

int getData()
{
	int number;
	cout << "Please enter a number: ";
		cin >> number;
		while (number < -1000000 || number > 1000000) {
			cout << "Error. Please enter a valid number."
			     << "\nPlease enter a number: ";
			cin >> number;
		}
	return number;
}

void displayMenu (int & val)
{	
   cout << "\n1) Is the number odd or even?\n"                          
		<< "2) Is the number positive or negative?\n"                 
		<< "3) What is the square root of the number?\n"
		<< "4) How many digits are in the number?\n"
		<< "5) Digit Extraction.\n"
		<< "6) Display Addition Table.\n"
		<< "7) Display Multiplication Table.\n"
		<< "8) Exit\n";
   int menuChoice = 0;  
	 cout << "\nEnter a menu choice: ";
	 cin >> menuChoice;
	int val = menuChoice;
}

void processMenuChoice(int val)
{
	switch (val)
	{
	case 1:
		isPosNeg();
		break;
	case 2:
		isOddEven();
		break;
	}
}

	void isPosNeg( int number)
	{
		int answer = getData();
		if (answer > 0)                                    
			cout << "The number is positive!\n";
		else if (answer < 0)                                 
			cout << "The number is negative!\n";
		else if (answer == 0)
			cout << "The number you entered was a zero and is neither positive or negative\n";
	}

	void isOddEven()
	{
		int answer = getData();
		if (answer % 2 == 0 && answer != 0)                    
			cout << "The number is even.\n";
		else if (answer % 2 == 1)                              
			cout << "The number is odd.\n";
		else if (answer == 0)
			cout << "The number you entered is a 0 and is not even or odd.\n";
	}

Last edited on
Hello runningbear,

When I tried to compile the program there was some errors that need to be addressed.

From the beginning: Your prototypes are good in that you have 1 for every function, but after that some are wrong.

The "int getData();" works if you need this function to return a value, but maybe the assignment is ment to pass a variable by reference?

The "void displayMenu(int & val);" Works and has the right parameter.

The "void processMenuChoice();" 1st the prototype needs to match the function definition. And this function needs 2 parameters.

"void isPosNeg();" and "void isOddEven();" I believe these are wrong as I think they need at least 1 parameter, but not important yet to deal with.

At this point debugging the code should be done in much the same way as you should have written the code, i.e., in small steps. Step 1 would be dealing with the "displayMenu" function. You need to get that working properly before you go to step 2 the "processMenuChoice" function. Without a valid choice from "displayMenu" there is not much point in the "processMenuChoice" unless you want to add more code than you need.

Replace you "main" function with this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
    int menuChoice = 0;

    std::cout << "\n  B4 the function call the value of menuChoice = " << menuChoice << "\n\n";
    
    /*int result = */displayMenu(menuChoice);

    std::cout << "\n  After the function call the value of menuChoice = " << menuChoice << "\n\n";
    
    // <--- These lines I do not understand what they are for yet, but it is becomming more clear. Not important yet.
    //cout << "You entered " << getData();
    //cout << "You selected" << result;

    return 0;  // <--- Not required, but makes a good break point.
}

This is not meant to replace what you have permenantly, but to help understand the pass by reference part.

When "main" calls "displayMenu" you do have a problem:

  B4 the function call the value of menuChoice = 0

1) Is the number odd or even?
2) Is the number positive or negative?
3) What is the square root of the number?
4) How many digits are in the number?
5) Digit Extraction.
6) Display Addition Table.
7) Display Multiplication Table.
8) Exit
  Enter a menu choice: 10

  After the function call the value of menuChoice = 10  


As you can see the function does allow the entry of an invalid choice. You can either take care of this in the "displayMenu" function or later in "processMenuChoice". If you take of an invalid menu choice later this will cause some big changes in the "processMenuChoice" function. Easier to deal with everything in the "displayMenu" function.

Here is an example. I know there are better ways to write this function, but I am thinking that this would be easier to understand at first. Save the improvements for later. For now understand how it works.
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
void displayMenu(int & menuChoice)
{
    do
    {
        cout <<
            "\n1) Is the number odd or even?\n"
            "2) Is the number positive or negative?\n"
            "3) What is the square root of the number?\n"
            "4) How many digits are in the number?\n"
            "5) Digit Extraction.\n"
            "6) Display Addition Table.\n"
            "7) Display Multiplication Table.\n"
            "8) Exit\n"
            "  Enter a menu choice: ";
        cin >> menuChoice;

        if (!std::cin || (menuChoice < 1 || menuChoice > 8))
        {
            if (!std::cin)
            {
                std::cerr<<"\n     Invalid Input! Must be a number.\n\n";

                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
            }
            else if (menuChoice < 1 || menuChoice > 8)
            {
                std::cerr << "\n     Invalid menu Choice! Try again.\n\n";
            }
        }
    } while (menuChoice < 1 || menuChoice > 8);
}

The do/while loop keeps you in the function until you have entered a valid menu choice.

In your cout statement the insertion operator (<<) is not necessary. Only the first 1 is. Since everything is a quoted string I believe that "cout" will see this as 1 big string before it sends it to the display.

The first part of the first if statement will become true if anything other than a number is entered. Otherwise "cin" will be in a failed state and unusable anywhere in the program until it is fixed. Also there a chance that "menuChoice" may be set to zero if "cin" fails and that is not what you want.

When everything is correct the function will end and return to "main". The variable "menuChoice" being passed by reference will change the value of "menuChoice" in "main".

After this much is working you can move on to the "processMenuChoice" function. Doing whatever is need to send the correct parameters to the function.

An after thought. Your function void displayMenu(int & val) it is acceptable to change the name of the variable in the function, but I find it easier to work with if you do not change the name. Here "menuChoice" gives the function a better understanding of what you are using than "val" does. Also whether the variable is defined as a function parameter or after the opening { it is a local variable to the function. Only the pass by reference makes any difference, but it does not matter what the variable name is in the function.

Now that I have made changes to the the 1st part "displayMenu" I will add and work on the "processMenuChoice" function.

Andy
Topic archived. No new replies allowed.