Building a Simple CLI Calculator App in Dart

Apr 20 · 6 min read

This article assumes you know a little bit about the basics of Dart, like how to set up classes and their instance fields and methods. There are also some constraints and improvements we could add to this app, discussed in the Limitations and Improvements section.

• Composing basic app setup (public class, constructor, etc.)
• Creating basic mathematical functions in Dart
• Conditionals and switch statements
• The basics of typecasting
• Implementing recursion

You can follow along with the repo here:

https://github.com/jeanluc243/dart-calculator

Setting up the Basics

This app gets input from a user, and we’ll need the Stdin class to accept this input. At the top of our file, we’ll import it.

`import 'dart:io';`

The next thing we’ll do is set up the skeleton of our app. First, we’ll create a public class, naming it Calc. This class will use two numbers for calculations, instance fields we can define as `num1` and `num2`. The datatypes for both of these will be doubles, so we can add both whole and fractionated numbers. This is also needed for the exponentiate function, explained later.

The … represents the code we’ll write in the future.

The next thing we’ll do is make the constructor method. All this is going to take is take two numbers and set them as our instance fields.

To finish up the skeleton, we’ll make the main method, which we’ll leave empty for now.

It’s good to get all the basics done first, even if we’re not filling them in right away.

Now that we’ve got the edifice for our app, we can get to the fun stuff, building out the functionality.

All of these functions are pretty simple and have the same structure.

Basically, all we do is take the first number and put it on the left side of the operator, while the second number goes on the right side of the operator. We return the resulting value:

Basic math functions.

Exponentiation

This function will raise the first number to the second number’s power. There’s no built-in operator for this, as opposed to other languages like JavaScript. Because of that, we have to utilize the Math lib `pow` function. It takes two arguments: the first being the base, and the second being the exponent. It’s basically the call of other functions we wrote already.

We’re also using an example of typecasting here. There’s a lot more to it than this, but basically it allows conversion between data types. By writing our desired datatype in parentheses, we tell Dart to process whatever it’s going to process, then take the value and convert it to the datatype.

The reason we’re using typecasting, in this case, is to account for large numbers that result from exponents. The double data type can only account to numbers up to a certain degree, while long can account for more.

Using Stdin to Enhance the User experience

Now that we’ve made the mathematical functions, we need some way to receive input from a user. Also, we should try to make it easy to exit this program any time input can be provided, so users don’t have to do something sloppy like `Ctrl+C`. A scanner can solve both these problems.

Earlier, we imported dart:io into this app. I’m not too familiar with it myself, but the documentation is easily available and we don’t need to know the world about it for an app like this.

Using Stdin is like using any other class. First, we’ll make a new instance of it like so:

`String Input = stdin.readLineSync(encoding: Encoding.getByName('utf-8')) ;`

Then, we’ll set up another variable in the meantime named `firstNum`, a double. This will store the first number a user inputs. For now, we’ll just set its default value to 0.0. This helps us avoid initialization issues we might come across (refactoring the code could also help get around this issue).

`double firstNum = 0.0;`

Next, we’ll use a conditional to assess the user’s input.

This basically says “If the user typed exit, abort the program. If not, convert the user’s input to a double value and assign it to `firstNum`. Use `double.parse()` to convert a value into a double.

We can apply this exact same logic for the second number. For simplicity’s sake, this is repeated in the file, but could easily be made more DRY by taking this functionality and consolidating it in a helper function.

Finally, we’ll assess what mathematical function the user wants to perform on the two numbers, saving the user input as string as a variable called operator.

You’ll notice that we also account for the user deciding to exit at this point, or if an unrecognized input is received, via the default case.

At this point, we’d normally close the scanner since we’re done using it. However, this causes issues when we introduce recursive functionality, so we won’t close it. Doing so causes a resource leak, discussed further in the Limitations and Improvements section.

In the switch statement, there’s a function we haven’t talked about yet, `backToMainMenu()`. This is the recursive part of our app. When run, we’ll start the whole input process over. What’s the body of this function look like? It’s really simple, but to explain it, we’ll have to discuss how every part of this app comes together.

Bringing together the whole thing

So far, we’ve built pretty much everything this app needs. For the final touches, we should build out messages the user can see so they know what to input and when. That’s relatively simple though, so I won’t cover that here.

Imagine we’ve done that and are now ready to run the app. Instead of bogging main down with all that logic, why don’t we put the whole thing in a function? I was tired by this point, so rather than naming it something appropriate, I just named it `wholeThing()`, but it gets the point across enough.

By providing `wholeThing()` with all of our logic, calling it in main looks a lot cleaner, and makes it easier for us to recurse. As we saw in the switch statement, when an operator is given we run the `backToMainMenu()` function. Let’s explore the body of it:

All this method does is call wholeThing, which will reset app functionality.

Super simple. All we do is give a message to the user and then run the whole thing again. This means that if the user gives the right inputs, this thing could go on forever. Good thing we gave them the option to exit.

With that, we’ve built the whole calculator. There are some things that could be refactored or made better, which we’ll touch upon in the next section.

Conclusion

In this article, we’ve discussed how to set up a basic CLI calculator with helpful features such as display messages and recursion to benefit the user experience. We discussed the use of the Stdin class to receive user input along with the use of conditionals and switch cases to handle this input. There are some issues with this code that were discussed along with solutions to those issues that can be implemented.

While this is a simple app, we’ve gone over a decent amount of stuff! It’s a great exercise for those just starting out in Dart, so have fun, and happy coding.

You can write to me here :

Written by

Written by