Essential Elements of SimpleCalculator.cs

   


Essential Elements of SimpleCalculator.cs

You have already met the string type in Chapter 3, "A Guided Tour through C#: Part I." The calculator program you will see shortly introduces another type called int, which is a commonly used type for variables holding whole numbers. You will further see how you can define and use your own methods. The important namespace concept, enabling classes and other types to be organized into a single coherent hierarchical structure while providing easy access, is also presented. WriteLine will show off by revealing its versatility, and you will finally meet the handy Math class and apply a couple of methods from this part of the .NET Framework class library.

Presenting SimpleCalculator.cs

The source code in Listing 4.1 calculates the sum, product, minimum, and maximum value of two numbers entered by the user. The program prints the answers on the command console.

Listing 4.1 Source Code for SimpleCalculator.cs
01: using System; 02: 03: /* 04:  * This class finds the sum, product, 05:  * min and max of two numbers 06:  */ 07: public class SimpleCalculator 08: { 09:     public static void Main() 10:     { 11:         int x; 12:         int y; 13: 14:         Console.Write("Enter first number: "); 15:         x = Convert.ToInt32(Console.ReadLine()); 16:         Console.Write("Enter second number: "); 17:         y = Convert.ToInt32(Console.ReadLine()); 18:         Console.WriteLine("The sum is: " + Sum(x, y)); 19:         Console.WriteLine("The product is: " + Product(x, y)); 20:         Console.WriteLine("The maximum number is: " + Math.Max(x, y)); 21:         Console.WriteLine("The minimum number is: " + Math.Min(x, y)); 22:     } 23: 24:      // Sum calculates the sum of two int's 25:     public static int Sum(int a, int b) 26:     { 27:         int sumTotal; 28: 29:         sumTotal = a + b; 30:         return sumTotal; 31:     } 32: 33:      // Product calculates the product of two int's 34:     public static int Product(int a, int b) 35:     { 36:         int productTotal; 37: 38:         productTotal = a * b; 39:         return productTotal; 40:     } 41: } 

The following is the sample output when the user enters 3 and 8:

 Enter first number: 3<enter> Enter second number: 8<enter> The sum is: 11 The product is: 24 The maximum number is: 8 The minimum number is: 3 

A quick reference to the source code in Listing 4.1 is provided in Listing 4.2. You will most likely recognize several constructs from Shakespeare.cs in Chapter 2, "Your First C# Program," and Hello.cs in Chapter 3, and you will probably begin to form a picture of what the fundamental elements of a typical C# program look like.

Listing 4.2 Brief Analysis of Listing 4.1
01: Allow this program to use shortcuts when accessing classes in System namespace 02: Empty line 03: Begin multi-line comment 04:     Second line of multi-line comment: This class finds the sum, product, 05:     Third line of multi-line comment: min and max of two numbers 06: End multi-line comment 07: Begin the definition of a class named SimpleCalculator 08: Begin the block of the SimpleCalculator class definition 09:     Begin the definition of a method called Main() 10:     Begin the block of the Main() method definition 11:         Declare a variable called x which can store whole numbers (integers). 12:         Declare a variable called y which can store whole numbers (integers). 13:         Empty line 14:         Print out: Enter first number: 15:         Store users answer in the x variable. Move down one line 16:         Print out: Enter second number: 17:         Store users answer in the y variable. Move down one line 18:         Print out: The sum is: followed by the value returned from the Sum method. 19:         Print out: The product is: followed by the value returned from the Product  graphics/ccc.gifmethod. 20:         Print out: The maximum number is: followed by the value returned by the Max  graphics/ccc.gifmethod of the Math class. 21:         Print out: The minimum number is: followed by the value returned by the Min  graphics/ccc.gifmethod of the Math class 22:     End the block containing the Main() method definition 23:     Empty line 24:     Make comment: Sum calculates the sum of two int's 25:     Begin the definition of a the method Sum(int a, int b) 26:     Begin the block of the Sum(int a, int b) method definition 27:         Declare a local variable called sumTotal which can store whole integers. 28:         Empty line 29:         Find the sum of a and b; store this result in sumTotal 30:         Terminate the method; return the value of sumTotal to the caller. 31:     End the block of the Sum(int a, int b) method 32:     Empty line.  33:     Make comment: Product calculates the product of two int's 34:     Begin the definition of a the method Product(int a, int b) 35:     Begin the block of the Product(int a, int b) method definition 36:         Declare a local variable called productTotal which can store whole integers 37:         Empty line 38:         Find the product of a and b; store this result in productTotal. 39:         Terminate the method; return the value of productTotal to the caller 40:     End the block of the Product(int a, int b) method 41: End block containing SimpleCalculator class definition 

By now, I assume you are comfortable writing source code in Notepad and compiling it with the csc command of the command console; therefore, I will let you write and run the source code in Listing 4.1 in peace now.

A Closer Look at SimpleCalculator.cs

SimpleCalculator.cs is probably not a program people would rush to buy in their local software store, but it certainly contains a few essential ingredients that would be part of most C# best-selling computer programs. The following section will take a closer look at Listing 4.1 to uncover them.

Introducing Namespaces

We need to introduce the namespace concept to get an initial understanding for line 1. To this end, we move to a seemingly unrelated place your home.

 01: using System; 

Have you ever, like me, had the feeling of an invisible spirit at play that constantly turns your home into a place resembling a test site for new explosives, despite your best efforts to the contrary?

There seems to be a large number of different objects in a home causing the mess to relentlessly get out of hand shirts, spoons, knives, shampoo, books, CDs, apples, pots, and Picasso paintings all pile up.

How, then, do we manage to make our home neat and tidy before the family arrives at Christmas? Containers are the solution to our problem. We form small hierarchies of containers inside other containers holding similar kinds of objects. For example, a kitchen knife (the object) would be positioned in the kitchen (here regarded as being a container) in the upper-left drawer container, in the cutlery tray container, in the knife compartment container, together with other more-or-less similar knives.

Not only do these containers help us to make our home nice and tidy, they also allow us to get an overview of where different objects are stored in the house. We are even able to show our guests where to find different objects. When everything is tidy around Christmas time, we can confidently tell our new friend Fred how to find a knife. If we turned our home into a small hotel with new visitors arriving on a daily basis, we might further create a little system for how to tell new guests where to find different objects. In this referencing system, we could decide to simply put a dot (period) between each container name. A guest looking for a knife then might only need the message Kitchen.UpperLeftDrawer.CutleryTray.KnifeCompartment.

As a final bonus, we avoid name collision problems. For example, we can differentiate between a knife used for fishing found in the garage and a knife used for eating found in the kitchen, even though they are both referred to as knife. This is simply done by specifying where each particular knife is positioned. Accordingly, the kitchen knife specified by Kitchen.UpperLeftDrawer.CutleryTray.KnifeCompartment.Knife would likely be different from our fishing knife referenced by Garage.FishingCupboard.UpperRightDrawer.KnifeBox.Knife.

The kitchen contains not only drawers and boxes, it also can contain objects like chairs and tables. Similarly, every container can contain not only other containers but also objects.

The practical container system described here is similar in concept to the namespace idea. The namespaces act as containers for the many classes we construct and must keep track of. Namespaces help us organize our source code when developing our programs (keeping our "home" of classes "nice and tidy," allowing us to know where each class is kept). They also allow us to tell our "guest" users where classes are kept, so they (other programmers) easily can access and reuse our classes. Name collisions between classes created by different programmers, perhaps from different software companies, are eliminated, because each class can be uniquely referenced through its namespace name.

Recall the .NET Framework documentation viewed previously. If you had a good look, you would have encountered a myriad of classes. In fact, the .NET Framework contains several thousand classes. Consequently, the .NET Framework is heavily dependent on namespaces to keep its classes organized and accessible.

The .NET Framework contains an important namespace called System. It holds specific classes fundamental to any C# program. Many other System classes are frequently used by most C# programs. It also includes our familiar Console class used extensively in Listing 3.1 (lines 9 11 and 13 15) of Chapter 3 and lines 14 21 in Listing 4.1.

Tip

Avoid giving names to classes that are identical to important, often-used namespace identifiers, such as System, Collections, Forms, and IO


Listings 3.1 and 4.1 represent two different options available when accessing classes of the System (or any other) namespace in your source code:

  • Without using System; in the source code, as in line 1 of Listing 3.1 We must then reference the System namespace explicitly every time we use one of its classes, as in Listing 3.1, line 14:


    graphics/04infig01.gif

  • With using System;, as in line 1 of Listing 4.1 We can use any class of the System namespace without the repetitive tedious chore of explicitly typing System. The previous example of code could then be truncated to the following (just like lines 14 21 of Listing 4.1).


    graphics/04infig02.gif

using essentially frees us from the burden of writing fully-qualified namespace names in numerous places of our source code. It also enhances the readability of our code by abbreviating otherwise lengthy references.

Note

graphics/common.gif

using can only be applied to namespaces and not classes, so the following line is invalid:


graphics/04infig03.gif


Multi-Line Comments

You have already met the double slash // used for single line comments in lines 1 and 4 of Listing 3.1. /* (forward slash star) indicates the beginning of a multi-line comment. Anything written between /* and the matching */ is a comment and is ignored by the compiler (as in line 3 of Listing 4.1).

 03: /* 

// could be used for multi-line comments, but you would have to include // in every line of the comment, as shown in the following:

 //This comment spans //over two lines 

/* */ could likewise be used for a single line comment:

 /* This is a single line comment */ 

Most programmers seem to prefer // for one or at most only a few lines of comments, whereas /* */ facilitates elaborate comments spanning numerous lines.

A few different multi-line commenting styles are often seen. The start comment /* and end comment */ have been highlighted so it is easier for you to locate the beginning and end of each comment.

 /*  Many attempts to communicate     are nullified by saying too much.                    Robert Greenleaf      */ /*  * I have made this rather  * long letter because I haven't  * had the time to make it shorter.  *  *          Blaise Pascal  */ /**********************************************  * It's a damn good program.  * If you have any comments,  * write them on the back  * of the cheque.  *  *   Adapted from Erle Stanley Gardner *********************************************/ 

Probably not the typical content of a comment, but these comments illustrate three different popular multi-line commenting styles and possess wisdom applicable when commenting source code.

The actual text of the multi-line comment is seen in lines 4 and 5 of Listing 4.1:

 04:  * This class finds the sum, product, 05:  * min and max of two numbers 

In line 6, */ matches /* of line 3 and terminates the multi-line comment.

 06:  */ 

Tip

graphics/bulb.gif

Making good comments is like adding salt to your food; you have to add the right amount. Excessive use of comments obscures the readability of the code and gives the reader more to read than necessary. It is as damaging as too few comments.

Rather than merely restating what the code does by using different words, try to describe the overall intent of the code.


graphics/04infig04.gif

Let's see how we can improve this source code:


graphics/04infig05.gif


Declaring a Variable of Type int

Line 11 contains a statement declaring a variable called x. Remember how we previously declared a variable of type string in Listing 3.1 line 7, enabling it to contain a string of characters (text). This time, we have exchanged the keyword string with the keyword int. It dictates the type of x to be a specific kind of integer taking up 32 bits of memory (4 bytes).

 11:         int x; 

Integers, in general are whole numbers, such as 8, 456, and 3123. This contrasts with floating-point numbers that include a fraction. 76.98, 3.876, and 10.1 are all examples of floating point numbers. Because x now takes up 32 bits of memory, it can represent numbers in the 2147483648 2147483647 range. We will not examine this fact closely now, but observe the following calculation:

graphics/04equ03.gif

The first 2 is the bit size, the 32 is the number of bits, and the /2 shows that half of the available numbers are allocated for positive numbers, and half for negative numbers.

Binary numbers are discussed at length in Appendix D, "Number Systems," which is found on www.samspublishing.com, while integers and their range will be discussed thoroughly in Chapter 6, "Types Part I: The Simple Types."

Line 12 declares a variable called y to be of type int.

 12:         int y; 

x and y are usually considered to be unacceptable names for variables because identifiers must be meaningful and reflect the content of the variable. In this particular case, however, x and y are involved in generic arithmetic calculations and do not represent any particular values, such as average rainfall or the number of newborns in Paris. Any math whiz kid would immediately accept x and y as valid name choices in a mathematical equation with equivalent generic characteristics.

Converting from Type string to Type int

Any user response typed on the console, followed by Enter, and received by Console.ReadLine() is considered to be of type string by the C# program. Even a number like 432 is initially presumed to merely be a set of characters and could easily be ABC or #@$ instead.

A number represented as a string cannot be stored directly in a variable of type int; so we must first convert the string variable to a variable of type int before commencing.

By using the ToInt32 method of the Convert class as in line 15, the program attempts to convert any user input to an int number. After successful conversion, the part on the right side of the equals sign in line 15 will represent the corresponding int number, and be stored in x. However, the conversion can only take place if the user input matches an int number. Thus, inputs such as 57.53 or three hundred will trigger an error, whereas 109 or 64732 are accepted.

 15:         x = Convert.ToInt32(Console.ReadLine()); 
Creating and Invoking Your Own Methods

Before line 18 can be understood properly, we need to jump ahead and look at lines 25 31.

 25:     public static int Sum(int a, int b) 26:     { 27:         int sumTotal; 28: 29:         sumTotal = a + b; 30:         return sumTotal; 31:     } 

Until now, we have happily used pre-fabricated methods, such as Console.ReadLine() and Console.WriteLine(). Despite the vast array of functionality found in the .NET Framework and other available commercial class libraries, you will, when creating new unique source code, need to supply specialized functionality by writing your own user-defined methods.

Lines 25 31 are an example of a user-defined method called Sum.

Briefly explained, Sum, when called, receives two numbers. It adds the two numbers together and returns the result to the caller.

The definition for the Sum() method, with its method header, braces { }, and method body, follows the same general structure as the definition for the Main method.

Tip

graphics/bulb.gif

Generally, classes represent objects, whereas methods represent actions. Try to adhere to the following when you name classes and methods:

Use nouns (Car, Airplane, and so on) when naming classes.

Use verbs for method names (DriveForward, MoveLeft, TakeOff, and so on).


The method header of line 25 is, in many ways, similar to the method header of Main in line 9 (recall the access modifier public and its ability to let a method be included in the interface of the class to which it belongs).

We have also previously introduced static, in line 5 of Listing 3.1, and will abstain from any further description of this keyword right now.

However, void has been replaced by int, and we see what looks like two variable declarations separated by a comma residing inside a pair of parentheses (int a, int b) located after Sum. This deserves an explanation.

Line 25 can be regarded as the interface of the Sum method. This interface facilitates the communication between the method calling Sum (in this case Main) and the method body of Sum.

In everyday language, an interface can be described as a feature or circumstance that enables separate (and sometimes incompatible) elements to communicate effectively.

Figure 4.1 zooms in on the process involved when Sum(int a, int b) of line 25 is invoked from line 18 Sum(x, y) of the Main() method. The two arrows marked Zoom simply indicate which parts have graphically been blown up and zoomed in on.

Figure 4.1. Invoking a user-defined method.
graphics/04fig01.gif

a and b in Sum's method header are called formal parameters. A formal parameter is used in the method body as a stand-in for a value that will be stored here when the method is called. In this case, the values of the arguments x and y of line 18 will be plugged into a and b indicated with arrows 1 and 2, just as though the two assignment statements a=x; and b=y; were executed.

a and b can now be used inside the method body (in this case line 29) just like any regular declared variable initially holding the values of x and y.

The int in line 25 replacing void not only tells us that Sum returns a value of some sort, but also that this value is of type int. This leads us to line 30, where we find the C# keyword return.

 30:       return sumTotal; 

return belongs to a type of statement called a return statement. When a return statement is executed, the method is terminated. The flow of execution is returned to the caller and brings along the value residing in the expression after return (in this case the value of sumTotal. See the arrows with number three in Figure 4.1).

Accordingly, the type of sumTotal must be compatible with the return type specified in the method header (in this case int), as illustrated in Figure 4.2.

Figure 4.2. Return type of method header must match type of return expression.
graphics/04fig02.gif

No Data Are Returned from a void Method

graphics/common.gif

When the keyword void is positioned in front of the method name in the method header, it indicates that when the runtime has finished executing the statements of the method, it will not return any data to the caller. Consequently the void keyword has the opposite meaning from the keyword int when put in front of the method name in the method header. The latter indicates that the method will always return a value of type int.


Tip

graphics/bulb.gif

When you program in C#, think in terms of building blocks. Classes, objects, and methods are meant for this approach. Break down your programs into manageable building blocks. In a C# program, you typically use classes and methods that are

  • From class libraries (NET Framework or other commercially available packages). Many class libraries can be obtained for free over the Internet.

  • Written by yourself and, as a result, contain user-defined classes and methods.

  • Created by other programmers, perhaps your fellow students or colleagues at work.

Don't attempt to reinvent the wheel. Before throwing time and money into creating new classes and methods, check to see if equivalent functionality has already been implemented, tested by professional programmers, and made available in the form of highly efficient and robust software components.


An Assignment Statement

Line 29 is an assignment statement. a and b are added together using the + operator. The result is stored in the sumTotal variable due to the assignment operator = (see Figure 4.3). Let's illustrate this by using the sample output example of from Listing 4.1, where the input provided was 3 and 8. When Sum is called, 3 and 8 are transferred to a and b, through x and y of Main. After the execution of line 29, sumTotal holds the value 11.

Figure 4.3. Assigning the result of a calculation to a variable.
graphics/04fig03.gif
 29:         sumTotal = a + b; 
Combining Strings and Method Calls

In line 18, we first need to focus on the Sum(x, y) part, which, as already shown, invokes the Sum method defined in lines 25 31 and sends the two arguments x and y along. Notice that we do not need to include ObjectName or ClassName as specified in the previously given conventions, ObjectName.MethodName(Optional_Arguments) and ClassName.MethodName(Optional_Arguments), because the invoker and the invoked method reside inside the same class SimpleCalculator.

 18:         Console.WriteLine("The sum is: " + Sum(x, y)); 

After the Sum method returns, you can virtually substitute Sum(x, y) with sumTotal from line 30. In our example, Sum(x, y) will represent the value 11 (see Figure 4.4).

Figure 4.4. Sum(x, y) represents the value of sumTotal when Sum returns.
graphics/04fig04.gif

Even though Sum(x, y) resides inside another method call in the form of Console.WriteLine(), C# can easily cope and correctly resolves the sequence of events that need to take place. When the value of Sum(x, y) is needed, the call will be made. Line 18 could then, after lines 25 31 have been executed and the flow has returned to line 18, be thought of as:

 Console.WriteLine("The sum is: " + 11); 

Because 11 is inside the parentheses of a call to WriteLine, it is automatically converted to a string. Consequently, we can now look at line 18 as follows:

 Console.WriteLine("The sum is: " + "11"); 

We still have one odd detail to sort out the + symbol between "The sum is: " and "11". When the + symbol is positioned between two numeric values, it adds them together in standard arithmetic fashion. However, when the C# compiler finds the + symbol surrounded by strings, it changes its functionality. It is then used to connect the two strings surrounding it, which results in "The sum is: 11". In general, connecting or pasting together two strings to obtain a larger string is called concatenation, so the + symbol in this case is referred to as a concatenation operator.

Finally, line 18 has essentially been transformed to look like the following:

 Console.WriteLine("The sum is: 11"); 

This is familiar to us and says, "Print out The sum is: 11 on the console." Fortunately, this is exactly what we see when running the program.

The + Symbol: Adding or Concatenating?

graphics/tnt.gif

The + operator can be used for different purposes. One moment it is used for a string concatenation; the next it is involved in adding numbers together. Due to this flexibility of the + operator, we say it is overloaded. Overloaded operators are very useful, but they come at a price; hard to trace bugs and mysterious results can sometimes appear.

For example, when + acting as a string concatenation operator is confused with + acting as an addition operator, the program produces unexpected results. Consider the following line of code:

 Console.WriteLine("x + 8 = " + x + 8); 

If x has the value 6, which output would you expect?

The actual output is x + 8 = 68, whereas many would have expected x + 8 = 14.

Why is that? Well first, "x + 8 = " + x is concatenated to "x + 8 = 6" which again is concatenated with 8 to form x + 8 = 68.

A correct result printing x + 8 = 14 can be produced with the following code:

 "x + 8 = " + (x + 8) 


KISS

graphics/bulb.gif

The C# compiler is capable of resolving extremely complicated, nested, convoluted statements and programs. Programmers with a bit of experience sometimes attempt to show off by stretching this power to create some warped, weird, and intricate programs that nobody apart from themselves can understand. This kind of programming practice is acceptable if you want to have a bit of fun in your free time at home, but it has no place in properly constructed software.

Be humble! Follow the KISS principle Keep It Simple Stupid.


Lines 34 40 are very similar to lines 25 31, the only differences being different method and variable names and, instead of calculating the sum, the Product method calculates the product of two numbers. Note that the asterisk (*) character is used to specify multiplication.

 34:     public static int Product(int a, int b) 35:     { 36:         int productTotal; 37: 38:         productTotal = a * b; 39:         return productTotal; 40:     } 

Lines 18 and line 19 are conceptually identical.

 19:         Console.WriteLine("The product is: " + Product(x, y)); 

Tip

graphics/bulb.gif

The order in which the methods of a class are defined is arbitrary and has no relation to when you can call those methods in your source code and when they will be executed. Accordingly, you could change the order in which the Sum and Product definitions appear in the definition of the SimpleCalculator class.


The Math Class: A Useful Member of the .NET Framework

Line 20 is similar in concept to lines 18 and 19. However, here we utilize the Math class (instead of Sum and Product) of the System namespace in the .NET Framework class library to find the greater of two numbers using the Max method.

 20:         Console.WriteLine("The maximum number is: " + Math.Max(x, y)); 

The Math class contains many useful math-related methods, such as trigonometry and logarithms.

Tip

graphics/bulb.gif

It is permissible to spread one long statement over several lines as long as no tokens are separated into smaller pieces of text. However, if not thoughtfully done, breaking up statements into several lines can easily obscure the readability of the source code. To avoid this problem, choose logical breaking points, such as after an operator or after a comma. When statements are separated into more than one line, indent all successive lines.

For example, we might decide that line 20 of Listing 4.1 is too long

 20:       Console.WriteLine("The maximum number is: " + Math.Max(x, y)); 

and break it up after the concatenation operator (+) so that Math.Max(x,y)); is moved down to the next line and indented

 20:       Console.WriteLine("The maximum number is: " +           Math.Max(x, y)); 


Analogous to line 20, Math.Min(x, y) in line 21 finds the smaller of x and y.

 21:         Console.WriteLine("The minimum number is: " + Math.Min(x, y)); 

This ends our tour through Listing 4.1.


   


C# Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 286
Authors: Stephen Prata

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