Loops

Pages: 1234... 7
I am working on the next portion of the program - Option B the calculator.
There is some problems. I am running into problems with looping the calculator at the end of an equation or when I try to clear the data. I also have issues with exiting the program on command.

I think I took Phil123's knowledge into a lot of consideration. I cannot see what is wrong. Though some of the "error checking" may be conflicting with loops. It seems like the program should run fine with these "conflicts" due to my limited understanding. I think it runs in a serious of checks - like a check list in chronological order. I may be wrong.

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
if (Game == 'b' || Game == 'B')  // Option B
    {
        cout << "\nBasic Calculator\n"  // Option Name
                "\n";

       do
    {
        cout << "Enter first number:            0 to exit\n> ";
        cin >> cnum;    // Enter first number for calculation

        while (cnum >= 'a' && cnum >= 'A' && cin.fail())    // Error checking for first number input
        {
                    cin.clear();
                    cin.ignore(1000, '\n');
                    cout << "\nInvalid input. Enter first number:\n" ;
                    cin >> cnum;
        }

        if (cnum != 0)  // If first number doesn't equal close 0 continue
        {
                cout << "\nEnter a operator (+ - / *) (C to clear)";

            do
            {
                cout << "\n> ";  // Enter operator
                cin >> symbol;

                while ( symbol != '+' && symbol != '-' && symbol != '/' && symbol != '*' && symbol != 'c' && symbol != 'C' && symbol != 0 && cin.fail())
                {
                    cin.clear();        //Error checking for operator input
                    cin.ignore(1000, '\n');
                    cout << "\nInvalid input. Enter a operator (+ - / *) (C to clear):\n" ;
                    cin >> symbol;
                }

                if (symbol != 'c' && symbol != 'C' && symbol != 0)      // If operator doesn't equal clear (c) or close 0 continue
                {
                    cout << "\nEnter second number (E to clear):\n>";
                    cin >> newNum;      // Enter second number for calculation

                    while ( newNum >= 'a' && newNum >= 'A' && cin.fail())
                {
                    cin.clear();            //Error checking second number input
                    cin.ignore(1000, '\n');
                    cout << "\nInvalid input. Enter second number (C to clear):\n" ;
                    cin >> newNum;
                }

                    switch (symbol)
                    {
                        case '*':
                            ansnum = cnum*newNum;      // Multiply input
                            cout << "\n= " << ansnum;
                            break;



							case '-':
                            ansnum = cnum-newNum;       // Subtract unput
                            cout << "\n= " << ansnum;
                            break;


							case '+':
                            ansnum = cnum+newNum;       // Add input
                            cout << "\n= " << ansnum;
                            break;



							case '/':
                            ansnum = cnum / newNum;     // Divide input
                            cout << "\n= " << ansnum;
                            break;

                        default:        //if anything else occurs
                            break;

                    }
                }

            } while (symbol != 'c' || symbol != 'C');   // If input cleared C, loop
        }
    } while (cnum != 0 && symbol != 0 && newNum != 0);  // If user inputs close 0, end
    }
This is not the proper way to check to see if someone entered a correct value:
1
2
3
4
5
6
7
        while (cnum >= 'a' && cnum >= 'A' && cin.fail())    // Error checking for first number input
        {
                    cin.clear();
                    cin.ignore(1000, '\n');
                    cout << "\nInvalid input. Enter first number:\n" ;
                    cin >> cnum;
        }


This:
1
2
3
4
5
6
        if (cnum != 0)  // If first number doesn't equal close 0 continue
        {
                cout << "\nEnter a operator (+ - / *) (C to clear)";

            do
            {

} while (symbol != 'c' || symbol != 'C'); // If input cleared C, loop

Will loop until you "clear" your calculator. This is the only way to stop the calculator.

Then you need to change symbol to 0 which would be impossible, cnum would have to be zero, which isn't smart, and newNum would have to be zero which is also impossible.

You need to rethink your calculator.
Hi,
It seems you have two topics about the same subject.

I have been writing heaps into the calculator topic, while everyone else has been writing heaps into this topic (loops)

Still think you need to abandon this code.

TheIdeasMan
Sorry, I should qualify that a bit.

Still think you need to abandon this code, because of the reasons I mentioned in the calculator topic.

TheIdeasMan

You have the right idea. Everything looks good. I would also surround the menu in another do while. Let's say the user guesses a number but then wants to use your calculator. They would need to relaunch your application. This way when they're done guessing a number, they'll be asked what to do next.


I have some different ideas (Even though I have tried hard to talk you out of using this code at all, if we are going to persist - here we go):

Try putting the code ( and only this code) that does the main menu selction, into main().
Then call functions that do the actual work of the menu selection. This will save the outer most loop.

The same thing for the do while and while loops: put the code inside the braces into a function that is called from the loop. This will make it easier to understand the logic of all these loops and simplify the code bigtime.

Do you really need to use a do while loop instead of a while loop? They are almost the same. A while loop does it's test at the start, whereas a do while does the test at the end and is always executed at least once. A problem that you have is that the test expression for the do while is 78 lines of code down the file, which makes it harder to sort out what's going on.

In practice do whiles are rarely used, you can nearly always use a while loop instead and in this case I think it wil be easier to understand as well.

TheIdeasMan



I thought you were just referring to the calculator, when you said abandon it. I will look for better ways to accomplish the same task but, unfortunately I don't have the knowledge yet.

As for the Do While loops - I thought (which isn't saying much..ha) I needed them to ensure my program runs at-least once. Then if the user chooses to return to the main menu at the end of the guessing game they could. I am not sure how to accomplish the same task, using while loops and all the "checks" I implemented.

I have limited knowledge and am trying to put myself in a challenging situation to better understand Loops and IF statements before I move onto switches.
Ok, these are almost the same:

1
2
3
4
5

while(test-expression){
   // multiple lines of code
};


1
2
3
4
5

do {
 // multiple lines of code
}while(test-expression);


if the test-expression is the same, then the only difference is that the do while executes the code in braces before testing the test-expression. The code in braces is always executed at least once.

With the while loop, test-expression is tested first, and that determines whether the code in braces is executed or not. The test -expression is the opposite way around compared to the do while.

Both of these loops will execute the code multiple times as long as the test-expression is true.



I am not sure how to accomplish the same task, using while loops and all the "checks" I implemented.



I hope you can see that this is pretty easy from the code snippets above. The code inside the braces stays the same, it just needs the while(test-expression) before the braces. The test-expression should be reversed.

Did you understand this bit?



Try putting the code ( and only this code) that does the main menu selction, into main().
Then call functions that do the actual work of the menu selection. This will save the outer most loop.

The same thing for the do while and while loops: put the code inside the braces into a function that is called from the loop. This will make it easier to understand the logic of all these loops and simplify the code bigtime.




Here's another thought:

If you convert the user response to upper case then you won't have to test for upper and lower case. Google toupper() function or C++ string. If you use C++ strings instead of C chars, you will be able call this function from the object with the dot operator.

TheIdeasMan
Last edited on
I thought (which isn't saying much..ha)


This idea is toxic to your well being. Everyone's had to start somewhere, so just because you have trouble with something doesn't mean that it's the end of the world. In fact, when I first started programming, it took me 2 hours to figure out how to print "Hello world!" to the screen (due to an issue that wasn't related to the actual code I was typing).

Always be positive - programming isn't something where you flick a switch, and suddenly you're the most versatile/brilliant programmer in the world. So be positive, and smile when you have to debug something complex :)
I am positive. I meant that statement in a humorous fashion. I am enjoying every bit of this. I am out of college for the summer and am hooked. Trying really hard to understand.
I don't think I am doing the toupper correct.

There is a lot of different ways to represent the toupper on the internet. Is some outdated?

This is what I have so far for the menu:

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


using namespace std;

int main()
{
    string name;
    char num = 'a' && 'b' && 'c';

    cout << "Enter your name\n";
    cin >> name;
    cout << "Hello, " << name << "\n";

    cout << "What would you like to use?\n"
            "(A) Calculator\n"
            "(B) Guessing Game\n"
            "(C) Enter Text\n";
            num=toupper('a');
            num=toupper('b');
            num=toupper('c');
            cin >> num;

            while ( num == 'A')
            {
                cout << "Hello";
            }

            while ( num == 'B')
            {
                cout << "hi";
            }

            while ( num == 'C')
            {
                cout << "hi";
            }
}
Haha ok, as long as you don't beat yourself up over something.

1
2
3
// get char input
// then convert char to upper case
// I don't remember the specific code for it, so you'd have to look it up 
Hi,

First up, I must have been a bit discombobulated this morning when I was talking about the test-expressions in while loops. I said that they were opposite to those in a do while, which is wrong (no one noticed?). I had it right to start with, then edited it to make it wrong - My really Bad.

Ok, if you are to use cout, then use endl instead of \n.

 
cout << "What would you like to use?" << endl;


Do the toupper function once, then use the result in a switch statement, like this:

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() 


You seem to have a thing for loops: Even as you code stands the while's should have been if statements. The while loops you have are infinite and would continuously print text.

You should also have other functions ( such as ProcessOperator(symbol) that takes code out of your loop, making it easier to understand.

Also

 
while ( symbol != '+' && symbol != '-' && symbol != '/' && symbol != '*' && symbol != 'c' && symbol != 'C' && symbol != 0 && cin.fail())


You still have &&'s when they should be ||'s.

Instead of having a big long test-expression, write a function bool IsOperator(symbol) . Then you can do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//before main
 bool IsOperator(char symbol);


while (IsOperator(symbol) == false){
      ProcessOperator(symbol);
}

//after the end of the main() function ie after main's closing brace
//put all the other function definitions here

 bool IsOperator(char symbol){
if ( symbol != '+' || symbol != '-' || symbol != '/' || symbol != '*' )
       return true;
else return false;
}


You could do a similar thing for IsQuit and IsClearInput even though they would only be 1 line of code, it would make things easier to maintain later.

I don't see where ansnum is declared, and all these values read in with cin should be floats or doubles because of the multiplication and division. At the moment it does integer multiplication and division, which is not what you need.

So declare a bunch of variables as doubles to hold the values you read in. C++ allows "on the fly declarations" whereby you can declare a new variable anywhere. Don't declare new things inside loops though. In C, all the declaration go together near the top of the file, or for local variables, at the beginning of the function.

Finally, I have been telling this multiple times:

Don't do this:

 
using namespace std;


Newbies do this because thats what they see in textbooks.
If you are only cin and cout and string ,Do this instead:

1
2
3
using std::cin;
using  std::cout;
using  std::string;


It makes it a lot easier on the compiler/ optimiser because it doesn't bring in all the other stuff that is in std:: (and there is lots of it) It won't make any difference to your program either way, it's a matter of style and it's what professional programmers do.

Let us know how you go with all this. Don't worry everyone has to start somewhere, and you have a good attitude I think :)


TheIdeasMan


I found this website :

http://users.powernet.co.uk/eton/kandr2/krx4.html


The code was a bit longer than what I thought and maybe it looks scary to you, but it will be good for you to understand how it works. This is code from the guys who invented the C language.

Once you feel confident, you could try some of the exercises.

TheIdeasMan
Also

while ( symbol != '+' && symbol != '-' && symbol != '/' && symbol != '*' && symbol != 'c' && symbol != 'C' && symbol != 0 && cin.fail())

You still have &&'s when they should be ||'s.


I agree with the rest of your post, but if these were || (ors) instead of && (ands) then this while loop would run forever. With &&, this basically tests if variable symbol is not equal to any of these operators. Say you had symbol +, if he had || (ors) in there, then it'd run forever since + is not equal to - / * c or C, so be careful. I like your idea with the isoperator function though.
Phil123,

I disagree:

The variable symbol can only have one value at a time. symbol cannot be '+' and at the same time be '-'.

Consider this:

1
2
3
int a =1;

if (a ==1 && a ==2)  //always false because a is 1. a can never be 1 and 2 at      //                              the same time 


is not equal to any of these

says that the || should separate the tests.

whereas "is not equal to all of these" says && should be used, but this is impossible because we only have 1 variable.

here's an example of where to use &&:

1
2
3
4
5
6
int a =1;
int b=2;

if (a==1 && b==2){ //2 variables
//execute this code
}


Hope this makes it clear.
TheIdeasMan


1
2
3
4
5
6
7
8
9
10
11
int main()
{

using namespace std;
char symbol = 'h'; // wrong input!!
if (symbol != '*' && symbol != '+' && symbol != '-' && symbol != '/')
    cout << "Invalid input!\n";

cin.get();
return 0;
}


Is an example of what I meant. What I'm saying only works with the not equal to operator (!=). We're testing to ensure that symbol equals to one of the operators for the calculator function, if it doesn't, then we tell the user they made a typo, and prompt them for input again.
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
5
6
7

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. :) :)

TheIdeasMan
I read your first post with lots of information. I kept seeing this:

1
2
3
using std::cin;
using  std::cout;
using  std::string;


all over the internet and wasn't sure if it was a older style in C++. It makes sense to import the tools you are going to use instead of taking them all.
Logic would tell me (as you mentioned) this would be a lot easier when compiling a huge program instead of sifting through all of the tools you don't use.

I also enjoy seeing two people who know what is going on discuss the way to go about coding. Helps clarify things.

Just got home. I will look over this with more detail. In a bit. Have to start dinner.
There's a reason HP doesn't make calculators anymore, and that's because RPN is not an intuitive way to input data.
This is my outline:

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 UseCalculator()
{
    cout << "Calculator" << endl;
}
void PlayGuessingGame()
{
    cout << "Guessing game" << endl;
}
void EnterText()
{
    cout << "Enter text" << endl;
}

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

    cout << "Enter your name" << endl;
    cin >> name;
    cout << "Hello, " << name << "\n" << endl;

    do
    {
        cout << "What would you like to use?\n"
                "(A) Calculator\n"
                "(B) Guessing game\n"
                "(C) Enter text" << endl;
        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;
}


I am not sure why I need:
void ShowMenu()
When I input it along with the:
1
2
3
ShowMenu() ;
cin >> MenuOption;
MenuOption = toupper(MenuOption);

It tells me I cannot use "ShowMenu" as a function.
Last edited on
Pages: 1234... 7