Arrays in Action: A Roman Numeral Calculator

Arrays in Action: A Roman Numeral Calculator

Let's write a simple program that shows the power of arrays. A good start would be a program that converts a number to its equivalent Roman numeral. The user types in a number, and the program displays the results. Figure 6-11 shows an example.

Figure 6-11

A Roman numeral calculator.

To build our Roman numeral calculator, start out by creating a new Visual Basic project. Name the project Throwback, and add a text box, a button, and two labels to Form1. Align the controls to look like the window in Figure 6-11, and then set the following properties with the values listed in Table 6-3.

Table 6-3  Controls and properties for the Throwback program

Object

Property

Value

Text box

Name

txtInput

Text

" "

Button

Name

cmdCalculate

Text

Calculate

Label

Name

lblDescription

Text

Roman Numeral Result

TextAlign

MiddleCenter

Label

Name

lblResult

BorderStyle

Fixed3D

Text

" "

TextAlign

MiddleCenter

Writing the Code

We want to display the name of the program in several places, such as the form's title bar and various message boxes. Rather than write the name of the program for each place we want to display it, we will dimension a constant value to hold the name. Not only do we save space by declaring this value once, but the value can be computed at compile time, which makes our program marginally faster. Also, if you decide to change the name of the program to Legionnaire's Helper, simply change the value of the constant and recompile and the new name will show up throughout the program. Here's the code:

Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code "

 Const sProgName As String = "Throwback Calculator"

In the Click event handler of our cmdCalculate button, add the following code. This code does the heavy lifting for our program.

Private Sub cmdCalculate_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdCalculate.Click  Dim Arabics() As Integer = {1, 4, 5, 9, 10, 40, 50, 90, 100, _ 400, 500, 900, 1000} Dim Romans() As String = {"I", "IV", "V", "IX", "X", "XL", _ "L", "XC", "C", "CD", "D", "CM", "M"} Dim sInput As String = txtInput().Text Dim iInput, iCounter As Integer Dim sOutPut As String = "" Dim ArabicLower As Integer = Arabics.GetLowerBound(0) Dim ArabicUpper As Integer = Arabics.GetUpperBound(0) lblResult().Text = "" iInput = Int32.Parse(txtInput().Text) For iCounter = ArabicUpper To ArabicLower Step -1 While iInput >= Arabics(iCounter) iInput -= Arabics(iCounter) sOutPut += Romans(iCounter) End While Next lblResult().Text = sInput & " = " & sOutPut End Sub

When the form loads, we can set the title of the form to our program's name. Because sProgName refers to our constant, we simply add this value to the Text property of the form.

Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load  Me.Text = sProgName End Sub

Examining the Code

In the Throwback program, we've created two arrays, one of integers and one of strings. Remember that arrays must hold the same data type. You can't place a string in an integer array. Our arrays each have 13 elements, indexed from 0 through 12. We've initialized them when they are declared, as you can see here:

Dim Arabics() As Integer = {1, 4, 5, 9, 10, 40, 50, 90, 100, _     400, 500, 900, 1000} Dim Romans() As String = {"I", "IV", "V", "IX", "X", "XL", _     "L", "XC", "C", "CD", "D", "CM", "M"}

Next the string variable sInput is initialized with the contents of the text box. As are the other variables in the Click event of our button, sInput is a local, or procedure-level, variable, which means that whenever the user clicks the button, this variable is declared and initialized. When the code exits the subroutine, the variable goes out of scope and is destroyed. In other words, sInput's lifetime is only as long as the time that passes when the code is executing in the Click event.

Dim sInput As String = txtInput().Text

Another necessary improvement over classic Visual Basic is the ability to declare like variable data types on the same line. In the declaration below in classic Visual Basic, iCounter would be an integer, but iInput would be a variant. This difference caused no end of headaches and made tracking down bugs for C programmers coming to Visual Basic difficult. Having this capability in Visual Basic .NET is a major step forward in the maturity of the language. (And because it means less typing for me, all the better.)

Dim iInput, iCounter As Integer

note

Another important change is that Visual Basic .NET now supports "short circuiting." If we had code like the following in previous versions of Visual Basic, both tests on the If line would be conducted, even though we can clearly see that iInteger <> 0 is false:

Dim iInteger as integer = 0 If ((iInteger <> 0) and (dcConnection = open)) then 'Do something important End if

Both tests would take place and only then would the test return false. Not only is this inefficient, but it caused many a raised eyebrow from those coming to Visual Basic from other languages. Thankfully, Visual Basic .NET would evaluate the first condition, determine that iInteger indeed equals zero, and abandon the test at that point. This approach is how most other languages work.

Caching Our Variables

In the Throwback program, we will loop through both arrays, but going backward this time. We could write the code like this:

For iCounter = 12 To 0 Step -1

While this code would work, it is considered bad programming form because if we ever added or deleted an array element, our program would crash. A good rule of thumb is to never hard-code any limits if they can be calculated dynamically. This way, if you ever change the number of array elements, your code will still work just fine. To compensate, you could also write code like this.

For iCounter = Arabics.GetUpperBound(0) To _ Arabics.GetUpperBound(0) Step -1

Other than more typing, coding like this has a fundamental problem. While we can now add and delete elements from the array and the loop continues to work fine, each time through the loop the program must calculate the upper and lower bounds of the array. While for small arrays this operation might not be noticeable, on larger arrays it can really eat up CPU cycles, constantly calculating array boundary values that won't change each time through the loop.

Whenever you write a loop that has to get an upper and lower bound that can be calculated beforehand, always assign these values to variables. Accessing a local variable in memory is much faster than having the compiler first look up the array and then find the method and then finally return a value. This technique is known as caching a variable. We calculate the bounds a single time, assign them to variables, and then use the variables in the loop. This mechanism is very fast.

Dim ArabicLower As Integer = Arabics.GetLowerBound(0) Dim ArabicUpper As Integer = Arabics.GetUpperBound(0)

Each time we use our Throwback calculator, we want to be sure the result label is free of old calculations. If a value from a previous calculation is in the result label, we get rid of it. While you might think you could just overwrite the old value with the new result, what if you get an error? An error could really confuse the user by retaining an old value that does not correspond with the new input. Here's the code that solves this problem; it simply clears the text box before the calculation is performed:

lblResult().Text = ""

When we read a value from the input text box, the result will be a string (note the Text property). However, we want an integer, not a string. The Visual Basic .NET way of converting these types is the Parse method. The Parse method of the int32 data type converts the string representation of a number to its 32-bit signed integer equivalent.

iInput = int32.Parse(txtInput().Text)

The next part of the code does the heavy lifting for our program. We run through each of the elements of the Arabics array backward, from 12 down to 0, decrementing by 1 each time through the loop. As long as the value that the user typed in the text box is larger than or equal to the current value of the Arabics array element, we decrement iInput by that amount. At the same time, we concatenate the value in Roman numerals from the Romans array to our output string, sOutPut.

Let's say a user enters 1,000. Because iInput = 1,000, which is the value of the last element of the Arabics array, iInput is decremented by 1000. At the same time, sOutput has "M" concatenated to it. The program steps through the rest of the Arabics array elements down to 0, but because iInput is 0, the While loop is never entered again.

For iCounter = ArabicUpper To ArabicLower Step -1 While iInput >= Arabics(iCounter) iInput -= Arabics(iCounter) sOutPut += Romans(iCounter) End While Next

We finally display the results of our calculations in the lblResult label.

lblResult().Text = sInput & " = " & sOutPut

Now the user can see the Roman numeral display of the Throwback Calculator, as shown in Figure 6-12.

Figure 6-12

The Throwback Calculator in action.



Coding Techniques for Microsoft Visual Basic. NET
Coding Techniques for Microsoft Visual Basic .NET
ISBN: 0735612544
EAN: 2147483647
Year: 2002
Pages: 123
Authors: John Connell

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net