Reference no: EM13838918
Stream
Implementing Calculator Functionality
The instructions below assumes that you used the recommended names, i.e.
Project Name: Calculator
Form: CalculatorForm
If you did not use the names suggested last week then you will need to modify the code below appropriately.
If when you load your project you have an error panel appear that tells you the Designer view could not be loaded, close this panel and right click on CalculatorForm.h in the Solution Explorer and select View Designer.
When you see the Designer View click on the lblRunningOper label and delete the 0 from its Text property.
The first thing that you would notice if you attempted to run your project is that you would be presented with an error telling you that there is no entry point for your project. To correct this we need to add some code to the CalculatorForm.cpp file and then modify some of the properties of the project.
Open the CalculatorForm.cpp file and enter the code below.
#include -CalculatorForm.h-
using namespace System;
using namespace System::Windows::Forms;
[STAThread] void Main(array String^ ^ args) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Calculator::CalculatorForm form;
Application::Run(%form);
}
With the code entered into your CalculatorForm.cpp file we now need to set this up as the start point for your program. Right click on Calculator in the Solution Explorer and select Properties. In the window that appears click on Linker under Configuration Properties. Now click on System under Linker, then click on the dropdown button next to SubSystem. Select Windows (/SUBSYSTEM:WINDOWS) from the list. Now click on Advanced under Linker and click in the area next to Entry Point. Type in Main here - Main is the name of the function you just created in CalculatorForm.cpp. Follow the screen shots below for visual instructions.
If you now run your project you should see the calculator form displayed on the screen. Close your application and go back to Visual Studio.
1.1 Displaying the result of number presses
Open up the Form Designer in Visual Studio and double click on the number 1 button. This should automatically open up the code view of CalculatorForm.h and create a piece of code for you - similar to below:
Place your cursor to the left of the left brace and hit enter. This will put the brace on the new line and make it somewhat easier to read. Now click to the right of the opening brace and add a blank line - this is where you will be writing your code. The code that we are currently working in will be executed everytime the button is clicked, so if we consider how a calculator works we would expect three presses on the number 1 button would result in the number 111 being displayed. To enable this we need to continuously append the number pressed to the end of the currently displayed result. This will mean that for each button press we need to retrieve the current value displayed on the lblResult widget. However, we also need to be mindful that if the current result on display is a 0 then we simply replace the 0 with the number pressed.
To access the text on the label we use the - operator. At this point we can think of this operator as the means to access elements of a larger, complicated structure. For example a person is made up of many properties, like name, hair colour, age, cultural background. If we wanted to access the age of a person called Brett we may represent it like Brett- age. The same process should be used for the text on the labels of our Form, i.e. lblResult- Text.
We need to assign this text to a suitable structure which will be a String^ which we can name currentResult. This would result in the following code:
String^ currentResult = lblResult- Text;
Now that we have the current result value we can test to see what response we should offer. Use an if statement to determine if the currentResult is equal to -0-, if it is then this means that the user hasn't entered anything into the calculator yet so we have to replace the 0 on the output with the number 1. If however the currentResult does not equal 0 then that suggests that the user has already entered a number so we need to set currentResult to:
currentResult + -1-;
This will append the number 1 to the end of the existing current result, i.e. if the user had previously pressed the number 1 button twice we would expect to see 11 (which we have assigned to currentResult) for the purposes of our program at this point this is actually the text "11" not the number 11 - therefore the operation that we are completing is to join or concatenate two strings or pieces of text together: -11- + -1- results in -111-.
Finally once the processing of the if statement has beeen concluded you need to set the newly defined currentResult as the text for the lblResult:
lblResult- Text = currentResult;
Run your program and test the press of the number 1 button. Verify that the correct number of presses produce the correct number.
Repeat the steps above for all remaining number buttons. You will have a lot of repeated code. Run your program and test that all the numbers can be displayed correctly.
1.2 Implementing calculation
To enable calculation we need to keep track of what operands, operators, and running results are being used. To do this we need to define some variables. Navigate to the top of your newly entered code for handling number presses and you should find a piece of code that looks like:
#pragma endregion
Place your cursor to the right of this statement and hit enter twice to give you some empty lines. At this point you need to define a variable of type char called oper and initialize it with the value ‘0'. This will allow us to keep track of the current operation or calculation taking place - when our program is running depending on the button pressed we will change the value of this variable to either ‘+', ‘-', ‘*', ‘/', ‘0'. For the purposes of our program the ‘0' character represents no calculation taking place. Also define a new variable of type double called result and initialize it with the value 0.
We will store our operands as pieces of text not numbers to allow for easy manipulation of the values while the user enters numbers, so define two variables of type String^ called num1 and num2, initialize num1 with -0- and num2 with --.
In the operation of our calculator as soon as we press an operator button we know that the user has entered in a complete number, for instance if I wanted to complete the following start of a calculation (111 +) I would do the following sequence:
Press button number 1
Press button number 1
Press button number 1
Press button +
This tells me that my first operand will be 111 and I am wanting to complete an addition operation. This information needs to be presented to the user in the lblRunningOper label so they can see the sequence of their calculation as seen in the screenshot below:
Double click on the + button in the Design View of you program to automatically create the stub of code for this button's interactions. The first thing that we want to do in response to the button being pressed is to set the value of the oper variable. As we are dealing with the + button we will need to set the value to the character +, i.e.:
oper = ‘+';
The next thing to do is to up date the running operation label (lblRunningOper). This label should contain the existing information that is currently on the label combined with the current result displayed on lblResult combined with the selected operator - for the + button it may look something like:
lblRunningOper- Text = lblRunningOper- Text + lblResult- Text + -+-;
Testing your program at this point should allow you to update the running operation label no calculations will be completed yet. Verify that the text for the calculation appears in the lblRunningOper label.
Now that we have the + button responding in some way to presses we can begin to detail the calculation process. To complete this part we will need to modify the code in one of our number buttons - for now choose the number 1 button code you implemented earlier. We need to determine which operand we are currently working with - to enable this we can use the oper variable and its current value. Remember a value of ‘0' meant that we were not performing an operation - we can use this assumption to make a decision on whether we are dealing with the first operand (num1) or the second (num2). If the oper is 0 then we know that we are dealing with num1 otherwise if the oper is not 0 (i.e. +, -, *, or /) then we would be dealing with num2 but if num2 is empty then we need to set num2 to the number pressed - the same operation that occured when assigning a number after the first button press (i.e. the calculator starts with 0 on its display instead of appending the number to the end of 0 we replace 0 with the number). The following pseudo code describes this problem:
if oper is ‘0' then set num1 to currentResult
else
if num2 is not -- then
set num2 to currentResult
else
set num2 to -1- //assuming number 1 button pressed set currentResult to -1-
You should implement the above code in your number button code just before you set the Text of lblResult to currentResult.
Now to complete this process we need to define code for the equals button. Go to your Designer View and double click the equals button on your form. For the functionality of the equal button we should not try to complete a calculation if there are not 2 operands to work with (i.e. num1 and num2 both have values other than --). To handle this we need to place a decision at the start of this new code to check if num2 contains an appropriate value - if it does then we can complete the calculation, if however it does not then we should do nothing in response to the equals button press. So start with:
if(num2 != --)
{
}
If the boolean expression is true then we need to take the existing values for num1 and num2 (which are strings) and convert them into their number equivalent. To do this declare two double variables called n1 and n2 and then assign the parsed double value of the appropriate number:
double n1 = double::Parse(num1);
When you have the number values you need to create a switch that uses the value of oper to determine which calculation needs to take place, remember for our + button we set the value of oper to ‘+'. If oper does contain the value ‘+' then use the result variable declared earlier and assign the result of the operation n1 + n2 to it. Remember to add in a break; at the end of the case. Even though we haven't defined the operation of the other arithmetic operators yet we can fill in the rest of the switch statement with the following for each specific case:
result = n1 - n2;
result = n1 * n2;
result = n1 / n2;
Once we have calculated the result after the conclusion of the switch we should then assign this result to num1. To ensure that the double value assigned to result is represented correctly as a string we use the following: result.ToString() - by assigning this to num1 we are storing the text version of the numeric result value. num1 holds the result so that the next arithmetic operation can be applied to the existing total. As we are now waiting for the next operand to be entered we can set num2 back to --. We have also finished our calculation so we can reset oper back to ‘0'.
Finally update the lblResult- Text with the calculated result (remember result is double and lblResult- Text requires a string) and set the Text of lblRunningOper back to --.
You should be able to test your code and perform addition operations on any variation of numbers containing all 1's, i.e. 1 + 1 should return 2, a subsequent + 11 should return 13, etc. The final part to completing the addition operation requires you to go back to the + button code. When using a calculator you can typically execute a number of operations without pressing equals, (i.e. 1 + 1 + 11 + 1 + 111 + 11), and the calculator should produce a running sum (136). This is what we will implement now.
At the end of your + button code test to see whether a value has been supplied for num2, if a value exists (or another way of considering this is if num2 is not equal to --) then calculate the result of this operation (num1 + num2, don't forget to parse to get their double version). Assign this result to lblResult- Text and then set the value of num1 to this newly calculated result and clear num2 by setting it to --.
Once again test your code and verify that the calculations taking place work with the equals button as well as the + button.
Replicate the above code for the addition operation for all other arithmetic operators and numbers. Remember that to insert the ÷ symbol you will need to use the following key combination: Alt + 0, the 2, then 4, then 7 - on the number pad.
1.3 The Clear and Memory Buttons
For the Clear button we simply reset all variables back to their starting condition. Double click the Clear button on the Designer View and complete the following:
Set the Text of lblResult to -0-
Set the Text of lblRunningOper to --
Set num1 to -- Set num2 to --
Set result to 0
Set oper to ‘0'
To display the Memory operations we will add a new label to our form. Create a new label and drag it onto your Calculator form. Set the following properties:
Name: lblMem
Text: M
Background: White
Location: 20, 15
Visible: False
Setting these properties should make your form look like the following (note the M in the top left corner of the Result label):
By setting the Visible property to False when you run the project you will notice that there is no M visible in the executing form. We will implement code to make this visible and the invisible as needed.
Go back up in your code to where you defined your variables and create a new variable call mem of type String^ and initialize it with the value -0-. We should not store 0 in our memory for our calculator so 0 will be treated as though there is nothing currently held in memory. Now go to the Design View and double click on the M+ button. The operation of this button is to take what ever is currently in memory and add the value currently displayed on the result label then store this in the mem variable. Therefore if nothing is in memory and the user presses the number 5 button and then M+ this would result in: 0 + 5 = 5, therefore the value 5 would be assigned to the variable mem. If the value 5 was currently assigned to mem and the user entered the number 27 and the pressed the M+ button this would result in: 5 + 27 = 32, therefore the value 32 would be assigned to the variable mem. Remember to do the calculation you will need to retrieve the current value of mem as well as the current value of the lblResult- Text and parse them as doubles.
You only need to do the above operation if the lblResult- Text is not -0-. If this is true then you should also set the lblMem property Visible to true so the M on your calculator becomes visible:
lblMem- Visible = true;
For the Memory Clear function you simply need to set the value of mem to -0- and set the lblMem- Visible property to false.
For Memory Recall you should check to see if you are dealing with the first operand or the second by testing to see if oper is equal to ‘0'. If it is then this tells us that an arithmetic operator button has not been pressed and therefore we need to assign num1 with the current value of mem otherwise an arithmetic operator button has been pressed and therefore we are dealing with the second operand and should assign num2 with the current value of mem. When the user presses the Memory Recall button the lblResult- Text should also be updated to show the value of mem.
1.4 The %, ±, and . Buttons
Our pecentage operation can only occur once we have two operands so just like other examples we have previously completed we need to test to see if we have two operands. If we do, then we can complete the following calculation and assign the result to num2:
num1 * (num2 / 100)
The result of the percentage calculation also needs to be assigned to lblResult and appended to lblRunningOper. Add this code to the automatically generated stub created when you double click on the percentage button.
Now you need to define the code to handle the use of the decimal place. To begin deeclare and initialize a new variable to determine when a decimal point has been or can be used - define a variable of type bool named decimal and set its initial value to false. Double click on the decimal point button and enter your code into the newly created stub.
Retrieve the value of lblResult and assign it to String^currentValue. Test to see if we are working with num1 or num2 - remember the value of oper can help you. If we are working with num1 then assign the value of currentResult to num1. However, if we are working with num2 then we need to test whether there is any values already associated with num2, if not then assign num2 with the currentValue otherwise assign num2 the value -0.- and currentResult the same value. Finally, update lblResult with teh value of currentResult.
If you have implemented this correctly they you can display decimal points within your numbers, however there is no control over ensuring that the user cannot enter more than one decimal point - that can be controlled with the bool variable decimal we declared earlier. To ensure the process described above only occurs once we can test to see if a decimal place has already been used and if not we can do everything and then set the bool decimal to true so we stop the program from adding another decimal point, i.e.:
if(!decimal)
{ do the operations defined above set decimal to true }
Now when an operator, clear or equals button is pressed you need to add the following piece of code to each of these sections to reset the use of the decimal point:
decimal = false;
The last task for this part of the calculator is to implement the ± button. Double click on the button to create the new stub of code. Capture the current value of lblResult- Text and test to see whether the numeric value is greater than 0. If it is then you need to prepend a - symbol to the start of the value in lblResult- Text, i.e.:
currentResult = --- + currentResult;
If however the number is less than 0 then we need to remove the - symbol from the start of the value seen in lblResult. To do this we need the following code:
currentResult = currentResult- SubString(1);
SubString return a string that is made up of parts of the original string. The instruction SubString(1) tells our program that we want everything from currentResult except for the first character (i.e. the - symbol). The 1 in the brackets represents the index where you should start extracting characters from - we begin all indexing from 0, therefore 0 is the index of the first character, 1 is the index of the second character, ....
Now that you have adjusted the value of currentResult you should assign its value to lblResult. The last step you need to complete is to assign the positive or negative value to the correct operand - if oper is ‘0' then assign the value of currentResult to num1 otherwise assign this value to num2.
Testing your calculator should now enable all the standard functions (except for the backspace) and should funtion as a typical calculator.
Show your demonstrator the completed output for your week 1 and week 4 work.