Loops

Pages: 1... 34567
ok, That worked.

I do see what you did but there is a problem. If you left out cin.ignore(1000, '\n'); If the user entered a letter the loop would continuously run. I put it back. Is continue; a form of loop ?
Also, When asked to play again if the user inputs anything other than 'Y' it brings you back to the menu. I don't like that. (To change, can I add another case to the bool?)

How can I globally define something to be used in these functions. I noticed that I will have to insert bool PlayAgain = true; every-time I want to use it.
Last edited on
Also, When asked to play again if the user inputs anything other than 'Y' it brings you back to the menu. I don't like that.


Why is that a problem? The user didn't enter positive response, so they don't want to play that game anymore, so why is going back to the main menu no good?

Your use of cin.ignore is ok, I hadn't used that before.

continue starts execution at the beginning of a loop again as per the comment I put in.

How can I globally define something to be used in these functions. I noticed that I will have to insert bool PlayAgain = true; every-time I want to use it.


At the moment you do have another PlayAgain inside each function that wants to use it because the scope of local variables only lasts inside a function. A global variable seems like a good idea, but is bad form because they can get out of control.

The other way is to pass a pointer to the variable concerned to the function that needs it. I didn't do this because this is harder and creating a new PlayAgain inside each function is a reasonable soultion.

It's bad because to me it seems lazy and if the user input a typo it boots them out of the game.

Ok - It probably is best for me to put of global variables for now. Have a lot on my plate.
Sorry I didn't read your earlier post properly.

(To change, can I add another case to the bool?)


bool is just a type, what you mean is add another case to the switch in the WantToPlayAgain function. The answer to that is yes, say add Q means the same as N, but that is unnessary because you asked for a y/n answer. I'm not sure why you would want to do that. If you mean that the user types 't' or 'u' instead of 'y' - I think that is going a bit overboard at this stage

Ok - It probably is best for me to put of global variables for now. Have a lot on my plate.


There is no need, just put

bool PlayAgain = true;

in the function that needs to use it. I was trying to discourage you from using global variables - stick with what we have now.

You should write some code in the menu functions that just print text, so that the user can get back to the main menu.

Edit: I mean the UseCalculator function
Last edited on
What does this all mean?
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;
}

I have to create a prototype ProcessOperator(symbol)
I cannot put void in front of it.

I get all sorts of errors. I'm doing something wrong.

1
2
3
4
5
bool IsOperator(char symbol);

ProcessOperator(symbol);

int main()


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
void UseCalculator()
{
    int cnum, newNum, ansnum; // Calc numbers
    char symbol;      // Calc oporators
    bool PlayAgain = true;

    cout << "\nCalculator" << endl;

    while ( PlayAgain == true )
    {
        cout << "Enter a number: "<< endl;
        cin >> cnum;
        cnum =(toupper(cnum));

        if (cnum >= 'A' || cin.fail())
        {
            cin.clear();
            cin.ignore(1000, '\n');
            cout << "Invalid input." << endl;
            continue;

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

        }

        PlayAgain = WantToPlayAgain();
    }
}

I have to define something within. Not sure what to define and how to define it.
I know the continue; is a cheap fix and I cannot do that for the second number. I was thinking I would input a while loop, for the second number. I think it would be more efficient to do so, instead of creating two separate functions. Considering each number will have its own variable.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// below main brace
bool IsOperator(char symbol)
{
    if ( symbol != '+' && symbol != '-' && symbol != '/' && symbol != '*' )
       return true;
        else return false;
}
ProcessOperator(symbol)
{
    bool symbol = false;

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


I may be getting a little loopy. Been working on this over 12 hours straight, with a laundry or bathroom break. =)
Feel silly saying 12 hours... You could write this in a hour? ha

Last edited on
So we are back to the calculator again. I will explain a few things but we need to go back to basics and do a design.

Rightoh here we go. :)

ProcessOperator() is a function just like the other functions, it needs to have a declaration near the top of the file with all the other ones, and a definition after main like the other functions. The purpose of ProcessOperator is to replace a bunch of code with a function call.

1
2
3
4
5
bool IsOperator(char symbol);

float ProcessOperator(symbol);

int main()


The return type is float (or double) because we are going to return the answer and an integer type won't work because of the division and multiplication.

So These need to be floats or doubles:

int cnum, newNum, ansnum; // Calc numbers

Put them on their own lines so you can document them: I have renamed them as well.

1
2
3
float FirstNumber;    //cnum The first number in + - * / calculation
float SecondNumber;    //newNum The second number in + - * / calculation
float  Answer; // ansnum  The answer of the + - * / calculation 


the definition of ProcessOperator(symbol) goes after main() but we will get back to this once we have completed the design.

So our design method is to write comments to explain our methodology for how we are going to solve our problem. Once the design is finished we can go back and write the code between the comments. Here is an outline, you can have go at filling in more details.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void UseCalculator() 
{
// declare variables

PlayAgain = true;
while ( PlayAgain == true ) {
     // get first number
            //check it is a number find a built in function for this
     // get second number
            //check it is a number
     // get the operator
            //check it is a operator IsOperator(Operator)

Answer =    ProcessOperator( FirstNumber, SecondNumber, Operator);

     PlayAgain = WantToPlayAgain();
} //this is the end of the while loop

}//this is the end ofUseCalculator


Now there are some concepts you haven't got yet.

1
2
3
4
while (IsOperator(symbol) == false)
            {
                ProcessOperator(symbol);
            }


This doesn't make sense does it? I would like you to explain to me in your own words what the difference between a while statement and an if statement is.

And this looks strange, although i can see why you are doing it.

1
2
3
4
5
cout << "Enter a number: "<< endl;
        cin >> cnum;
        cnum =(toupper(cnum));

        if (cnum >= 'A' || cin.fail())


You ask for a number then convert it to upper case. That will return the number unchanged. You are doing it because you want to check for bad input, but I think there is a better way. This is another example of something that is counter intuitive. We can come back to this when the design is finished.

See how you go with the design & explanation of while & if




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 UseCalculator()
{
    float FirstNumber;    //The first number to be calculated
    float SecondNumber;    //The second number to be calculated
    float  Answer;         // The outputted answer
    bool PlayAgain = true;  // Play again prototype
    float ProcessOperator = false; // Process operators Function

    cout << "\nCalculator" << endl;

    while ( PlayAgain == true )
    {   // Ask: Enter first number
            // Get first number
                // Check if first number is within range
                
        // Ask: Enter Operator of choice (+ - / *)
            // Get Operator (+ - / *)
                // Check if operator is within range using IsOperator
            
        // Ask: Enter second number
            //Get second number
                // Check if second number is within range
                
        // Calculate first number and second number with the choosen operator
                
        //Get answer
            //display answer

    }
        PlayAgain = WantToPlayAgain();  // Replay Calculator
    }  // End of While Loop
} //End of Calculator 



While loop:
1
2
3
4
5
6
7
8
9
10
11
int main ()
{
    int x;
                           // does not need an initializer
   while (x != 1)
    {
       cout << "to repeat type 2" << endl;  // loop continues until the condition (x != 1) is false
       cout << "to stop type 1" << endl;
       cin x;
    }
}



IF statement:
1
2
3
4
5
6
7
8
9
10
11
int main ()
{
    int x;
                   cout << "type 2 for a special message" << endl;
                   cout << "type 1 to ignore special message" << endl;      // does need an initializer
   if (x != 1)
    {
       cout << "special message" << endl;  // display if condition (x != 1) is true from the initializer
       
    }
}
1
2
3
4
while (IsOperator(symbol) == false)
            {   //am I saying while IsOperator is true
                ProcessOperator(symbol); //do this
            }


but the condition equals false?
Last edited on
so why not do this:

1
2
3
4
while (IsOperator(symbol) == true)
            {   
                ProcessOperator(symbol); 
            }


So our design so far tells us that we could rename ProcessOperator to GetAnswer because that is what it is relly going to do.

OK now the if's and whiles:

Your code for the if statement works but it uses negative logic (!=), how about this:

1
2
3
4
5
6
7
8
9
10
11
12
 int x;
                   cout << "type 1 for a special message" << endl;
                   cout << "type anything else for a different message" << endl; 
        cin  x;  //get the input    
   if (x == 1)
    {
       cout << "special message" << endl;  
       
    }
    else {
         cout << "different message" << endl;  
    }


The same with the while loop.

What do you mean by these?

// does need an initializer

// does not need an initializer

Back to the design:

Now we need to look for things that can be functions because we want to reuse our code rather repeating code. I have simplified the design a bit:

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

void UseCalculator()
{
    float FirstNumber;    //The first number to be calculated
    float SecondNumber;    //The second number to be calculated
    float  Answer;         // The outputted answer
    bool PlayAgain = true;  // Play again prototype variable
    float ProcessOperator = false; // Process operators Function
   

    cout << "\nCalculator" << endl;

    while ( PlayAgain == true )
    {  
            // Get first number
                // Check if it is a number 
                
        
            // Get Operator (+ - / *)
                // Check if operator is within range using IsOperator
            
       
            //Get second number
                // Check if it is a number
                
        // Calculate first number and second number with the choosen operator
                
        

    }
        PlayAgain = WantToPlayAgain();  // Replay Calculator
    }  // End of While Loop
} //End of Calculator 

float GetAnswer( float FirstNumber, float SecondNumber, char Operator)
{

}


So, looking at the comments, what functions are we going to have?


Edit: We were going to change ProcessOperator to GetAnswer
Last edited on
An initializer would be the
1
2
3
cout << "type 1 for a special message" << endl;
                   cout << "type anything else for a different message" << endl; 
        cin  x;  //get the input  


The while loop does not need any input to activate the sequence opposed to the IF statement.
In programming an initialiser is a function that sets a value to a variable.

1
2
3
4
5
6
7
8
int a;  //declaration
a= 1  //initialisation

int SetA(int number)  // a initialiser function to set a
{
a= 1;  //initialisation
return a;
};


When you print text on the screen asking for input, that is called prompting.

The while loop does not need any input to activate the sequence opposed to the IF statement.


If you mean user input, both of them can have user input, or both of them can have the variables in the test expression set by code.

cin x; //get the input

does this work?

should it be

cin >> x; //get the input

I had it in my post but I had copied it from yours without thinking. A function of doing all nighters again !
I had to get some sleep.

I just woke up to get some water and thought of something like this for the
number check.

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
float FN;
float SN;

  cout << "Enter first number" << endl;
  cin >> FN;
  FN = toupper(FN)

     while (FN >= 'A' || SN >= 'A')   // This is the function
     {
         cout << "Invalid input, enter a number for calculation" << endl;
         cin >> FN, SN;
         FN = toupper(FN)
         SN = toupper(SN)
     }


I'm trying to look for a way to include the first and second number, within one function.

Would it be better to use a bool?

Going back to sleep. Let me know what you think.
Instead of writing new code, keep going with our design process. We are up to deciding which functions we are going to have based on our design so far, keeping in mind we want to reuse code.

I think there are a couple things that are confused:

while (FN >= 'A' || SN >= 'A') // This is the function

It's not a function - it's a while loop. A function is something that can take arguments (optionally - you can have function with no args) does some processing or calculating, then returns one answer (optionally not returning anything).

An example of a function that takes no args and doesn't return anything is the ShowMenu() function we have already done. All it does is print text, but by putting it all in a function, we make the code easier to read. You would do this if you had a lot of code in the body of a loop. You have seen how I have done this in earlier posts.

An example of a function that takes args and returns a value is the GetAnswer function. We haven't written it yet, but you have seen the prototype or forward declaration of it.

float GetAnswer( float FirstNumber, float SecondNumber, char Operator); //forward declaration

On the other hand loops ( such as while and for), if statements, switch statements are example of flow control. They cause execution of the code to "jump" around depending on the test expression or end condition. Jump is a proper technical term btw - Assembly language has jump statements.

The other thing is that your error checking (and how you go about it) is putting confusing logic in your code. Once we have completed our design process you will see how we separate getting input and doing error checking.
Had another thought:

float GetAnswer( float FirstNumber, float SecondNumber, char Operator); //forward declaration

should be :

float GetAnswer( const float FirstNumber, const float SecondNumber, const char Operator); //

This is saying that the function isn't allowed to change any of the arguments.
@SGM

I haven't heard from you for a couple of days, maybe you are busy at work or something.

I hope that I haven't scared you off with my last comment about not writing any new code?

If that is the case, don't worry, we are not far off getting a really good solution.

So our design is essentially this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void UseCalculator() {
//UseCalculator function
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Does simple calculations using 2 floats and an operator 
//Author:
//State: Incomplete design only
//problems:
//to do list:
//Last edited:
//////////////////////////////////////////////////////////////////////////////////////////////////////


//get a number
     //check that it is valid

//get an operator
     //check that it is valid

//get a number
   //check that it is valid

//Calculate the answer

} //end of function UseCalculator 


And this translates into having these functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//variable declarations

//variable float FirstNumber;
//variable float SecondNumber;
//variable char Operator;

/get a number
GetFloat();
     //check that it is valid
    IsValidFloat(FirstNumber);

//get an operator
GetOperator();
     //check that it is valid
    IsOperator(Operator);

//get a number
GetFloat();
   //check that it is valid
   IsValidFloat(SecondNumber);

//Calculate the answer
CalcAnswer(FirstNumber, Operator, SecondNumber )


Going to the next stage:


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
void UseCalculator() {
//UseCalculator function
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Does simple calculations using 2 floats and an operator 
//Author: TheIdeasMan
//State: Incomplete function skeletons
//problems: it s all going well
//to do list: function definitions
//Last edited:  28/06/2012
//////////////////////////////////////////////////////////////////////////////////////////////////////
//variable declarations & initialisation

//variable float FirstNumber;
float FirstNumber =0.0;

//variable float SecondNumber;
float SecondNumber = 0.0;

//variable char Operator;
char Operator = 'a';  //purposely set it to something invalid

//variable bool ValidFloat;
bool ValidFloat = false;   //purposely set it to something invalid
;
//variable bool ValidOperator;
bool ValidOperator = false ; //purposely set it to something invalid

//get a number
FirstNumber = GetFloat();
     //check that it is valid
 ValidFloat =   IsValidFloat(FirstNumber);

//get an operator
 Operator = GetOperator();
     //check that it is valid
 ValidOperator =   IsOperator(Operator);

//get a number
SecondNumber = GetFloat();
     //check that it is valid
 ValidFloat =   IsValidFloat(SecondNumber);
  
//Calculate the answer
Answer = CalcAnswer( FirstNumber, SecondNumber, Operator);

};    //end of function UseCalculator

//function definitions outside main

float GetFloat(){
float TheFloat =0.0;  //local variable

return TheFloat
};

bool  IsValidFloat(float TheNumber){


//return a bool
};

bool IsOperator(char Operator){
//we have already done this one
//return a bool
}



float CalcAnswer( const float FirstNumber, const float SecondNumber, const char Operator) {

float answer = 0.0;
 // switch statement depending on what the operator is

//make sure to return answer;
};


Right, now for some info on the IsValidFloat function:

There are ways in C++ to check for valid input. cin.ignore is one of them, for example. They are a little bit more involved.

However I think we should keep it simple, and the rest of the code is C, so I am going to explain a C approach.

The C counterparts to cout and cin are functions called printf and scanf. The f means formatted input/output. There are others fprintf and fscanf which deals with files, and sscanf which gets formatted input and returns character array (aka a string, but it's not the same thing exactly as a C++ string)

The good thing about scanf is that it does a bit of error checking which is why we are going to use it

Return Value
On success, the function returns the number of items successfully read. This count can match the expected number of readings or fewer, even zero, if a matching failure happens.
In the case of an input failure before any data could be successfully read, EOF is returned.


If you google "C++ scanf" you will find the full explanation of this function, with all the format parameters. We are going to use the %f which stands for float. BTW %f also works for the double type.

The example on the web page is a bit simplistic because it doesn't check the return value of scanf.

We are going to use it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

float GetFloat(){
int ScanfReturnVal = 0;
float TheFloat = 0.0;


while(ScanfReturnVal = 0) {  //Bad input, it's not a float
       printf("Enter a floating point number.\n");

       ScanfReturnVal = scanf(%f, &TheFloat);  //& is the address of operator if TheFloat is actually
                                                                               // a float then ScanfReturnVal will be 1. and the
                                                                               //loop will terminate
}
return TheFloat;
}


Now in our design we had GetFloat and IsValidFloat, but the simple code above shows how we have got the input and validated it all in one go, so we don't really need IsValidFloat anymore.

Where you would need a validation function, would be when the float had to be in a range say 10.0 < float <= 20.0.

We already have the IsOperator function, so you should be able to use this write GetOperator in a similar fashion to GetFloat.

There should be enough clues now for you to write CalcAnswer using a switch.

Were nearly there!! I am interested to see how you go, and look forward to your reply
Last edited on
One of the people at work got sick and another quit.. Been filling in. 12 hour shifts on a grill is brutal at the end of the day. Good news is the pay check will be nice. I was thinking of getting a C++ reference book. Would this be a good idea for me as a beginner? If so, do you have a suggestion?

Today is the last of my grind, until Monday. A nice long weekend to relax, learn and write code. =)

I noticed you had wrote a few posts since we last spoke. When I return from work I will try to read some before I get rested for tomorrow.

Kept thinking about my compiler and lines of text all week. ha
Looking forward to getting back in the game!
Yeah, treat yourself to the big book o' Stroustrup.

Not the best written, to be honest and not a book to learn from by any stretch. But it is a good reference book. And it's the man himself. :-)
Last edited on
I think I should get Bjarne's book as well
To clarify this because I have not been working on this for a few days.

We are writing this calculator with functions "links" to the actual process on what to do.

We are outlining the calculator and will write the functions and definitions after.

That is what I understand from this post:
Pages: 1... 34567