Loops

Pages: 12345... 7
phil123,

I see what you are saying. I had the IsOperator code wrong as well. My bad.

here it is again:

1
2
3
4
bool IsOperator(char symbol){
if ( symbol == '+' || symbol == '-' || symbol == '/' || symbol == '*' )
       return true;
else return false;


Now this should be really clear for everyone (including me :)) The other advantage is that if symbol is an operator, '+' say, then the test evaluates to true as soon as it's particular test is evaluated. so if operator is '+' then symbol == '-' and the ones after it aren't evaluated and the whole test-expression is true.

Good spotting - it has allowed us to fix this - I should sleep more so I don't make silly logical errors. :) :)


Haha, it's all good, I understand what you're saying now as well.

SGM3, I'm going to talk a bit about functions and function prototyping, and a nifty if statement (for fun)

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

int greater (int a, int b); // this is called function prototyping
int lesser (int a, int b); // this allows you to put all your function code BELOW 
						  // your int main() function - it's an organizational thing
// notice how function prototypes in most cases (MOST cases, sometimes they are 
// slightly different! but I won't get into that) are exactly the same as below, except 
// there's a semi-colon after the close bracket
int main()
{
	int a = 2;
	int b = 10;
	int greaterNumber = greater (a, b); // a function with a return statement can initialize
	int lesserNumber = lesser (a, b); // a variable like this

	std::cout << greaterNumber << " is greater than " << lesserNumber << "!\n";
	std::cin.get();
	return 0;
}
 // two simple functions to find out which number is bigger, and smaller (for example sake)
int greater (int a, int b) // your actual function code goes down here
{
     return a > b ? a : b; // neat way of using return
} // if a is GREATER than b, return a, ELSE return b

int lesser (int a, int b)
{
    return a < b ? a : b; 
} // if a is less than b, return a, ELSE return b 


It tells me I cannot use "ShowMenu" as a function.


I can't seem to find the function declaration (or the prototype) for ShowMenu, so that's one possibility.
Last edited on
The showMenu as TheIdeasMan suggested:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//before main(), put these declarations for your functions.

void ShowMenu()                  //I have shown these functions   
                                           //not returning   anything i.e void,
                                           //which is ok for now
void  UseCalculator();           //but generally functions should return some
void PlayGuessingGame();    //sort of status, so you can do error checking
void  EnterText();

//in the main function do this instead
ShowMenu() ;
cin >> MenuOption;
MenuOption = toupper(MenuOption);

switch (MenuOption)
case 'A':
      //call function to do this option eg UseCalculator();
case 'B':
     //call function to do this option eg PlayGuessingGame();
case 'C':
     //call function to do this option eg EnterText();

//put the definition of all your functions after main()  


I inputted the ShowMenu function as the others but it gave me an error when using it.
I am thinking it is because it wasn't in the switch as the other functions are.
If my assumptions are correct, your ShowMenu function should look like this:

1
2
3
4
5
6
7
8
9
10
11
void ShowMenu ()
{
        cout << "\n\t\t\t_______________________________\n"
                    " \t\t\t| What would you like to use? |\n" // Options the program offers
                    " \t\t\t|-----------------------------|\n"
                    " \t\t\t|   (A) Guess the number      |\n"
                    " \t\t\t|   (B) Basic Calculator      |\n"
                    " \t\t\t|   (C) Print your text       |\n"
                    " \t\t\t|_____________________________|"
                    " \n";
}


void ShowMenu (); // function prototype of course

If you ever think something doesn't work, start a new project and an entirely new int main () and test ONLY that function, then copy and paste it into your project. This way, if something goes wrong, it's much easier to debug it
oh.. I feel silly. Thanks

This is really cool. Prototypes make the program easier to understand what is going on.

In my case the functions of the prototypes I don't think can go after the main 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>

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

void ShowMenu ()
{
        cout << "\n\t\t\t_______________________________\n"
                    " \t\t\t| What would you like to use? |\n" // Options the program offers
                    " \t\t\t|-----------------------------|\n"
                    " \t\t\t|   (A) Guess the number      |\n"
                    " \t\t\t|   (B) Basic Calculator      |\n"
                    " \t\t\t|   (C) Print your text       |\n"
                    " \t\t\t|_____________________________|" << endl;
}
void UseCalculator()
{
    cout << "Calculator" << endl;
}
void PlayGuessingGame()
{
    cout << "Guessing game" << endl;
}
void EnterText()
{
    cout << "Enter text" << endl;
}

int main()
{
    string name;
    char MenuOption;
    char ReturnMenu;

    do
    {
        ShowMenu ();
        cin >> MenuOption;
        MenuOption = toupper(MenuOption);

        switch ( MenuOption )
        {

            case 'A':
                UseCalculator();
                break;

            case 'B':
                PlayGuessingGame();
                break;

            case 'C':
                EnterText();
                break;

            default:
            cout << "" << MenuOption << " Is not a choice." << endl;
            break;
        }
        cout << "Would you like to return to main menu? (Y/N)" << endl;
        cin >> ReturnMenu;
        ReturnMenu = toupper(ReturnMenu);
        while ( ReturnMenu != 'Y' && ReturnMenu != 'N')
            {
                cout << "'" << ReturnMenu << "' Is not an option.\n"
                        "Would you like to return to the main menu? (Y/N)";
                        cin >> ReturnMenu;
                        ReturnMenu = toupper(ReturnMenu);
            }
    }
    while ( ReturnMenu == 'Y');
            cout << "\nGoodbye" << endl;
}
In my case the functions of the prototypes I don't think can go after the main function.


Whoa, no no, the function prototypes go before the main function, and the function declarations go after the main function.

1
2
3
4
5
6
7
8
9
10
void blabla (); // function prototype
int main()
{
    // do stuff
    return 0;
}
void blabla () // function declaration
{
    // do more stuff
}


Sorry if I was unclear :o

So:

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

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

void ShowMenu () // move all of these functions down below your main function
                            // then add in the prototypes above your main function
{
        cout << "\n\t\t\t_______________________________\n"
                    " \t\t\t| What would you like to use? |\n" // Options the program offers
                    " \t\t\t|-----------------------------|\n"
                    " \t\t\t|   (A) Guess the number      |\n"
                    " \t\t\t|   (B) Basic Calculator      |\n"
                    " \t\t\t|   (C) Print your text       |\n"
                    " \t\t\t|_____________________________|" << endl;
}
void UseCalculator()
{
    cout << "Calculator" << endl;
}
void PlayGuessingGame()
{
    cout << "Guessing game" << endl;
}
void EnterText()
{
    cout << "Enter text" << endl;
}

int main()
{
    // main function, do stuff, etc
    return 0
}

// functions go down here 

Last edited on
Ok - Let me explain it how I understand it to see if I get it.

void prototype();
above main to declare the function.


1
2
3
4
void prototype()
{
    //function properties.
}
Below main to define properties of the prototype.

Then you can use your prototype as a function within the main.

Also, would I use the functions as the whole program? The functions below the main - Would I input the whole program for say the guessing game?
Last edited on
Yeah, that's perfect. I'll give another example for 100% clarification:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

void message ();

int main()
{
    message ();
    cin.get();
    return 0;
}
void message ()
{
     cout << "Damn straight, I'm mastering these C++ functions!\n";
}
Last edited on
Would I use the prototypes for my programs?

Say the Guessing game. Would I input the entire code for the game in the function?
Yes, any time you create a function you should utilize function prototyping.

Yes, you would input all of the code for the guessing game into the function.
Do you use prototypes specifically for making code easier to understand?

What are other uses for prototypes than what I am using them for?
Why does this not work?

void EnterName();

It skips it when the program runs.

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

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

void EnterName();
void ShowMenu();
void UseCalculator();
void PlayGuessingGame();
void EnterText();

int main()
{
    char MenuOption;
    char ReturnMenu;

    void EnterName();

    do
    {
        ShowMenu ();
        cin >> MenuOption;
        MenuOption = toupper(MenuOption);

        switch ( MenuOption )
        {

            case 'A':
                UseCalculator();
                break;

            case 'B':
                PlayGuessingGame();
                break;

            case 'C':
                EnterText();
                break;

            default:
            cout << "'" << MenuOption << " Is not a choice." << endl;
            break;
        }

            cout << "Would you like to return to main menu? (Y/N)" << endl;
            cin >> ReturnMenu;
            ReturnMenu = toupper(ReturnMenu);

            while ( ReturnMenu != 'Y' && ReturnMenu != 'N')
                {
                    cout << "'" << ReturnMenu << "' Is not an option.\n"
                            "Would you like to return to the main menu? (Y/N)";
                            cin >> ReturnMenu;
                            ReturnMenu = toupper(ReturnMenu);
                }
    }
    while ( ReturnMenu == 'Y');
            cout << "\nGoodbye" << endl;
}

void EnterName()
{
    string name;

    cout << "Hello, Enter name." << endl;
    cin >> name;
    cout << "Hello, " << name << "." << endl;
}

void ShowMenu ()
{
        cout <<     "\n\t\t\t_______________________________\n"
                    " \t\t\t| What would you like to use? |\n" // Options the program offers
                    " \t\t\t|-----------------------------|\n"
                    " \t\t\t|   (A) Guess the number      |\n"
                    " \t\t\t|   (B) Basic Calculator      |\n"
                    " \t\t\t|   (C) Print your text       |\n"
                    " \t\t\t|_____________________________|" << endl;
}
void UseCalculator()
{
    cout << "Calculator" << endl;
}
void PlayGuessingGame()
{
    cout << "Guessing game" << endl;
}
void EnterText()
{
    cout << "Enter text" << endl;
}
Just curious, Instead of these functions and lines of code defining the prototypes. Would it be better to make classes for each program?
You use prototypes so you don't have to put your function declaration above your main function.

I've always wanted to make an educational 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
#include <iostream>
using namespace std;

void print_string (const char * sentence, int times = 2);

int main()
{
	cout << "Today's function prototype:\n"
			"--------------------------\n"
			"void print_string (const char * sentence, int times = 2);\n"
			"---------------------------------------------------------\n"
			"The following function is called, how many times \nwill \"Oh Hai\" be printed to the screen?\n\n"
			"print_string (\"Oh Hai\", 1);\n\n"
			"(Press Enter when you think you know the answer)\n";
	cin.get();
	print_string("Oh Hai", 1);

	cout << "The following function is called, how many times \nwill \"Oh Hai\" be printed to the screen?\n\n"
			"print_string (\"Oh Hai\");\n\n"
			"(Press Enter when you think you know the answer)\n";
	cin.get();
	print_string("Oh Hai");

	cout << "The following function is called, how many times \nwill \"Oh Hai\" be printed to the screen?\n\n"
			"print_string (\"Oh Hai\", 0);\n\n"
			"(Press Enter when you think you know the answer)\n";
	cin.get();
	print_string("Oh Hai" , 0);

	cout << "The following function is called, how many times \nwill \"Oh Hai\" be printed to the screen?\n\n"
			"print_string (\"Oh Hai\", 5);\n\n"
			"(Press Enter when you think you know the answer)\n";
	cin.get();
	print_string("Oh Hai" , 5);

	cin.get();
	return 0;
}

void print_string (const char * sentence, int times)
{
	for ( int i = 0; i < times; i++)
		cout << sentence << endl;
	cout << "---------\n";
}


Copy this into your compiler, and play my game :)

Basically, you can set default values in the function prototype from RIGHT to LEFT. So the following is valid:

void print_string (const char * sentence, int times = 2); // Fine

void print_string (int times = 2, const char * sentence); // BAD

void print_string (const char * sentence, int number, int times = 2); // Fine

void print_string (const char * sentence, int number = 5, int times); // BAD

void print_string (const char * sentence, int number = 5, int times = 2); // Fine


Just curious, Instead of these functions and lines of code defining the prototypes. Would it be better to make classes for each program?


I don't feel that I have enough experience with classes to properly answer this question, sorry. Though I imagine classes are used for larger/more complex programs - perhaps someone else could jump in here and help me out.

void EnterName();

You have a function prototype in your int main, this is a problem.

1
2
3
4
5
6
7
int main ()
{



return 0;
}


Can't seem to find your return 0; any function that has a return type (like int main, with int being the return type) needs a return keyword in it

Edit: Time for sleep, we shall reconvene tomorrow ;p
Last edited on
oh, you all make me feel stupid! ha =)

I had void in there.. I over look minor details sometimes. Need to work on that.

Why do I need to "return 0;" ? What does that do?

0 = ok ?
1 = error ?

Hi,

To call the function in main just do this:

 
EnterName();


this is a function declaration:

void EnterText();

It is a forward declaration and it tells the compiler that the definition of the function is later in the file. If yoou don't have the forward declaration then you need to have the definition of the function before main(). Forward declarations are better because you don't have to scroll through heaps of code before you get to main().

OK, we are on the right track with using functions to divide & conquer. There are 2 things to do now.

1. The processing of the menu option should be a function as well.
2. Change the do while to a while like this:

1
2
3
4
5
6
while ( ReturnMenu == 'Y') {
ProcessMenu()
};

cout << "\nGoodbye" << endl;


See how if you take the body of loop out and put it in function it makes it much easier to understand? If the body of the loop (the stuff between the braces) is more than 10 lines then it could be a candidate for doing this, although sometimes it is done when there are only a few lines.

When you come to extend this by writing the UseCalculator function (and the others) you will have these functions call other functions to do things.


I had another thought about the IsOperator function - we should always keep in mind that things will probably be extended or changed. So what if we had 10 operators? Instead of having a long test expression in the if statement, we should have a switch instead:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool IsOperator(char symbol){
switch (symbol);
{
    case '+'
          return true;
case '-'
          return true;
case '*'
          return true;
case '/'
          return true;
default:
          return false;
}


I haven't put break statements for each case like you would normally do because it will never get past each of the returns. break statements used like this prevent control "falling through" to the next case, which is not usually what you want.

So this is much easier to extend, and easier to read (better all round really).

I haven't seen this method of using cout before:

1
2
3
4
5
6
7
cout <<     "\n\t\t\t_______________________________\n"
                    " \t\t\t| What would you like to use? |\n" // Options the program offers
                    " \t\t\t|-----------------------------|\n"
                    " \t\t\t|   (A) Guess the number      |\n"
                    " \t\t\t|   (B) Basic Calculator      |\n"
                    " \t\t\t|   (C) Print your text       |\n"
                    " \t\t\t|_____________________________|" << endl;


I am more used to individual cout statementslike this:

1
2
3
4
cout << endl;
cout <<  "\t\t\t_______________________________" << endl;
cout << " \t\t\t| What would you like to use? |" << endl;


See how you go.

TheIdeasMan

1
2
3
4
5
6
7
8
9
10
11
bool IsOperator(char symbol)
{
  switch (symbol)
  {
  case '+':
  case '-':
  case '*':
  case '/': return true;
  default:  return false;
  }
}

:)

On the other hand, what good is knowing that it's a valid operator? You'll still have to check what that operator is again to know what to do with it.
Last edited on
Ok - I think I see what you are saying. You are trying to make the program simpler.

Why do I need a do while loop when a while loop is enough for this.

The cases is making everything easy. (I don't have a bunch of braces which was getting confusing.)

Should I eliminate the "do" or just replace the while with a prototype?

If I eliminate the do while how do I right the code within.

A while loop checks the see if a variable is true before it continues. Which causes problems when a while loop is in the beginning of what I want to loop.

Also if I put the menu process eg:
1
2
cin >> MenuOption;
        MenuOption = toupper(MenuOption);


I have to define "MenuOption" twice, locally and global.
I am having issues when I do that. The default case is kicking in "Is not a choice". Even though I am picking a correct choice eg. A, B, or C.
Last edited on
@LowestOne

Yes, your switch statement is easier, It takes advantage of control falling through.

On the other hand, what good is knowing that it's a valid operator? You'll still have to check what that operator is again to know what to do with it.


The concept is to do this:

1
2
3
4
5
if(IsOperator)
    ProcessOperator(symbol);
else{
/// it's something else deal with it here
}


The IsOperator function is reuse of code. IsOperator could be called from many locations in the code. If you don't have this function then you have have the switch statement (possibly quite long) everywhere you want to test if it's an operator.

@SGM3

Einstein once said:


Things should be simple, simple as possible, but no simpler.


A lot of people trip up on the last bit. They try to design something that is too simple for what they need. Put another way: "Things should be simple enough to cater for the complexity of the problem."

Here's another example:

Say you are involved in a software project that has 500,00 lines of code. All that code is NOT going to be in the main() function. It won't even be in 1 file either. Large projects are split into files and these are organised into folders of source code. I have heard of some projects that compile 500 folders worth of code.

So it is the divide & conquer concept.

Cheers TheIdeasMan

I think I figured it out.

Your "ProcessMenu" had a typo which caused the program not to work.

Me (the noob ha) didn't know it was wrong.
You wrote this:
1
2
3
while ( ReturnMenu == 'Y') {
ProcessMenu()
};

Notice the semi colon?

It should be like this:
1
2
3
while ( ReturnMenu == 'Y'); {
ProcessMenu()
}


Get some sleep man! haha

Thank you for your help.

I am going to write my own calculator this time. No more copy and paste =)
Pages: 12345... 7