Site icon Embarcadero RAD Studio, Delphi, & C++Builder Blogs

Learn to program C++ with C++Builder Community Edition: #5 Operators, and final application!

Welcome to the fifth and final episode of Learning C++ with C++Builder Starter. Last time, we had a calculator and numerical input, demonstrating using boost::optional, smart pointers, and more. This post is shorter: it will finish the calculator with operators (implementing addition, subtraction, etc) and end with a full application, ready to move to cross-platform if you wish.

Operators

The calculator is almost functional. The one thing missing is actually performing the math operations.

We want to support four operations: addition, subtraction, multiplication, and division. Each of these is an operation; each takes two operands, a left and a right operand.  In the expression

3 x 4

The left operand is 3, the right operand is 4, and the operation is Multiply.

This gives us a good basis for an interface, and an object-oriented design for operations, and is a good excuse to make a polymorphic class hierarchy with virtual methods – a useful thing to see done when learning C++.  Let’s make an interface and factory methods in a new unit called uOperator.cpp:

 

[crayon-674271265dd67717844398/]

And implement these in the .cpp file. For example, Add would be:

 

[crayon-674271265dd6f702897916/]

Along with the factory method, switching on Op.

Any call to the interface’s methods, Calc or Name, will call into the implemented descendant.

Next, create this when the user sets the operator.  Add a std::unique_ptr<IOperator> m_Op; to the TCalculator class, and change TCalculator::SetOperator to look like so:

 

[crayon-674271265dd71013629052/]

This is currently simplified – we’ll examine some other things that have to happen here in a moment.

This allows us to calculate the result of an operator, so long as we have two numbers. How do we get those two numbers?

Left and Right Operands, and the Result

Last post, we had an accumulator – a small object whose job was to take button keypresses and turn them into numbers. When has the user finished typing?

In both these cases, it indicates one number is complete, and something else needs to happen: in the first case, that the second number needs to be entered; in the second, to calculate the result. Also in the first case, entering the second number might mean calculating as well – if the user has entered ‘1 + 2’, and presses the multiply button, they want to multiply 3 by something. That something is the new right operand, and the result is the new left operand.

This means that SetOperator needs to be able to promote the accumulator’s value to a new left or right operand value, and also sometimes invoke Equals and moving the result to the left operand, before setting the operator.

Secondly, the left and right operands, and the result, do not always exist.  When the calculator app has just started, and the user has entered nothing, there are no operands or result. When Equals has been pressed, there is a result but no left or right operand. This harks back to last week’s post: how do you represent something that may or may not exist? Using boost::optional.

Let’s add three optional values to the calculator class’s declaration:

 

[crayon-674271265dd72277440095/]

They’re not initialised to any value in the class constructor, since at app startup they are empty.

Promoting the accumulator

First, let’s create a method for moving a number from being typed in (the accumulator) to a left or right operand. It’s fairly simple: if there is no left operand, initialize the left with the accumulator’s value; if there is, then initialize the right operand with the accumulator’s value. If there’s already both a left and a right, that indicates a logic error.

 

[crayon-674271265dd73635479049/]

Setting the operator

We can now expand the method called when the user wants to set the operator – when they press + or -.

The code to do this looks like so:

 

[crayon-674271265dd74787754451/]

Calculating

Not much left!  We can now make use of the operator classes we created at the beginning of the post.  The calculation method, called Equals after the button, will promote the accumulator if necessary (the user might have been typing what should become a right-side operand); if it has a left, a right, and an operator, call the virtual Calc method to get a result.

 

[crayon-674271265dd75713200403/]

 

Printing

One final step: displaying this onscreen.

A traditional calculator only displays the number currently being entered, or the result. The operator interface we designed has an operator name, and there’s no reason our app can’t be slightly more advanced than a desktop calculator.  If the user is trying to calculate “1 + 2” why display only 1, or only 2, and no sight of ‘+’?

My version of this code will show the left and right operands, if they exist, along with the operator if it’s set, accounting for the user typing (for example, there might not be a right operand, just the accumulator in use – same with the left operand.)

There’s not much new here: this uses string streams, and dereferences the optional left or right values.

 

 

[crayon-674271265dd76898877643/]

The Calculator

And that’s it. Really. Congratulations, you now have a fully functional calculator!

This code, being FireMonkey, can be compiled on Windows, macOS, and mobile. (Note if you want to target Android, you’ll need to install Boost for Mobile.)  You can theme it, and change the layout for any device using the multi-device designer. You’ve created a cross-platform app without even trying.

We’ve covered:

and ended with a complete, working, very nice calculator. Your challenge? Recompile it for macOS or iOS! (Hint: investigate the ‘Target Platforms’ node in the Project Manager…)

Thanks for reading each post. I hope you learned some good stuff!

Source code

Read more

The Learn to program C++ with C++Builder series:

 

Exit mobile version