Desktop

Home

50-game

C++

1 - C++ OVERVIEW

Compilers


The essential tools needed to follow these tutorials are a computer and a compiler toolchain able to compile C++ code and build the programs to run on it.

C++ is a language that has evolved much over the years, and these tutorials explain many features added recently to the language. Therefore, in order to properly follow the tutorials, a recent compiler is needed. It shall support (even if only partially) the features introduced by the 2011 standard.

Many compiler vendors support the new features at different degrees. See the bottom of this page for some compilers that are known to support the features needed. Some of them are free!

If for some reason, you need to use some older compiler, you can access an older version of these tutorials here (no longer updated).

What is a compiler?


Computers understand only one language and that language consists of sets of instructions made of ones and zeros. This computer language is appropriately called machine language.

A single instruction to a computer could look like this:

0000010011110

A particular computer's machine language program that allows a user to input two numbers, adds the two numbers together, and displays the total could include these machine code instructions:

0000010011110
0000111110100
0001010011110
0001111010100
0010010111111
0010100000000

As you can imagine, programming a computer directly in machine language using only ones and zeros is very tedious and error prone. To make programming easier, high level languages have been developed. High level programs also make it easier for programmers to inspect and understand each other's programs easier.

This is a portion of code written in C++ that accomplishes the exact same purpose:

Even if you cannot really understand the code above, you should be able to appreciate how much easier it will be to program in the C++ language as opposed to machine language.

Because a computer can only understand machine language and humans wish to write in high level languages high level languages have to be re-written (translated) into machine language at some point. This is done by special programs called compilers, interpreters, or assemblers that are built into the various programming applications.

C++ is designed to be a compiled language, meaning that it is generally translated into machine language that can be understood directly by the system, making the generated program highly efficient. For that, a set of tools are needed, known as the development toolchain, whose core are a compiler and its linker.

Console programs


Console programs are programs that use text to communicate with the user and the environment, such as printing text to the screen or reading input from a keyboard. Console programs are easy to interact with, and generally have a predictable behavior that is identical across all platforms. They are also simple to implement and thus are very useful to learn the basics of a programming language: The examples in these tutorials are all console programs.

The way to compile console programs depends on the particular tool you are using.

The easiest way for beginners to compile C++ programs is by using an Integrated Development Environment (IDE). An IDE generally integrates several development tools, including a text editor and tools to compile programs directly from it.

Here you have instructions on how to compile and run console programs using different free Integrated Development Interfaces (IDEs):

IDEPlatformConsole programs
Code::blocksWindows/ Linux/ MacOSCompile console programs using Code::blocks
Visual Studio ExpressWindowsCompile console programs using VS Express 2013
Dev-C++WindowsCompile console programs using Dev-C++

If you happen to have a Linux or Mac environment with development features, you should be able to compile any of the examples directly from a terminal just by including C++11 flags in the command for the compiler:

CompilerPlatformCommand
GCCLinux, among others...g++ -std=c++0x example.cpp -o example_program
ClangOS X, among others...clang++ -std=c++11 -stdlib=libc++ example.cpp -o example_program

2 - C++ STRUCTURE OF A PROGRAM

The best way to learn a programming language is by writing programs. Typically, the first program beginners write is a program called "Hello World", which simply prints "Hello World" to your computer screen. Although it is very simple, it contains all the fundamental components C++ programs have:

Hello World!

The left panel above shows the C++ code for this program. The right panel shows the result when the program is executed by a computer. The grey numbers to the left of the panels are line numbers to make discussing programs and researching errors easier. They are not part of the program.

Let's examine this program line by line:

Line 1: // my first program in C++
Two slash signs indicate that the rest of the line is a comment inserted by the programmer but which has no effect on the behavior of the program. Programmers use them to include short explanations or observations concerning the code or program. In this case, it is a brief introductory description of the program.

Line 2: #include <iostream>
Lines beginning with a hash sign (#) are directives read and interpreted by what is known as the preprocessor. They are special lines interpreted before the compilation of the program itself begins. In this case, the directive #include <iostream>, instructs the preprocessor to include a section of standard C++ code, known as header iostream, that allows to perform standard input and output operations, such as writing the output of this program (Hello World) to the screen.

Line 3: A blank line. Blank lines have no effect on a program. They simply improve readability of the code.

Line 4: int main () This line initiates the declaration of a function. Essentially, a function is a group of code statements which are given a name: in this case, this gives the name "main" to the group of code statements that follow. Functions will be discussed in detail in a later chapter, but essentially, their definition is introduced with a succession of a type (int), a name (main) and a pair of parentheses (()), optionally including parameters.

The function named main is a special function in all C++ programs; it is the function called when the program is run. The execution of all C++ programs begins with the main function, regardless of where the function is actually located within the code.

Lines 5 and 7: { and } The open brace ({) at line 5 indicates the beginning of main's function definition, and the closing brace (}) at line 7, indicates its end. Everything between these braces is the function's body that defines what happens when main is called. All functions use braces to indicate the beginning and end of their definitions.

Line 6: std::cout< "Hello World!";
This line is a C++ statement. A statement is an expression that can actually produce some effect. It is the meat of a program, specifying its actual behavior. Statements are executed in the same order that they appear within a function's body.

This statement has three parts: First, std::cout, which identifies the standard character output device (usually, this is the computer screen). Second, the insertion operator (<<), which indicates that what follows is inserted into std::cout. Finally, a sentence within quotes ("Hello world!"), is the content inserted into the standard output.

Notice that the statement ends with a semicolon (;). This character marks the end of the statement, just as the period ends a sentence in English. All C++ statements must end with a semicolon character. One of the most common syntax errors in C++ is forgetting to end a statement with a semicolon.

You may have noticed that not all the lines of this program perform actions when the code is executed. There is a line containing a comment (beginning with //). There is a line with a directive for the preprocessor (beginning with #). There is a line that defines a function (in this case, the main function). And, finally, a line with a statements ending with a semicolon (the insertion into cout), which was within the block delimited by the braces ( { } ) of the main function.

The program has been structured in different lines and properly indented, in order to make it easier to understand for the humans reading it. But C++ does not have strict rules on indentation or on how to split instructions in different lines.
For example, instead of

We could have written:

all in a single line, and this would have had exactly the same meaning as the preceding code.

In C++, the separation between statements is specified with an ending semicolon (;), with the separation into different lines not mattering at all for this purpose. Many statements can be written in a single line, or each statement can be in its own line. The division of code in different lines serves only to make it more legible and schematic for the humans that may read it, but has no effect on the actual behavior of the program.

Now, let's add an additional statement to our first program:

Hello World! I'm a C++ program

In this case, the program performed two insertions into std::cout in two different statements. Once again, the separation in different lines of code simply gives greater readability to the program, since main could have been perfectly valid defined in this way:

The source code could have also been divided into more code lines instead:

And the result would again have been exactly the same as in the previous examples.

Preprocessor directives (those that begin by #) are out of this general rule since they are not statements. They are lines read and processed by the preprocessor before proper compilation begins. Preprocessor directives must be specified in their own line and, because they are not statements, do not have to end with a semicolon (;).

Comments


As noted above, comments do not affect the operation of the program; however, they provide an important tool to document directly within the source code what the program does and how it operates.

C++ supports two ways of commenting code:

The first of them, known as line comment, discards everything from where the pair of slash signs (//) are found up to the end of that same line. The second one, known as block comment, discards everything between the /* characters and the first appearance of the */ characters, with the possibility of including multiple lines.

Let's add comments to our second program:

Hello World! I'm a C++ program

If comments are included within the source code of a program without using the comment characters combinations //, /* or */, the compiler takes them as if they were C++ expressions, most likely causing the compilation to fail with one, or several, error messages.

Using namespace std


If you have seen C++ code before, you may have seen cout being used instead of std::cout. Both name the same object: the first one uses its unqualified name (cout), while the second qualifies it directly within the namespace std (as std::cout).

cout is part of the standard library, and all the elements in the standard C++ library are declared within what is a called a namespace: the namespace std.

In order to refer to the elements in the std namespace a program shall either qualify each and every use of elements of the library (as we have done by prefixing cout with std::), or introduce visibility of its components. The most typical way to introduce visibility of these components is by means of using declarations:

using namespace std;

The above declaration allows all elements in the std namespace to be accessed in an unqualified manner (without the std:: prefix).

With this in mind, the last example can be rewritten to make unqualified uses of cout as:

Hello World! I'm a C++ program

Both ways of accessing the elements of the std namespace (explicit qualification and using declarations) are valid in C++ and produce the exact same behavior. For simplicity, and to improve readability, the examples in these tutorials will more often use this latter approach with using declarations, although note that explicit qualification is the only way to guarantee that name collisions never happen.

3 - C++ VARIABLES AND TYPES

The usefulness of the "Hello World" programs shown in the previous chapter is rather questionable. We had to write several lines of code, compile them, and then execute the resulting program, just to obtain the result of a simple sentence written on the screen. It certainly would have been much faster to type the output sentence ourselves.

However, programming is not limited only to printing simple texts on the screen. In order to go a little further on and to become able to write programs that perform useful tasks that really save us work, we need to introduce the concept of variables.

Let's imagine that I ask you to remember the number 5, and then I ask you to also memorize the number 2 at the same time. You have just stored two different values in your memory (5 and 2). Now, if I ask you to add 1 to the first number I said, you should be retaining the numbers 6 (that is 5+1) and 2 in your memory. Then we could, for example, subtract these values and obtain 4 as result.

The whole process described above is a simile of what a computer can do with two variables. The same process can be expressed in C++ with the following set of statements:

Obviously, this is a very simple example, since we have only used two small integer values, but consider that your computer can store millions of numbers like these at the same time and conduct sophisticated mathematical operations with them.

We can now define variable as a portion of memory to store a value.

Each variable needs a name that identifies it and distinguishes it from the others. For example, in the previous code the variable names were a, b, and result, but we could have called the variables any names we could have come up with, as long as they were valid C++ identifiers.

Identifiers


A valid identifier is a sequence of one or more letters, digits, or underscore characters (_). Spaces, punctuation marks, and symbols cannot be part of an identifier. In addition, identifiers shall always begin with a letter. They can also begin with an underline character (_), but such identifiers are -on most cases- considered reserved for compiler-specific keywords or external identifiers, as well as identifiers containing two successive underscore characters anywhere. In no case can they begin with a digit.

C++ uses a number of keywords to identify operations and data descriptions; therefore, identifiers created by a programmer cannot match these keywords. The standard reserved keywords that cannot be used for programmer created identifiers are:

alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq

Specific compilers may also have additional specific reserved keywords.

Very important: The C++ language is a "case sensitive" language. That means that an identifier written in capital letters is not equivalent to another one with the same name but written in small letters. Thus, for example, the RESULT variable is not the same as the result variable or the Result variable. These are three different identifiers identifiying three different variables.

Fundamental data types


The values of variables are stored somewhere in an unspecified location in the computer memory as zeros and ones. Our program does not need to know the exact location where a variable is stored; it can simply refer to it by its name. What the program needs to be aware of is the kind of data stored in the variable. It's not the same to store a simple integer as it is to store a letter or a large floating-point number; even though they are all represented using zeros and ones, they are not interpreted in the same way, and in many cases, they don't occupy the same amount of memory.

Fundamental data types are basic types implemented directly by the language that represent the basic storage units supported natively by most systems. They can mainly be classified into:

  • Character types: They can represent a single character, such as 'A' or '$'. The most basic type is char, which is a one-byte character. Other types are also provided for wider characters.
  • Numerical integer types: They can store a whole number value, such as 7 or 1024. They exist in a variety of sizes, and can either be signed or unsigned, depending on whether they support negative values or not.
  • Floating-point types: They can represent real values, such as 3.14 or 0.01, with different levels of precision, depending on which of the three floating-point types is used.
  • Boolean type: The boolean type, known in C++ as bool, can only represent one of two states, true or false.

Here is the complete list of fundamental types in C++:

GroupType names*Notes on size / precision
Character typescharExactly one byte in size. At least 8 bits.
char16_tNot smaller than char. At least 16 bits.
char32_tNot smaller than char16_t. At least 32 bits.
wchar_tCan represent the largest supported character set.
Integer types (signed)signed charSame size as char. At least 8 bits.
signed short intNot smaller than char. At least 16 bits.
signed intNot smaller than short. At least 16 bits.
signed long intNot smaller than int. At least 32 bits.
signed long long intNot smaller than long. At least 64 bits.
Integer types (unsigned)unsigned char(same size as their signed counterparts)
unsigned short int
unsigned int
unsigned long int
unsigned long long int
Floating-point typesfloat
doublePrecision not less than float
long doublePrecision not less than double
Boolean typebool
Void typevoidno storage
Null pointerdecltype(nullptr)

* The names of certain integer types can be abbreviated without their signed and int components - only the part not in italics is required to identify the type, the part in italics is optional. I.e., signed short int can be abbreviated as signed short, short int, or simply short; they all identify the same fundamental type.

Within each of the groups above, the difference between types is only their size (i.e., how much they occupy in memory): the first type in each group is the smallest, and the last is the largest, with each type being at least as large as the one preceding it in the same group. Other than that, the types in a group have the same properties.

Note in the panel above that other than char (which has a size of exactly one byte), none of the fundamental types has a standard size specified (but a minimum size, at most). Therefore, the type is not required (and in many cases is not) exactly this minimum size. This does not mean that these types are of an undetermined size, but that there is no standard size across all compilers and machines; each compiler implementation may specify the sizes for these types that fit the best the architecture where the program is going to run. This rather generic size specification for types gives the C++ language a lot of flexibility to be adapted to work optimally in all kinds of platforms, both present and future.

Type sizes above are expressed in bits; the more bits a type has, the more distinct values it can represent, but at the same time, also consumes more space in memory:

SizeUnique representable valuesNotes
8-bit256= 28
16-bit65 536= 216
32-bit4 294 967 296= 232 (~4 billion)
64-bit18 446 744 073 709 551 616= 264 (~18 billion billion)

For integer types, having more representable values means that the range of values they can represent is greater; for example, a 16-bit unsigned integer would be able to represent 65536 distinct values in the range 0 to 65535, while its signed counterpart would be able to represent, on most cases, values between -32768 and 32767. Note that the range of positive values is approximately halved in signed types compared to unsigned types, due to the fact that one of the 16 bits is used for the sign; this is a relatively modest difference in range, and seldom justifies the use of unsigned types based purely on the range of positive values they can represent.

For floating-point types, the size affects their precision, by having more or less bits for their significant and exponent.

If the size or precision of the type is not a concern, then char, int, and double are typically selected to represent characters, integers, and floating-point values, respectively. The other types in their respective groups are only used in very particular cases.

The properties of fundamental types in a particular system and compiler implementation can be obtained by using the numeric_limits classes (see standard header <limits>). If for some reason, types of specific sizes are needed, the library defines certain fixed-size type aliases in header <cstdint>.

The types described above (characters, integers, floating-point, and boolean) are collectively known as arithmetic types. But two additional fundamental types exist: void, which identifies the lack of type; and the type nullptr, which is a special type of pointer. Both types will be discussed further in a coming chapter about pointers.

C++ supports a wide variety of types based on the fundamental types discussed above; these other types are known as compound data types, and are one of the main strengths of the C++ language. We will also see them in more detail in future chapters.

Declaration of variables


C++ is a strongly-typed language, and requires every variable to be declared with its type before its first use. This informs the compiler the size to reserve in memory for the variable and how to interpret its value. The syntax to declare a new variable in C++ is straightforward: we simply write the type followed by the variable name (i.e., its identifier). For example:

int a; float mynumber;

These are two valid declarations of variables. The first one declares a variable of type int with the identifier a. The second one declares a variable of type float with the identifier mynumber. Once declared, the variables a and mynumber can be used within the rest of their scope in the program. If declaring more than one variable of the same type, they can all be declared in a single statement by separating their identifiers with commas. For example:

int a, b, c;

This declares three variables (a, b and c), all of them of type int, and has exactly the same meaning as:

int a; int b; int c;

4

Don't be worried if something else than the variable declarations themselves look a bit strange to you. Most of it will be explained in more detail in coming chapters.

Initialization of variables


When the variables in the example above are declared, they have an undetermined value until they are assigned a value for the first time. But it is possible for a variable to have a specific value from the moment it is declared. This is called the initialization of the variable.

In C++, there are three ways to initialize variables. They are all equivalent and are reminiscent of the evolution of the language over the years:

The first one, known as c-like initialization (because it is inherited from the C language), consists of appending an equal sign followed by the value to which the variable is initialized:

type identifier = initial_value;
For example, to declare a variable of type int called x and initialize it to a value of zero from the same moment it is declared, we can write:

int x = 0;

A second method, known as constructor initialization (introduced by the C++ language), encloses the initial value between parentheses (()):

type identifier (initial_value);
For example:

int x (0);

Finally, a third method, known as uniform initialization, similar to the above, but using curly braces ({}) instead of parentheses (this was introduced by the revision of the C++ standard, in 2011):

type identifier {initial_value};
For example:

int x {0};

All three ways of initializing variables are valid and equivalent in C++.

6

Type deduction: auto and decltype


When a new variable is initialized, the compiler can figure out what the type of the variable is automatically by the initializer. For this, it suffices to use auto as the type specifier for the variable:

int foo = 0;
auto bar = foo; // the same as: int bar = foo;

Here, bar is declared as having an auto type; therefore, the type of bar is the type of the value used to initialize it: in this case it uses the type of foo, which is int.

Variables that are not initialized can also make use of type deduction with the decltype specifier:

int foo = 0;
decltype(foo) bar; // the same as: int bar;

Here, bar is declared as having the same type as foo.

auto and decltype are powerful features recently added to the language. But the type deduction features they introduce are meant to be used either when the type cannot be obtained by other means or when using it improves code readability. The two examples above were likely neither of these use cases. In fact they probably decreased readability, since, when reading the code, one has to search for the type of foo to actually know the type of bar.

Introduction to strings


Fundamental types represent the most basic types handled by the machines where the code may run. But one of the major strengths of the C++ language is its rich set of compound types, of which the fundamental types are mere building blocks. An example of compound type is the string class. Variables of this type are able to store sequences of characters, such as words or sentences. A very useful feature! A first difference with fundamental data types is that in order to declare and use objects (variables) of this type, the program needs to include the header where the type is defined within the standard library (header <tring>):

This is a string

As you can see in the previous example, strings can be initialized with any valid string literal, just like numerical type variables can be initialized to any valid numerical literal. As with fundamental types, all initialization formats are valid with strings:

string mystring = "This is a string";
string mystring ("This is a string");
string mystring {"This is a string"};

Strings can also perform all the other basic operations that fundamental data types can, like being declared without an initial value and change its value during execution:

This is the initial string content
This is a different string content

Note: inserting the endl manipulator ends the line (printing a newline character and flushing the stream).

The string class is a compound type. As you can see in the example above, compound types are used in the same way as fundamental types: the same syntax is used to declare variables and to initialize them.

4 - C++ CONSTANTS

Constants are expressions with a fixed value.

Literals


Literals are the most obvious kind of constants. They are used to express particular values within the source code of a program. We have already used some in previous chapters to give specific values to variables or to express messages we wanted our programs to print out, for example, when we wrote:

a = 5;

The 5 in this piece of code was a literal constant.

Literal constants can be classified into: integer, floating-point, characters, strings, Boolean, pointers, and user-defined literals.

Integer Numerals

1776
707
-273

These are numerical constants that identify integer values. Notice that they are not enclosed in quotes or any other special character; they are a simple succession of digits representing a whole number in decimal base; for example, 1776 always represents the value one thousand seven hundred seventy-six.

In addition to decimal numbers (those that most of us use every day), C++ allows the use of octal numbers (base 8) and hexadecimal numbers (base 16) as literal constants. For octal literals, the digits are preceded with a 0 (zero) character. And for hexadecimal, they are preceded by the characters 0x (zero, x). For example, the following literal constants are all equivalent to each other:

75 // decimal
0113 // octal
0x4b // hexadecimal

All of these represent the same number: 75 (seventy-five) expressed as a base-10 numeral, octal numeral and hexadecimal numeral, respectively.

These literal constants have a type, just like variables. By default, integer literals are of type int. However, certain suffixes may be appended to an integer literal to specify a different integer type:

SuffixType modifier
u or Uunsigned
l or Llong
ll or LLlong long

Unsigned may be combined with any of the other two in any order to form unsigned long or unsigned long long.

For example:

In all the cases above, the suffix can be specified using either upper or lowercase letters.

Floating Point Numerals

They express real values, with decimals and/or exponents. They can include either a decimal point, an e character (that expresses "by ten at the Xth height", where X is an integer value that follows the e character), or both a decimal point and an e character:

These are four valid numbers with decimals expressed in C++. The first number is PI, the second one is the number of Avogadro, the third is the electric charge of an electron (an extremely small number) -all of them approximated-, and the last one is the number three expressed as a floating-point numeric literal.

The default type for floating-point literals is double. Floating-point literals of type float or long double can be specified by adding one of the following suffixes:

SuffixType
f or Ffloat
l or Llong double

For example:

Any of the letters that can be part of a floating-point numerical constant (e, f, l) can be written using either lower or uppercase letters with no difference in meaning.

Character and string literals
Character and string literals are enclosed in quotes:

The first two expressions represent single-character literals, and the following two represent string literals composed of several characters. Notice that to represent a single character, we enclose it between single quotes ('), and to express a string (which generally consists of more than one character), we enclose the characters between double quotes (").

Both single-character and string literals require quotation marks surrounding them to distinguish them from possible variable identifiers or reserved keywords. Notice the difference between these two expressions:

x
'x'

Here, x alone would refer to an identifier, such as the name of a variable or a compound type, whereas 'x' (enclosed within single quotation marks) would refer to the character literal 'x' (the character that represents a lowercase x letter).

Character and string literals can also represent special characters that are difficult or impossible to express otherwise in the source code of a program, like newline (\n) or tab (\t). These special characters are all of them preceded by a backslash character (\).
Here you have a list of the single character escape codes:

Escape codeDescription
\nnewline
\rcarriage return
\ttab
\vvertical tab
\bbackspace
\fform feed (page feed)
\aalert (beep)
\'single quote (')
\"double quote (")
\?question mark (?)
\\backslash (\)

For example:

'\n'
'\t'
"Left \t Right"
"one\ntwo\nthree"

Internally, computers represent characters as numerical codes: most typically, they use one extension of the ASCII character encoding system (see ASCII code for more info). Characters can also be represented in literals using its numerical code by writing a backslash character (\) followed by the code expressed as an octal (base-8) or hexadecimal (base-16) number. For an octal value, the backslash is followed directly by the digits; while for hexadecimal, an x character is inserted between the backslash and the hexadecimal digits themselves (for example: \x20 or \x4A).

Several string literals can be concatenated to form a single string literal simply by separating them by one or more blank spaces, including tabs, newlines, and other valid blank characters. For example:

The above is a string literal equivalent to:

Note how spaces within the quotes are part of the literal, while those outside them are not.

Some programmers also use a trick to include long string literals in multiple lines: In C++, a backslash (\) at the end of line is considered a line-continuation character that merges both that line and the next into a single line. Therefore the following code:

is equivalent to:

All the character literals and string literals described above are made of characters of type char. A different character type can be specified by using one of the following prefixes:

PrefixCharacter type
uchar16_t
Uchar32_t
Lwchar_t

Note that, unlike type suffixes for integer literals, these prefixes are case sensitive: lowercase for char16_t and uppercase for char32_t and wchar_t.

For string literals, apart from the above u, U, and L, two additional prefixes exist:

PrefixDescription
u8The string literal is encoded in the executable using UTF-8
RThe string literal is a raw string

In raw strings, backslashes and single and double quotes are all valid characters; the content of the literal is delimited by an initial R"sequence( and a final )sequence", where sequence is any sequence of characters (including an empty sequence). The content of the string is what lies inside the parenthesis, ignoring the delimiting sequence itself. For example:

Both strings above are equivalent to "string with \\backslash". The R prefix can be combined with any other prefixes, such as u, L or u8.

Other literals


Three keyword literals exist in C++: true, false and nullptr:

  • true and false are the two possible values for variables of type bool.
  • nullptr is the null pointer value.

Typed constant expressions


Sometimes, it is just convenient to give a name to a constant value:

We can then use these names instead of the literals they were defined to:

31.4159

Preprocessor definitions (#define)


Another mechanism to name constant values is the use of preprocessor definitions. They have the following form:

#define identifier replacement

After this directive, any occurrence of identifier in the code is interpreted as replacement, where replacement is any sequence of characters (until the end of the line). This replacement is performed by the preprocessor, and happens before the program is compiled, thus causing a sort of blind replacement: the validity of the types or syntax involved is not checked in any way.

For example:

31.4159

Note that the #define lines are preprocessor directives, and as such are single-line instructions that -unlike C++ statements- do not require semicolons (;) at the end; the directive extends automatically until the end of the line. If a semicolon is included in the line, it is part of the replacement sequence and is also included in all replaced occurrences.

1 - C++ OPERATORS

Once introduced to variables and constants, we can begin to operate with them by using operators. What follows is a complete list of operators. At this point, it is likely not necessary to know all of them, but they are all listed here to also serve as reference.

Assignment operator (=)


The assignment operator assigns a value to a variable.

x = 5;

This statement assigns the integer value 5 to the variable x. The assignment operation always takes place from right to left, and never the other way around:

x = y;

This statement assigns to variable x the value contained in variable y. The value of x at the moment this statement is executed is lost and replaced by the value of y.

Consider also that we are only assigning the value of y to x at the moment of the assignment operation. Therefore, if y changes at a later moment, it will not affect the new value taken by x.

For example, let's have a look at the following code - I have included the evolution of the content stored in the variables as comments:

a:4 b:7

This program prints on screen the final values of a and b (4 and 7, respectively). Notice how a was not affected by the final modification of b, even though we declared a = b earlier.

Assignment operations are expressions that can be evaluated. That means that the assignment itself has a value, and -for fundamental types- this value is the one assigned in the operation. For example:

y = 2 + (x = 5);

In this expression, y is assigned the result of adding 2 and the value of another assignment expression (which has itself a value of 5). It is roughly equivalent to:

x = 5;
y = 2 + x;

With the final result of assigning 7 to y.

The following expression is also valid in C++:

y = y = z = 5;

It assigns 5 to the all three variables: x, y and z; always from right-to-left.

Arithmetic operators ( +, -, *, /, % )


The five arithmetical operations supported by C++ are:

Operations of addition, subtraction, multiplication and division correspond literally to their respective mathematical operators. The last one, modulo operator, represented by a percentage sign (%), gives the remainder of a division of two values. For example:

x = 11 % 3;

results in variable x containing the value 2, since dividing 11 by 3 results in 3, with a remainder of 2.

Compound assignment (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)


Compound assignment operators modify the current value of a variable by performing an operation on it. They are equivalent to assigning the result of an operation to the first operand:

expressionequivalent to...
y += x;y = y + x;
x -= 5;x = x - 5;
x /= y;x = x / y;
price *= units + 1;price = price * (units+1);

and the same for all other compound assignment operators. For example:

Increment and decrement (++, --)


Some expression can be shortened even more: the increase operator (++) and the decrease operator (--) increase or reduce by one the value stored in a variable. They are equivalent to +=1 and to -=1, respectively. Thus:

are all equivalent in its functionality; the three of them increase by one the value of x.

In the early C compilers, the three previous expressions may have produced different executable code depending on which one was used. Nowadays, this type of code optimization is generally performed automatically by the compiler, thus the three expressions should produce exactly the same executable code.

A peculiarity of this operator is that it can be used both as a prefix and as a suffix. That means that it can be written either before the variable name (++x) or after it (x++). Although in simple expressions like x++ or ++x, both have exactly the same meaning; in other expressions in which the result of the increment or decrement operation is evaluated, they may have an important difference in their meaning: In the case that the increase operator is used as a prefix (++x) of the value, the expression evaluates to the final value of x, once it is already increased. On the other hand, in case that it is used as a suffix (x++), the value is also increased, but the expression evaluates to the value that x had before being increased. Notice the difference:

Example 1Example 2
x = 3;
y = ++x;
// x contains 4, y contains 4
x = 3;
y = x++;
// x contains 4, y contains 3

In Example 1, the value assigned to y is the value of x after being increased. While in Example 2, it is the value x had before being increased.

Relational and comparison operators ( ==, !=, >, <, >=, <= )


Two expressions can be compared using relational and equality operators. For example, to know if two values are equal or if one is greater than the other.

The result of such an operation is either true or false (i.e., a Boolean value).

The relational operators in C++ are:

operatordescription
==Equal to
!=Not equal to
<Less than
>Greater than
<=Less than or equal to
>=Greater than or equal to

Here there are some examples:

Of course, it's not just numeric constants that can be compared, but just any value, including, of course, variables. Suppose that a=2, b=3 and c=6, then:

Be careful! The assignment operator (operator =, with one equal sign) is not the same as the equality comparison operator (operator ==, with two equal signs); the first one (=) assigns the value on the right-hand to the variable on its left, while the other (==) compares whether the values on both sides of the operator are equal. Therefore, in the last expression ((b=2) == a), we first assigned the value 2 to b and then we compared it to a (that also stores the value 2), yielding true.

Logical operators ( !, &&, || )


The operator ! is the C++ operator for the Boolean operation NOT. It has only one operand, to its right, and inverts it, producing false if its operand is true, and true if its operand is false. Basically, it returns the opposite Boolean value of evaluating its operand. For example:

The logical operators && and || are used when evaluating two expressions to obtain a single relational result. The operator && corresponds to the Boolean logical operation AND, which yields true if both its operands are true, and false otherwise. The following panel shows the result of operator && evaluating the expression a&&b:

&& OPERATOR (and)
aba && b
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

The operator || corresponds to the Boolean logical operation OR, which yields true if either of its operands is true, thus being false only when both operands are false. Here are the possible results of a||b:

|| OPERATOR (or)
aba || b
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

When using the logical operators, C++ only evaluates what is necessary from left to right to come up with the combined relational result, ignoring the rest. Therefore, in the last example ((5==5)||(3>6)), C++ evaluates first whether 5==5 is true, and if so, it never checks whether 3>6 is true or not. This is known as short-circuit evaluation, and works like this for these operators:

operatorshort-circuit
&&if the left-hand side expression is false, the combined result is false (the right-hand side expression is never evaluated).
||if the left-hand side expression is true, the combined result is true (the right-hand side expression is never evaluated).

This is mostly important when the right-hand expression has side effects, such as altering values:

Here, the combined conditional expression would increase i by one, but only if the condition on the left of && is true, because otherwise, the condition on the right-hand side (++i<n) is never evaluated.

Conditional ternary operator ( ? )


The conditional operator evaluates an expression, returning one value if that expression evaluates to true, and a different one if the expression evaluates as false. Its syntax is:

condition ? result1 : result2

If condition is true, the entire expression evaluates to result1, and otherwise to result2.

For example:

7

In this example, a was 2, and b was 7, so the expression being evaluated (a>b) was not true, thus the first value specified after the question mark was discarded in favor of the second value (the one after the colon) which was b (with a value of 7).

Comma operator ( , )


The comma operator (,) is used to separate two or more expressions that are included where only one expression is expected. When the set of expressions has to be evaluated for a value, only the right-most expression is considered.

For example, the following code:

a = (b=3, b+2);

would first assign the value 3 to b, and then assign b+2 to variable a. So, at the end, variable a would contain the value 5 while variable b would contain value 3.

Bitwise operators ( &, |, ^, ~, <<, >> )


Bitwise operators modify variables considering the bit patterns that represent the values they store.

operatorasm equivalentdescription
&ANDBitwise AND
|ORBitwise inclusive OR
^XORBitwise exclusive OR
~NOTUnary complement (bit inversion)
<<SHLShift bits left
>>SHRShift bits right

Explicit type casting operator


Type casting operators allow to convert a value of a given type to another type. There are several ways to do this in C++. The simplest one, which has been inherited from the C language, is to precede the expression to be converted by the new type enclosed between parentheses (()):

The previous code converts the floating-point number 3.14 to an integer value (3); the remainder is lost. Here, the typecasting operator was (int). Another way to do the same thing in C++ is to use the functional notation preceding the expression to be converted by the type and enclosing the expression between parentheses:

Both ways of casting types are valid in C++.

sizeof


This operator accepts one parameter, which can be either a type or a variable, and returns the size in bytes of that type or object:

Here, x is assigned the value 1, because char is a type with a size of one byte.

The value returned by sizeof is a compile-time constant, so it is always determined before program execution.

Other operators


Later in these tutorials, we will see a few more operators, like the ones referring to pointers or the specifics for object-oriented programming.

Precedence of operators


A single expression may have multiple operators. For example:

In C++, the above expression always assigns 6 to variable x, because the % operator has a higher precedence than the + operator, and is always evaluated before. Parts of the expressions can be enclosed in parenthesis to override this precedence order, or to make explicitly clear the intended effect. Notice the difference:

From greatest to smallest priority, C++ operators are evaluated in the following order:

LevelPrecedence groupOperatorDescriptionGrouping
1Scope::scope qualifierLeft-to-right
2Postfix (unary)++ --postfix increment / decrementLeft-to-right
()functional forms
[]subscript
. ->member access
3Prefix (unary)++ --prefix increment / decrementRight-to-left
~ !bitwise NOT / logical NOT
+ -unary prefix
& *reference / dereference
new deleteallocation / deallocation
sizeofparameter pack
(type)C-style type-casting
4Pointer-to-member.* ->*access pointerLeft-to-right
5Arithmetic: scaling* / %multiply, divide, moduloLeft-to-right
6Arithmetic: addition+ -addition, subtractionLeft-to-right
7Bitwise shift<< >>shift left, shift rightLeft-to-right
8Relational< > <= >=comparison operatorsLeft-to-right
9Equality== !=equality / inequalityLeft-to-right
10And&bitwise ANDLeft-to-right
11Exclusive or^bitwise XORLeft-to-right
12Inclusive or|bitwise ORLeft-to-right
13Conjunction&&logical ANDLeft-to-right
14Disjunction||logical ORLeft-to-right
15Assignment-level expressions= *= /= %= += -=
>>= <<= &= ^= |=
assignment / compound assignmentRight-to-left
?:conditional operator
16Sequencing,comma separatorLeft-to-right

When an expression has two operators with the same precedence level, grouping determines which one is evaluated first: either left-to-right or right-to-left.

5 - C++ INPUT / OUPUT

The example programs of the previous sections provided little interaction with the user, if any at all. They simply printed simple values on screen, but the standard library provides many additional ways to interact with the user via its input/output features. This section will present a short introduction to some of the most useful.

C++ uses a convenient abstraction called streams to perform input and output operations in sequential media such as the screen, the keyboard or a file. A stream is an entity where a program can either insert or extract characters to/from. There is no need to know details about the media associated to the stream or any of its internal specifications. All we need to know is that streams are a source/destination of characters, and that these characters are provided/accepted sequentially (i.e., one after another).

The standard library defines a handful of stream objects that can be used to access what are considered the standard sources and destinations of characters by the environment where the program runs:

streamdescription
cinstandard input stream
coutstandard output stream
cerrstandard error (output) stream
clogstandard logging (output) stream

We are going to see in more detail only cout and cin (the standard output and input streams); cerr and clog are also output streams, so they essentially work like cout, with the only difference being that they identify streams for specific purposes: error messages and logging; which, in many cases, in most environment setups, they actually do the exact same thing: they print on screen, although they can also be individually redirected.

Standard output (cout)


On most program environments, the standard output by default is the screen, and the C++ stream object defined to access it is cout.

For formatted output operations, cout is used together with the insertion operator, which is written as << (i.e., two "less than" signs).

The << operator inserts the data that follows it into the stream that precedes it. In the examples above, it inserted the literal string Output sentence, the number 120, and the value of variable x into the standard output stream cout. Notice that the sentence in the first statement is enclosed in double quotes (") because it is a string literal, while in the last one, x is not. The double quoting is what makes the difference; when the text is enclosed between them, the text is printed literally; when they are not, the text is interpreted as the identifier of a variable, and its value is printed instead. For example, these two sentences have very different results:

Multiple insertion operations (<<) may be chained in a single statement:

This last statement would print the text This is a single C++ statement. Chaining insertions is especially useful to mix literals and variables in a single statement:

Assuming the age variable contains the value 24 and the zipcode variable contains 90064, the output of the previous statement would be: I am 24 years old and my zipcode is 90064 What cout does not do automatically is add line breaks at the end, unless instructed to do so. For example, take the following two statements inserting into cout: cout << "This is a sentence."; cout << "This is another sentence."; The output would be in a single line, without any line breaks in between. Something like: This is a sentence.This is another sentence. To insert a line break, a new-line character shall be inserted at the exact position the line should be broken. In C++, a new-line character can be specified as \n (i.e., a backslash character followed by a lowercase n). For example:

This produces the following output:

First sentence.
Second sentence.
Third sentence.

Alternatively, the endl manipulator can also be used to break lines. For example:

This would print:

First sentence.
Second sentence.

The endl manipulator produces a newline character, exactly as the insertion of '\n' does; but it also has an additional behavior: the stream's buffer (if any) is flushed, which means that the output is requested to be physically written to the device, if it wasn't already. This affects mainly fully buffered streams, and cout is (generally) not a fully buffered stream. Still, it is generally a good idea to use endl only when flushing the stream would be a feature and '\n' when it would not. Bear in mind that a flushing operation incurs a certain overhead, and on some devices it may produce a delay.

Standard input (cin)


In most program environments, the standard input by default is the keyboard, and the C++ stream object defined to access it is cin.

For formatted input operations, cin is used together with the extraction operator, which is written as >> (i.e., two "greater than" signs). This operator is then followed by the variable where the extracted data is stored. For example:

The first statement declares a variable of type int called age, and the second extracts from cin a value to be stored in it. This operation makes the program wait for input from cin; generally, this means that the program will wait for the user to enter some sequence with the keyboard. In this case, note that the characters introduced using the keyboard are only transmitted to the program when the ENTER (or RETURN) key is pressed. Once the statement with the extraction operation on cin is reached, the program will wait for as long as needed until some input is introduced.

The extraction operation on cin uses the type of the variable after the >> operator to determine how it interprets the characters read from the input; if it is an integer, the format expected is a series of digits, if a string a sequence of characters, etc.

As you can see, extracting from cin seems to make the task of getting input from the standard input pretty simple and straightforward. But this method also has a big drawback. What happens in the example above if the user enters something else that cannot be interpreted as an integer? Well, in this case, the extraction operation fails. And this, by default, lets the program continue without setting a value for variable i, producing undetermined results if the value of i is used later.

This is very poor program behavior. Most programs are expected to behave in an expected manner no matter what the user types, handling invalid values appropriately. Only very simple programs should rely on values extracted directly from cin without further checking. A little later we will see how stringstreams can be used to have better control over user input.
Extractions on cin can also be chained to request more than one datum in a single statement:

This is equivalent to:

In both cases, the user is expected to introduce two values, one for variable a, and another for variable b. Any kind of space is used to separate two consecutive input operations; this may either be a space, a tab, or a new-line character.

cin and strings


The extraction operator can be used on cin to get strings of characters in the same way as with fundamental data types:

However, cin extraction always considers spaces (whitespaces, tabs, new-line...) as terminating the value being extracted, and thus extracting a string means to always extract a single word, not a phrase or an entire sentence.

To get an entire line from cin, there exists a function, called getline, that takes the stream (cin) as first argument, and the string variable as second. For example:

What's your name? Homer Simpson
Hello Homer Simpson.
What is your favorite team? The Isotopes
I like The Isotopes too!

Notice how in both calls to getline, we used the same string identifier (mystr). What the program does in the second call is simply replace the previous content with the new one that is introduced.

The standard behavior that most users expect from a console program is that each time the program queries the user for input, the user introduces the field, and then presses ENTER (or RETURN). That is to say, input is generally expected to happen in terms of lines on console programs, and this can be achieved by using getline to obtain input from the user. Therefore, unless you have a strong reason not to, you should always use getline to get input in your console programs instead of extracting from cin.

stringstream


The standard header <sstream> defines a type called stringstream that allows a string to be treated as a stream, and thus allowing extraction or insertion operations from/to strings in the same way as they are performed on cin and cout. This feature is most useful to convert strings to numerical values and vice versa. For example, in order to extract an integer from a string we can write:

This declares a string with initialized to a value of "1204", and a variable of type int. Then, the third line uses this variable to extract from a stringstream constructed from the string. This piece of code stores the numerical value 1204 in the variable called myint.

Enter price: 22.25 Enter quantity: 7 Total price: 155.75

In this example, we acquire numeric values from the standard input indirectly: Instead of extracting numeric values directly from cin, we get lines from it into a string object (mystr), and then we extract the values from this string into the variables price and quantity. Once these are numerical values, arithmetic operations can be performed on them, such as multiplying them to obtain a total price.

With this approach of getting entire lines and extracting their contents, we separate the process of getting user input from its interpretation as data, allowing the input process to be what the user expects, and at the same time gaining more control over the transformation of its content into useful data by the program.

6 - C++ CONTROL STRUCTURE

Statements and flow control


A simple C++ statement is each of the individual instructions of a program, like the variable declarations and expressions seen in previous sections. They always end with a semicolon (;), and are executed in the same order in which they appear in a program.

But programs are not limited to a linear sequence of statements. During its process, a program may repeat segments of code, or take decisions and bifurcate. For that purpose, C++ provides flow control statements that serve to specify what has to be done by our program, when, and under which circumstances.

Many of the flow control statements explained in this section require a generic (sub)statement as part of its syntax. This statement may either be a simple C++ statement, -such as a single instruction, terminated with a semicolon (;) - or a compound statement. A compound statement is a group of statements (each of them terminated by its own semicolon), but all grouped together in a block, enclosed in curly braces: {}:

{ statement1; statement2; statement3; }

The entire block is considered a single statement (composed itself of multiple substatements). Whenever a generic statement is part of the syntax of a flow control statement, this can either be a simple statement or a compound statement.

Selection statements: if and else


The if keyword is used to execute a statement or block, if, and only if, a condition is fulfilled. Its syntax is:

if (condition) statement

Here, condition is the expression that is being evaluated. If this condition is true, statement is executed. If it is false, statement is not executed (it is simply ignored), and the program continues right after the entire selection statement. For example, the following code fragment prints the message (x is 100), only if the value stored in the x variable is indeed 100:

If x is not exactly 100, this statement is ignored, and nothing is printed.

If you want to include more than a single statement to be executed when the condition is fulfilled, these statements shall be enclosed in braces ({}), forming a block:

As usual, indentation and line breaks in the code have no effect, so the above code is equivalent to:

Selection statements with if can also specify what happens when the condition is not fulfilled, by using the else keyword to introduce an alternative statement. Its syntax is:

if (condition) statement1 else statement2

where statement1 is executed in case condition is true, and in case it is not, statement2 is executed.

For example:

This prints x is 100, if indeed x has a value of 100, but if it does not, and only if it does not, it prints x is not 100 instead.
Several if + else structures can be concatenated with the intention of checking a range of values. For example:

This prints whether x is positive, negative, or zero by concatenating two if-else structures. Again, it would have also been possible to execute more than a single statement per case by grouping them into blocks enclosed in braces: {}.

Iteration statements (loops)


Loops repeat a statement a certain number of times, or while a condition is fulfilled. They are introduced by the keywords while, do, and for.

The while loop

The simplest kind of loop is the while-loop. Its syntax is:

while (expression) statement

The while-loop simply repeats statement while expression is true. If, after any execution of statement, expression is no longer true, the loop ends, and the program continues right after the loop. For example, let's have a look at a countdown using a while-loop:

The first statement in main sets n to a value of 10. This is the first number in the countdown. Then the while-loop begins: if this value fulfills the condition n>0 (that n is greater than zero), then the block that follows the condition is executed, and repeated for as long as the condition (n>0) remains being true.

The whole process of the previous program can be interpreted according to the following script (beginning in main):

  1. n is assigned a value
  2. The while condition is checked (n>0). At this point there are two possibilities:
    • condition is true: the statement is executed (to step 3)
    • condition is false: ignore statement and continue after it (to step 5)
  3. Execute statement:
    cout << n << ", ";
    --n;
  4. (prints the value of n and decreases n by 1)
  5. End of block. Return automatically to step 2.
  6. Continue the program right after the block:
    print liftoff! and end the program.

A thing to consider with while-loops is that the loop should end at some point, and thus the statement shall alter values checked in the condition in some way, so as to force it to become false at some point. Otherwise, the loop will continue looping forever. In this case, the loop includes --n, that decreases the value of the variable that is being evaluated in the condition (n) by one - this will eventually make the condition (n>0) false after a certain number of loop iterations. To be more specific, after 10 iterations, n becomes 0, making the condition no longer true, and ending the while-loop.

Note that the complexity of this loop is trivial for a computer, and so the whole countdown is performed instantly, without any practical delay between elements of the count (if interested, see sleep_for for a countdown example with delays).

The do-while loop
A very similar loop is the do-while loop, whose syntax is:

do statement while (condition);

It behaves like a while-loop, except that condition is evaluated after the execution of statement instead of before, guaranteeing at least one execution of statement, even if condition is never fulfilled. For example, the following example program echoes any text the user introduces until the user enters goodbye:

Enter text: hello
You entered: hello
Enter text: who's there?
You entered: who's there?
Enter text: goodbye
You entered: goodbye

The do-while loop is usually preferred over a while-loop when the statement needs to be executed at least once, such as when the condition that is checked to end of the loop is determined within the loop statement itself. In the previous example, the user input within the block is what will determine if the loop ends. And thus, even if the user wants to end the loop as soon as possible by entering goodbye, the block in the loop needs to be executed at least once to prompt for input, and the condition can, in fact, only be determined after it is executed.

The for loop
The for loop is designed to iterate a number of times. Its syntax is:

for (initialization; condition; increase) statement;

Like the while-loop, this loop repeats statement while condition is true. But, in addition, the for loop provides specific locations to contain an initialization and an increase expression, executed before the loop begins the first time, and after each iteration, respectively. Therefore, it is especially useful to use counter variables as condition.

It works in the following way:

  1. initialization is executed. Generally, this declares a counter variable, and sets it to some initial value. This is executed a single time, at the beginning of the loop.
  2. condition is checked. If it is true, the loop continues; otherwise, the loop ends, and statement is skipped, going directly to step 5.
  3. statement is executed. As usual, it can be either a single statement or a block enclosed in curly braces { }.
  4. increase is executed, and the loop gets back to step 2.
  5. the loop ends: execution continues by the next statement after it.

Here is the countdown example using a for loop:

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

The three fields in a for-loop are optional. They can be left empty, but in all cases the semicolon signs between them are required. For example, for (;n<10;) is a loop without initialization or increase (equivalent to a while-loop); and for (;n<10;++n) is a loop with increase, but no initialization (maybe because the variable was already initialized before the loop). A loop with no condition is equivalent to a loop with true as condition (i.e., an infinite loop).

Because each of the fields is executed in a particular time in the life cycle of a loop, it may be useful to execute more than a single expression as any of initialization, condition, or statement. Unfortunately, these are not statements, but rather, simple expressions, and thus cannot be replaced by a block. As expressions, they can, however, make use of the comma operator (,): This operator is an expression separator, and can separate multiple expressions where only one is generally expected. For example, using it, it would be possible for a for loop to handle two counter variables, initializing and increasing both:

This loop will execute 50 times if neither n or i are modified within the loop:

n starts with a value of 0, and i with 100, the condition is n!=i (i.e., that n is not equal to i). Because n is increased by one, and i decreased by one on each iteration, the loop's condition will become false after the 50th iteration, when both n and i are equal to 50.

Range-based for loop
The for-loop has another syntax, which is used exclusively with ranges:

for ( declaration : range ) statement;

This kind of for loop iterates over all the elements in range, where declaration declares some variable able to take the value of an element in this range. Ranges are sequences of elements, including arrays, containers, and any other type supporting the functions begin and end; Most of these types have not yet been introduced in this tutorial, but we are already acquainted with at least one kind of range: strings, which are sequences of characters.

An example of range-based for loop using strings:

[H][e][l][l][o][!]

Note how what precedes the colon (:) in the for loop is the declaration of a char variable (the elements in a string are of type char). We then use this variable, c, in the statement block to represent the value of each of the elements in the range.

This loop is automatic and does not require the explicit declaration of any counter variable.

Range based loops usually also make use of type deduction for the type of the elements with auto. Typically, the range-based loop above can also be written as:

Here, the type of c is automatically deduced as the type of the elements in str.

Jump statements


Jump statements allow altering the flow of a program by performing jumps to specific locations.

The break statement
break leaves a loop, even if the condition for its end is not fulfilled. It can be used to end an infinite loop, or to force it to end before its natural end. For example, let's stop the countdown before its natural end:

10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!

The continue statement

The continue statement causes the program to skip the rest of the loop in the current iteration, as if the end of the statement block had been reached, causing it to jump to the start of the following iteration. For example, let's skip number 5 in our countdown:

10, 9, 8, 7, 6, 4, 3, 2, 1, liftoff!

The goto statement

goto allows to make an absolute jump to another point in the program. This unconditional jump ignores nesting levels, and does not cause any automatic stack unwinding. Therefore, it is a feature to use with care, and preferably within the same block of statements, especially in the presence of local variables.

The destination point is identified by a label, which is then used as an argument for the goto statement. A label is made of a valid identifier followed by a colon (:).

goto is generally deemed a low-level feature, with no particular use cases in modern higher-level programming paradigms generally used with C++. But, just as an example, here is a version of our countdown loop using goto:

10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!

Another selection statement: switch.


The syntax of the switch statement is a bit peculiar. Its purpose is to check for a value among a number of possible constant expressions. It is something similar to concatenating if-else statements, but limited to constant expressions. Its most typical syntax is:

It works in the following way: switch evaluates expression and checks if it is equivalent to constant1; if it is, it executes group-of-statements-1 until it finds the break statement. When it finds this break statement, the program jumps to the end of the entire switch statement (the closing brace).

If expression was not equal to constant1, it is then checked against constant2. If it is equal to this, it executes group-of-statements-2 until a break is found, when it jumps to the end of the switch.

Finally, if the value of expression did not match any of the previously specified constants (there may be any number of these), the program executes the statements included after the default: label, if it exists (since it is optional).

Both of the following code fragments have the same behavior, demonstrating the if-else equivalent of a switch statement:

switch exampleif-else equivalent
switch (x) {
  case 1:
    cout << "x is 1";
    break;
  case 2:
    cout << "x is 2";
    break;
  default:
    cout << "value of x unknown";
  }
if (x == 1) {
  cout << "x is 1";
}
else if (x == 2) {
  cout << "x is 2";
}
else {
  cout << "value of x unknown";
}

The switch statement has a somewhat peculiar syntax inherited from the early times of the first C compilers, because it uses labels instead of blocks. In the most typical use (shown above), this means that break statements are needed after each group of statements for a particular label. If break is not included, all statements following the case (including those under any other labels) are also executed, until the end of the switch block or a jump statement (such as break) is reached.

If the example above lacked the break statement after the first group for case one, the program would not jump automatically to the end of the switch block after printing x is 1, and would instead continue executing the statements in case two (thus printing also x is 2). It would then continue doing so until a break statement is encountered, or the end of the switch block. This makes unnecessary to enclose the statements for each case in braces {}, and can also be useful to execute the same group of statements for different possible values. For example:

Notice that switch is limited to compare its evaluated expression against labels that are constant expressions. It is not possible to use variables as labels or ranges, because they are not valid C++ constant expressions.

7 - C++ FUNCTIONS

Functions allow to structure programs in segments of code to perform individual tasks.

In C++, a function is a group of statements that is given a name, and which can be called from some point of the program. The most common syntax to define a function is:

type name ( parameter1, parameter2, ...) { statements }

Where:
- type is the type of the value returned by the function. - name is the identifier by which the function can be called. - parameters (as many as needed): Each parameter consists of a type followed by an identifier, with each parameter being separated from the next by a comma. Each parameter looks very much like a regular variable declaration (for example: int x), and in fact acts within the function as a regular variable which is local to the function. The purpose of parameters is to allow passing arguments to the function from the location where it is called from.
- statements is the function's body. It is a block of statements surrounded by braces { } that specify what the function actually does.

Let's have a look at an example:

The result is 8

This program is divided in two functions: addition and main. Remember that no matter the order in which they are defined, a C++ program always starts by calling main. In fact, main is the only function called automatically, and the code in any other function is only executed if its function is called from main (directly or indirectly).

In the example above, main begins by declaring the variable z of type int, and right after that, it performs the first function call: it calls addition. The call to a function follows a structure very similar to its declaration. In the example above, the call to addition can be compared to its definition just a few lines earlier:

The parameters in the function declaration have a clear correspondence to the arguments passed in the function call. The call passes two values, 5 and 3, to the function; these correspond to the parameters a and b, declared for function addition.

At the point at which the function is called from within main, the control is passed to function addition: here, execution of main is stopped, and will only resume once the addition function ends. At the moment of the function call, the value of both arguments (5 and 3) are copied to the local variables int a and int b within the function.

Then, inside addition, another local variable is declared (int r), and by means of the expression r=a+b, the result of a plus b is assigned to r; which, for this case, where a is 5 and b is 3, means that 8 is assigned to r.

The final statement within the function:

return r;

Ends function addition, and returns the control back to the point where the function was called; in this case: to function main. At this precise moment, the program resumes its course on main returning exactly at the same point at which it was interrupted by the call to addition. But additionally, because addition has a return type, the call is evaluated as having a value, and this value is the value specified in the return statement that ended addition: in this particular case, the value of the local variable r, which at the moment of the return statement had a value of 8.

Therefore, the call to addition is an expression with the value returned by the function, and in this case, that value, 8, is assigned to z. It is as if the entire function call (addition(5,3)) was replaced by the value it returns (i.e., 8).

Then main simply prints this value by calling:

cout << "The result is " << z;

A function can actually be called multiple times within a program, and its argument is naturally not limited just to literals:

The first result is 5
The second result is 5
The third result is 2
The fourth result is 6

Similar to the addition function in the previous example, this example defines a subtract function, that simply returns the difference between its two parameters. This time, main calls this function several times, demonstrating more possible ways in which a function can be called.

Let's examine each of these calls, bearing in mind that each function call is itself an expression that is evaluated as the value it returns. Again, you can think of it as if the function call was itself replaced by the returned value:

If we replace the function call by the value it returns (i.e., 5), we would have:

With the same procedure, we could interpret:

as:

since 5 is the value returned by subtraction (7,2).

In the case of:

The arguments passed to subtraction are variables instead of literals. That is also valid, and works fine. The function is called with the values x and y have at the moment of the call: 5 and 3 respectively, returning 2 as result.

The fourth call is again similar:

The only addition being that now the function call is also an operand of an addition operation. Again, the result is the same as if the function call was replaced by its result: 6. Note, that thanks to the commutative property of additions, the above can also be written as:

With exactly the same result. Note also that the semicolon does not necessarily go after the function call, but, as always, at the end of the whole statement. Again, the logic behind may be easily seen again by replacing the function calls by their returned value:

Functions with no type. The use of void


he syntax shown above for functions:

type name ( argument1, argument2 ...) { statements }

Requires the declaration to begin with a type. This is the type of the value returned by the function. But what if the function does not need to return a value? In this case, the type to be used is void, which is a special type to represent the absence of value. For example, a function that simply prints a message may not need to return any value:

I'm a function!

void can also be used in the function's parameter list to explicitly specify that the function takes no actual parameters when called. For example, printmessage could have been declared as:

In C++, an empty parameter list can be used instead of void with same meaning, but the use of void in the argument list was popularized by the C language, where this is a requirement.

Something that in no case is optional are the parentheses that follow the function name, neither in its declaration nor when calling it. And even when the function takes no parameters, at least an empty pair of parentheses shall always be appended to the function name. See how printmessage was called in an earlier example:

printmessage ();

The parentheses are what differentiate functions from other kinds of declarations or statements. The following would not call the function:

printmessage;

The return value of main


You may have noticed that the return type of main is int, but most examples in this and earlier chapters did not actually return any value from main.

Well, there is a catch: If the execution of main ends normally without encountering a return statement the compiler assumes the function ends with an implicit return statement:

Note that this only applies to function main for historical reasons. All other functions with a return type shall end with a proper return statement that includes a return value, even if this is never used.

When main returns zero (either implicitly or explicitly), it is interpreted by the environment as that the program ended successfully. Other values may be returned by main, and some environments give access to that value to the caller in some way, although this behavior is not required nor necessarily portable between platforms. The values for main that are guaranteed to be interpreted in the same way on all platforms are:

valuedescription
0The program was successful
EXIT_SUCCESSThe program was successful (same as above).
This value is defined in header <cstdlib>.
EXIT_FAILUREThe program failed.
This value is defined in header <cstdlib>.

Because the implicit return 0; statement for main is a tricky exception, some authors consider it good practice to explicitly write the statement.

Arguments passed by value and by reference


In the functions seen earlier, arguments have always been passed by value. This means that, when calling a function, what is passed to the function are the values of these arguments on the moment of the call, which are copied into the variables represented by the function parameters. For example, take:

In this case, function addition is passed 5 and 3, which are copies of the values of x and y, respectively. These values (5 and 3) are used to initialize the variables set as parameters in the function's definition, but any modification of these variables within the function has no effect on the values of the variables x and y outside it, because x and y were themselves not passed to the function on the call, but only copies of their values at that moment.

In certain cases, though, it may be useful to access an external variable from within a function. To do that, arguments can be passed by reference, instead of by value. For example, the function duplicate in this code duplicates the value of its three arguments, causing the variables used as arguments to actually be modified by the call:

x=2, y=6, z=14

To gain access to its arguments, the function declares its parameters as references. In C++, references are indicated with an ampersand (&) following the parameter type, as in the parameters taken by duplicate in the example above.

When a variable is passed by reference, what is passed is no longer a copy, but the variable itself, the variable identified by the function parameter, becomes somehow associated with the argument passed to the function, and any modification on their corresponding local variables within the function are reflected in the variables passed as arguments in the call.

In fact, a, b, and c become aliases of the arguments passed on the function call (x, y, and z) and any change on a within the function is actually modifying variable x outside the function. Any change on b modifies y, and any change on c modifies z. That is why when, in the example, function duplicate modifies the values of variables a, b, and c, the values of x, y, and z are affected.

If instead of defining duplicate as:

Was it to be defined without the ampersand signs as:

The variables would not be passed by reference, but by value, creating instead copies of their values. In this case, the output of the program would have been the values of x, y, and z without being modified (i.e., 1, 3, and 7).

Efficiency considerations and const references


Calling a function with parameters taken by value causes copies of the values to be made. This is a relatively inexpensive operation for fundamental types such as int, but if the parameter is of a large compound type, it may result on certain overhead. For example, consider the following function:

This function takes two strings as parameters (by value), and returns the result of concatenating them. By passing the arguments by value, the function forces a and b to be copies of the arguments passed to the function when it is called. And if these are long strings, it may mean copying large quantities of data just for the function call.

But this copy can be avoided altogether if both parameters are made references:

Arguments by reference do not require a copy. The function operates directly on (aliases of) the strings passed as arguments, and, at most, it might mean the transfer of certain pointers to the function. In this regard, the version of concatenate taking references is more efficient than the version taking values, since it does not need to copy expensive-to-copy strings.

On the flip side, functions with reference parameters are generally perceived as functions that modify the arguments passed, because that is why reference parameters are actually for.

The solution is for the function to guarantee that its reference parameters are not going to be modified by this function. This can be done by qualifying the parameters as constant:

By qualifying them as const, the function is forbidden to modify the values of neither a nor b, but can actually access their values as references (aliases of the arguments), without having to make actual copies of the strings.

Therefore, const references provide functionality similar to passing arguments by value, but with an increased efficiency for parameters of large types. That is why they are extremely popular in C++ for arguments of compound types. Note though, that for most fundamental types, there is no noticeable difference in efficiency, and in some cases, const references may even be less efficient!

Inline functions


Calling a function generally causes a certain overhead (stacking arguments, jumps, etc...), and thus for very short functions, it may be more efficient to simply insert the code of the function where it is called, instead of performing the process of formally calling a function.

Preceding a function declaration with the inline specifier informs the compiler that inline expansion is preferred over the usual function call mechanism for a specific function. This does not change at all the behavior of a function, but is merely used to suggest the compiler that the code generated by the function body shall be inserted at each point the function is called, instead of being invoked with a regular function call.

For example, the concatenate function above may be declared inline as:

This informs the compiler that when concatenate is called, the program prefers the function to be expanded inline, instead of performing a regular call. inline is only specified in the function declaration, not when it is called.

Note that most compilers already optimize code to generate inline functions when they see an opportunity to improve efficiency, even if not explicitly marked with the inline specifier. Therefore, this specifier merely indicates the compiler that inline is preferred for this function, although the compiler is free to not inline it, and optimize otherwise. In C++, optimization is a task delegated to the compiler, which is free to generate any code for as long as the resulting behavior is the one specified by the code.

Default values in parameters


In C++, functions can also have optional parameters, for which no arguments are required in the call, in such a way that, for example, a function with three parameters may be called with only two. For this, the function shall include a default value for its last parameter, which is used by the function when called with fewer arguments. For example:

6
5

In this example, there are two calls to function divide. In the first one:

divide (12)

The call only passes one argument to the function, even though the function has two parameters. In this case, the function assumes the second parameter to be 2 (notice the function definition, which declares its second parameter as int b=2). Therefore, the result is 6.

In the second call:

divide (20,4)

The call passes two arguments to the function. Therefore, the default value for b (int b=2) is ignored, and b takes the value passed as argument, that is 4, yielding a result of 5.

Declaring functions


In C++, identifiers can only be used in expressions once they have been declared. For example, some variable x cannot be used before being declared with a statement, such as:

int x;

The same applies to functions. Functions cannot be called before they are declared. That is why, in all the previous examples of functions, the functions were always defined before the main function, which is the function from where the other functions were called. If main were defined before the other functions, this would break the rule that functions shall be declared before being used, and thus would not compile.

The prototype of a function can be declared without actually defining the function completely, giving just enough details to allow the types involved in a function call to be known. Naturally, the function shall be defined somewhere else, like later in the code. But at least, once declared like this, it can already be called.

The declaration shall include all types involved (the return type and the type of its arguments), using the same syntax as used in the definition of the function, but replacing the body of the function (the block of statements) with an ending semicolon.

The parameter list does not need to include the parameter names, but only their types. Parameter names can nevertheless be specified, but they are optional, and do not need to necessarily match those in the function definition. For example, a function called protofunction with two int parameters can be declared with either of these statements:

Anyway, including a name for each parameter always improves legibility of the declaration.

Please, enter number (0 to exit): 9
It is odd.
Please, enter number (0 to exit): 6
It is even.
Please, enter number (0 to exit): 1030
It is even.
Please, enter number (0 to exit): 0
It is even.

This example is indeed not an example of efficiency. You can probably write yourself a version of this program with half the lines of code. Anyway, this example illustrates how functions can be declared before its definition:

The following lines:

Declare the prototype of the functions. They already contain all what is necessary to call them, their name, the types of their argument, and their return type (void in this case). With these prototype declarations in place, they can be called before they are entirely defined, allowing for example, to place the function from where they are called (main) before the actual definition of these functions.

But declaring functions before being defined is not only useful to reorganize the order of functions within the code. In some cases, such as in this particular case, at least one of the declarations is required, because odd and even are mutually called; there is a call to even in odd and a call to odd in even. And, therefore, there is no way to structure the code so that odd is defined before even, and even before odd.

Recursivity


Recursivity is the property that functions have to be called by themselves. It is useful for some tasks, such as sorting elements, or calculating the factorial of numbers. For example, in order to obtain the factorial of a number (n!) the mathematical formula would be:

n! = n * (n-1) * (n-2) * (n-3) ... * 1
More concretely, 5! (factorial of 5) would be:

5! = 5 * 4 * 3 * 2 * 1 = 120
And a recursive function to calculate this in C++ could be:

Notice how in function factorial we included a call to itself, but only if the argument passed was greater than 1, since, otherwise, the function would perform an infinite recursive loop, in which once it arrived to 0, it would continue multiplying by all the negative numbers (probably provoking a stack overflow at some point during runtime).

8 - C++ OVERLOADS AND TEMPLATES

Overloaded functions


In C++, two different functions can have the same name if their parameters are different; either because they have a different number of parameters, or because any of their parameters are of a different type. For example:

In this example, there are two functions called operate, but one of them has two parameters of type int, while the other has them of type double. The compiler knows which one to call in each case by examining the types passed as arguments when the function is called. If it is called with two int arguments, it calls to the function that has two int parameters, and if it is called with two doubles, it calls the one with two doubles.

In this example, both functions have quite different behaviors, the int version multiplies its arguments, while the double version divides them. This is generally not a good idea. Two functions with the same name are generally expected to have -at least- a similar behavior, but this example demonstrates that is entirely possible for them not to. Two overloaded functions (i.e., two functions with the same name) have entirely different definitions; they are, for all purposes, different functions, that only happen to have the same name.

Note that a function cannot be overloaded only by its return type. At least one of its parameters must have a different type.

Function templates


Overloaded functions may have the same definition. For example:

Here, sum is overloaded with different parameter types, but with the exact same body.

The function sum could be overloaded for a lot of types, and it could make sense for all of them to have the same body. For cases such as this, C++ has the ability to define functions with generic types, known as function templates. Defining a function template follows the same syntax as a regular function, except that it is preceded by the template keyword and a series of template parameters enclosed in angle-brackets <>:<br>
template <template-parameters> function-declaration The template parameters are a series of parameters separated by commas. These parameters can be generic template types by specifying either the class or typename keyword followed by an identifier. This identifier can then be used in the function declaration as if it was a regular type. For example, a generic sum function could be defined as:

It makes no difference whether the generic type is specified with keyword class or keyword typename in the template argument list (they are 100% synonyms in template declarations).

In the code above, declaring SomeType (a generic type within the template parameters enclosed in angle-brackets) allows SomeType to be used anywhere in the function definition, just as any other type; it can be used as the type for parameters, as return type, or to declare new variables of this type. In all cases, it represents a generic type that will be determined on the moment the template is instantiated.

Instantiating a template is applying the template to create a function using particular types or values for its template parameters. This is done by calling the function template, with the same syntax as calling a regular function, but specifying the template arguments enclosed in angle brackets:

name <template-arguments> (function-arguments) For example, the sum function template defined above can be called with:

x = sum<int>(10,20);

The function sum<int> is just one of the possible instantiations of function template sum. In this case, by using int as template argument in the call, the compiler automatically instantiates a version of sum where each occurrence of SomeType is replaced by int, as if it was defined as:

Let's see an actual example:

In this case, we have used T as the template parameter name, instead of SomeType. It makes no difference, and T is actually a quite common template parameter name for generic types.

In the example above, we used the function template sum twice. The first time with arguments of type int, and the second one with arguments of type double. The compiler has instantiated and then called each time the appropriate version of the function.

Note also how T is also used to declare a local variable of that (generic) type within sum:

T result;

Therefore, result will be a variable of the same type as the parameters a and b, and as the type returned by the function. In this specific case where the generic type T is used as a parameter for sum, the compiler is even able to deduce the data type automatically without having to explicitly specify it within angle brackets. Therefore, instead of explicitly specifying the template arguments with:

It is possible to instead simply write:

without the type enclosed in angle brackets. Naturally, for that, the type shall be unambiguous. If sum is called with arguments of different types, the compiler may not be able to deduce the type of T automatically.

Templates are a powerful and versatile feature. They can have multiple template parameters, and the function can still use regular non-templated types. For example:


Note that this example uses automatic template parameter deduction in the call to are_equal:

are_equal(10,10.0)

Is equivalent to:

are_equal<int,double>(10,10.0)

There is no ambiguity possible because numerical literals are always of a specific type: Unless otherwise specified with a suffix, integer literals always produce values of type int, and floating-point literals always produce values of type double. Therefore 10 has always type int and 10.0 has always type double.

Non-type template arguments


The template parameters can not only include types introduced by class or typename, but can also include expressions of a particular type:

20
30

The second argument of the fixed_multiply function template is of type int. It just looks like a regular function parameter, and can actually be used just like one.

But there exists a major difference: the value of template parameters is determined on compile-time to generate a different instantiation of the function fixed_multiply, and thus the value of that argument is never passed during runtime: The two calls to fixed_multiply in main essentially call two versions of the function: one that always multiplies by two, and one that always multiplies by three. For that same reason, the second template argument needs to be a constant expression (it cannot be passed a variable).

9 - C++ NAME VISIBILITY

Scopes


Named entities, such as variables, functions, and compound types need to be declared before being used in C++. The point in the program where this declaration happens influences its visibility:

An entity declared outside any block has global scope, meaning that its name is valid anywhere in the code. While an entity declared within a block, such as a function or a selective statement, has block scope, and is only visible within the specific block in which it is declared, but not outside it.

Variables with block scope are known as local variables.

For example, a variable declared in the body of a function is a local variable that extends until the end of the the function (i.e., until the brace } that closes the function definition), but not outside it:

In each scope, a name can only represent one entity. For example, there cannot be two variables with the same name in the same scope:

The visibility of an entity with block scope extends until the end of the block, including inner blocks. Nevertheless, an inner block, because it is a different block, can re-utilize a name existing in an outer scope to refer to a different entity; in this case, the name will refer to a different entity only within the inner block, hiding the entity it names outside. While outside it, it will still refer to the original entity. For example:

Note that y is not hidden in the inner block, and thus accessing y still accesses the outer variable.

Variables declared in declarations that introduce a block, such as function parameters and variables declared in loops and conditions (such as those declared on a for or an if) are local to the block they introduce.

Namespaces


Only one entity can exist with a particular name in a particular scope. This is seldom a problem for local names, since blocks tend to be relatively short, and names have particular purposes within them, such as naming a counter variable, an argument, etc...

But non-local names bring more possibilities for name collision, especially considering that libraries may declare many functions, types, and variables, neither of them local in nature, and some of them very generic.

Namespaces allow us to group named entities that otherwise would have global scope into narrower scopes, giving them namespace scope. This allows organizing the elements of programs into different logical scopes referred to by names.

The syntax to declare a namespaces is:

Where identifier is any valid identifier and named_entities is the set of variables, types and functions that are included within the namespace. For example:

In this case, the variables a and b are normal variables declared within a namespace called myNamespace.

These variables can be accessed from within their namespace normally, with their identifier (either a or b), but if accessed from outside the myNamespace namespace they have to be properly qualified with the scope operator ::. For example, to access the previous variables from outside myNamespace they should be qualified like:

Namespaces are particularly useful to avoid name collisions. For example:

5
6.2832
3.1416

In this case, there are two functions with the same name: value. One is defined within the namespace foo, and the other one in bar. No redefinition errors happen thanks to namespaces. Notice also how pi is accessed in an unqualified manner from within namespace bar (just as pi), while it is again accessed in main, but here it needs to be qualified as bar::pi.

Namespaces can be split: Two segments of a code can be declared in the same namespace:

This declares three variables: a and c are in namespace foo, while b is in namespace bar. Namespaces can even extend across different translation units (i.e., across different files of source code).

using


The keyword using introduces a name into the current declarative region (such as a block), thus avoiding the need to qualify the name. For example:

5
2.7183
10
3.1416

Notice how in main, the variable x (without any name qualifier) refers to first::x, whereas y refers to second::y, just as specified by the using declarations. The variables first::y and second::x can still be accessed, but require fully qualified names.

The keyword using can also be used as a directive to introduce an entire namespace:

5
10
3.1416
2.7183

In this case, by declaring that we were using namespace first, all direct uses of x and y without name qualifiers were also looked up in namespace first.

using and using namespace have validity only in the same block in which they are stated or in the entire source code file if they are used directly in the global scope. For example, it would be possible to first use the objects of one namespace and then those of another one by splitting the code in different blocks:

5
3.1416

Namespace aliasing


Existing namespaces can be aliased with new names, with the following syntax:

namespace new_name = current_name;

The std namespace


All the entities (variables, types, constants, and functions) of the standard C++ library are declared within the std namespace. Most examples in these tutorials, in fact, include the following line:

using namespace std;

This introduces direct visibility of all the names of the std namespace into the code. This is done in these tutorials to facilitate comprehension and shorten the length of the examples, but many programmers prefer to qualify each of the elements of the standard library used in their programs. For example, instead of:

cout << "Hello world!";

It is common to instead see:

std::cout << "Hello world!";

Whether the elements in the std namespace are introduced with using declarations or are fully qualified on every use does not change the behavior or efficiency of the resulting program in any way. It is mostly a matter of style preference, although for projects mixing libraries, explicit qualification tends to be preferred.

Whether the elements in the std namespace are introduced with using declarations or are fully qualified on every use does not change the behavior or efficiency of the resulting program in any way. It is mostly a matter of style preference, although for projects mixing libraries, explicit qualification tends to be preferred.

Storage classes


The storage for variables with global or namespace scope is allocated for the entire duration of the program. This is known as static storage, and it contrasts with the storage for local variables (those declared within a block). These use what is known as automatic storage. The storage for local variables is only available during the block in which they are declared; after that, that same storage may be used for a local variable of some other function, or used otherwise.

But there is another substantial difference between variables with static storage and variables with automatic storage:
- Variables with static storage (such as global variables) that are not explicitly initialized are automatically initialized to zeroes. - Variables with automatic storage (such as local variables) that are not explicitly initialized are left uninitialized, and thus have an undetermined value.

For example:

0
4285838

The actual output may vary, but only the value of x is guaranteed to be zero. y can actually contain just about any value (including zero).

10 - C++ ARRAYS

An array is a series of elements of the same type placed in contiguous memory locations that can be individually referenced by adding an index to a unique identifier.

That means that, for example, five values of type int can be declared as an array without having to declare 5 different variables (each with its own identifier). Instead, using an array, the five int values are stored in contiguous memory locations, and all five can be accessed using the same identifier, with the proper index.

For example, an array containing 5 integer values of type int called foo could be represented as:

where each blank panel represents an element of the array. In this case, these are values of type int. These elements are numbered from 0 to 4, being 0 the first and 4 the last; In C++, the first element in an array is always numbered with a zero (not a one), no matter its length.

Like a regular variable, an array must be declared before it is used. A typical declaration for an array in C++ is:

type name [elements];

where type is a valid type (such as int, float...), name is a valid identifier and the elements field (which is always enclosed in square brackets []), specifies the length of the array in terms of the number of elements.

Therefore, the foo array, with five elements of type int, can be declared as:

int foo [5];

NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.

Initializing arrays


By default, regular arrays of local scope (for example, those declared within a function) are left uninitialized. This means that none of its elements are set to any particular value; their contents are undetermined at the point the array is declared.

But the elements in an array can be explicitly initialized to specific values when it is declared, by enclosing those initial values in braces {}. For example:

int foo [5] = { 16, 2, 77, 40, 12071 };

This statement declares an array that can be represented like this:

The number of values between braces {} shall not be greater than the number of elements in the array. For example, in the example above, foo was declared having 5 elements (as specified by the number enclosed in square brackets, []), and the braces {} contained exactly 5 values, one for each element. If declared with less, the remaining elements are set to their default values (which for fundamental types, means they are filled with zeroes). For example:

int bar [5] = { 10, 20, 30 };

Will create an array like this:

The initializer can even have no values, just the braces:

int baz [5] = { };

This creates an array of five int values, each initialized with a value of zero:

When an initialization of values is provided for an array, C++ allows the possibility of leaving the square brackets empty []. In this case, the compiler will assume automatically a size for the array that matches the number of values included between the braces {}:

int foo [] = { 16, 2, 77, 40, 12071 };

After this declaration, array foo would be 5 int long, since we have provided 5 initialization values.

Finally, the evolution of C++ has led to the adoption of universal initialization also for arrays. Therefore, there is no longer need for the equal sign between the declaration and the initializer. Both these statements are equivalent:

int foo[] = { 10, 20, 30 };
int foo[] { 10, 20, 30 };

Static arrays, and those declared directly in a namespace (outside any function), are always initialized. If no explicit initializer is specified, all the elements are default-initialized (with zeroes, for fundamental types).

Accessing the values of an array


The values of any of the elements in an array can be accessed just like the value of a regular variable of the same type. The syntax is:

name[index]
Following the previous examples in which foo had 5 elements and each of those elements was of type int, the name which can be used to refer to each element is the following:

For example, the following statement stores the value 75 in the third element of foo:

foo [2] = 75;

and, for example, the following copies the value of the third element of foo to a variable called x:

x = foo[2];

Therefore, the expression foo[2] is itself a variable of type int. Notice that the third element of foo is specified foo[2], since the first one is foo[0], the second one is foo[1], and therefore, the third one is foo[2]. By this same reason, its last element is foo[4]. Therefore, if we write foo[5], we would be accessing the sixth element of foo, and therefore actually exceeding the size of the array.

In C++, it is syntactically correct to exceed the valid range of indices for an array. This can create problems, since accessing out-of-range elements do not cause errors on compilation, but can cause errors on runtime. The reason for this being allowed will be seen in a later chapter when pointers are introduced.

At this point, it is important to be able to clearly distinguish between the two uses that brackets [] have related to arrays. They perform two different tasks: one is to specify the size of arrays when they are declared; and the second one is to specify indices for concrete array elements when they are accessed. Do not confuse these two possible uses of brackets [] with arrays.

12206

Multidimensional arrays


Multidimensional arrays can be described as "arrays of arrays". For example, a bidimensional array can be imagined as a two-dimensional table made of elements, all of them of a same uniform data type.

jimmy represents a bidimensional array of 3 per 5 elements of type int. The C++ syntax for this is:

int jimmy [3][5];

and, for example, the way to reference the second element vertically and fourth horizontally in an expression would be:

jimmy[1][3]

(remember that array indices always begin with zero).

Multidimensional arrays are not limited to two indices (i.e., two dimensions). They can contain as many indices as needed. Although be careful: the amount of memory needed for an array increases exponentially with each dimension. For example:

char century [100][365][24][60][60];

declares an array with an element of type char for each second in a century. This amounts to more than 3 billion char! So this declaration would consume more than 3 gigabytes of memory!

At the end, multidimensional arrays are just an abstraction for programmers, since the same results can be achieved with a simple array, by multiplying its indices:

int jimmy [3][5]; // is equivalent to int jimmy [15]; // (3 * 5 = 15)

With the only difference that with multidimensional arrays, the compiler automatically remembers the depth of each imaginary dimension. The following two pieces of code produce the exact same result, but one uses a bidimensional array while the other uses a simple array:

multidimensional arraypseudo-multidimensional array
#define WIDTH 5
#define HEIGHT 3

int jimmy [HEIGHT][WIDTH];
int n,m;

int main ()
{
  for (n=0; n<HEIGHT; n++)
    for (m=0; m<WIDTH; m++)
    {
      jimmy[n][m]=(n+1)*(m+1);
    }
}
#define WIDTH 5
#define HEIGHT 3

int jimmy [HEIGHT * WIDTH];
int n,m;

int main ()
{
  for (n=0; n<HEIGHT; n++)
    for (m=0; m<WIDTH; m++)
    {
      jimmy[n*WIDTH+m]=(n+1)*(m+1);
    }
}

None of the two code snippets above produce any output on the screen, but both assign values to the memory block called jimmy in the following way:

Note that the code uses defined constants for the width and height, instead of using directly their numerical values. This gives the code a better readability, and allows changes in the code to be made easily in one place.

Arrays as parameters


At some point, we may need to pass an array to a function as a parameter. In C++, it is not possible to pass the entire block of memory represented by an array to a function directly as an argument. But what can be passed instead is its address. In practice, this has almost the same effect, and it is a much faster and more efficient operation.

To accept an array as parameter for a function, the parameters can be declared as the array type, but with empty brackets, omitting the actual size of the array. For example:

void procedure (int arg[])

This function accepts a parameter of type "array of int" called arg. In order to pass to this function an array declared as:

int myarray [40];

it would be enough to write a call like this:

procedure (myarray);

Here you have a complete example:

5 10 15
2 4 6 8 10

In the code above, the first parameter (int arg[]) accepts any array whose elements are of type int, whatever its length. For that reason, we have included a second parameter that tells the function the length of each array that we pass to it as its first parameter. This allows the for loop that prints out the array to know the range to iterate in the array passed, without going out of range.

In a function declaration, it is also possible to include multidimensional arrays. The format for a tridimensional array parameter is:

base_type[][depth][depth]

For example, a function with a multidimensional array as argument could be:

void procedure (int myarray[][3][4])

Notice that the first brackets [] are left empty, while the following ones specify sizes for their respective dimensions. This is necessary in order for the compiler to be able to determine the depth of each additional dimension.

In a way, passing an array as argument always loses a dimension. The reason behind is that, for historical reasons, arrays cannot be directly copied, and thus what is really passed is a pointer. This is a common source of errors for novice programmers. Although a clear understanding of pointers, explained in a coming chapter, helps a lot.

Library arrays


The arrays explained above are directly implemented as a language feature, inherited from the C language. They are a great feature, but by restricting its copy and easily decay into pointers, they probably suffer from an excess of optimization.

To overcome some of these issues with language built-in arrays, C++ provides an alternative array type as a standard container. It is a type template (a class template, in fact) defined in header <array>.

Containers are a library feature that falls out of the scope of this tutorial, and thus the class will not be explained in detail here. Suffice it to say that they operate in a similar way to built-in arrays, except that they allow being copied (an actually expensive operation that copies the entire block of memory, and thus to use with care) and decay into pointers only when explicitly told to do so (by means of its member data).

Just as an example, these are two versions of the same example using the language built-in array described in this chapter, and the container in the library:

language built-in arraycontainer library array
#include <iostream>

using namespace std;

int main()
{
  int myarray[3] = {10,20,30};

  for (int i=0; i<3; ++i)
    ++myarray[i];

  for (int elem : myarray)
    cout << elem << '\n';
}
#include <iostream>
#include <array>
using namespace std;

int main()
{
  array<int,3> myarray {10,20,30};

  for (int i=0; i<myarray.size(); ++i)
    ++myarray[i];

  for (int elem : myarray)
    cout << elem << '\n';
}

As you can see, both kinds of arrays use the same syntax to access its elements: myarray[i]. Other than that, the main differences lay on the declaration of the array, and the inclusion of an additional header for the library array. Notice also how it is easy to access the size of the library array.

11 - C++ CHARACTER SWQUENCES

The string class has been briefly introduced in an earlier chapter. It is a very powerful class to handle and manipulate strings of characters. However, because strings are, in fact, sequences of characters, we can represent them also as plain arrays of elements of a character type.

For example, the following array:

char foo [20];

is an array that can store up to 20 elements of type char. It can be represented as:

Therefore, this array has a capacity to store sequences of up to 20 characters. But this capacity does not need to be fully exhausted: the array can also accommodate shorter sequences. For example, at some point in a program, either the sequence "Hello" or the sequence "Merry Christmas" can be stored in foo, since both would fit in a sequence with a capacity for 20 characters.

By convention, the end of strings represented in character sequences is signaled by a special character: the null character, whose literal value can be written as '\0' (backslash, zero).

In this case, the array of 20 elements of type char called foo can be represented storing the character sequences "Hello" and "Merry Christmas" as:

Notice how after the content of the string itself, a null character ('\0') has been added in order to indicate the end of the sequence. The panels in gray color represent char elements with undetermined values.

Initialization of null-terminated character sequences


Because arrays of characters are ordinary arrays, they follow the same rules as these. For example, to initialize an array of characters with some predetermined sequence of characters, we can do it just like any other array:

char myword[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

The above declares an array of 6 elements of type char initialized with the characters that form the word "Hello" plus a null character '\0' at the end.

But arrays of character elements have another way to be initialized: using string literals directly.

In the expressions used in some examples in previous chapters, string literals have already shown up several times. These are specified by enclosing the text between double quotes ("). For example:

"the result is: "

This is a string literal, probably used in some earlier example.

Sequences of characters enclosed in double-quotes (") are literal constants. And their type is, in fact, a null-terminated array of characters. This means that string literals always have a null character ('\0') automatically appended at the end.

Therefore, the array of char elements called myword can be initialized with a null-terminated sequence of characters by either one of these two statements:

char myword[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
char myword[] = "Hello";

In both cases, the array of characters myword is declared with a size of 6 elements of type char: the 5 characters that compose the word "Hello", plus a final null character ('\0'), which specifies the end of the sequence and that, in the second case, when using double quotes (") it is appended automatically.

Please notice that here we are talking about initializing an array of characters at the moment it is being declared, and not about assigning values to them later (once they have already been declared). In fact, because string literals are regular arrays, they have the same restrictions as these, and cannot be assigned values.

Expressions (once myword has already been declared as above), such as:

myword = "Bye";
myword[] = "Bye";

would not be valid, like neither would be:

myword = { 'B', 'y', 'e', '\0' };

This is because arrays cannot be assigned values. Note, though, that each of its elements can be assigned a value individually. For example, this would be correct:

myword[0] = 'B';
myword[1] = 'y';
myword[2] = 'e';
myword[3] = '\0';

Strings and null-terminated character sequences


Plain arrays with null-terminated sequences of characters are the typical types used in the C language to represent strings (that is why they are also known as C-strings). In C++, even though the standard library defines a specific type for strings (class string), still, plain arrays with null-terminated sequences of characters (C-strings) are a natural way of representing strings in the language; in fact, string literals still always produce null-terminated character sequences, and not string objects.

In the standard library, both representations for strings (C-strings and library strings) coexist, and most functions requiring strings are overloaded to support both.

For example, cin and cout support null-terminated sequences directly, allowing them to be directly extracted from cin or inserted into cout, just like strings. For example:

What is your name? Homer
Where do you live? Greece
Hello, Homer from Greece!

In this example, both arrays of characters using null-terminated sequences and strings are used. They are quite interchangeable in their use together with cin and cout, but there is a notable difference in their declarations: arrays have a fixed size that needs to be specified either implicit or explicitly when declared; question1 has a size of exactly 20 characters (including the terminating null-characters) and answer1 has a size of 80 characters; while strings are simply strings, no size is specified. This is due to the fact that strings have a dynamic size determined during runtime, while the size of arrays is determined on compilation, before the program runs.

In any case, null-terminated character sequences and strings are easily transformed from one another:

Null-terminated character sequences can be transformed into strings implicitly, and strings can be transformed into null-terminated character sequences by using either of string's member functions c_str or data:

(note: both c_str and data members of string are equivalent)

12 - C++ POINTERS

In earlier chapters, variables have been explained as locations in the computer's memory which can be accessed by their identifier (their name). This way, the program does not need to care about the physical address of the data in memory; it simply uses the identifier whenever it needs to refer to the variable.

For a C++ program, the memory of a computer is like a succession of memory cells, each one byte in size, and each with a unique address. These single-byte memory cells are ordered in a way that allows data representations larger than one byte to occupy memory cells that have consecutive addresses.

This way, each cell can be easily located in the memory by means of its unique address. For example, the memory cell with the address 1776 always follows immediately after the cell with address 1775 and precedes the one with 1777, and is exactly one thousand cells after 776 and exactly one thousand cells before 2776.

When a variable is declared, the memory needed to store its value is assigned a specific location in memory (its memory address). Generally, C++ programs do not actively decide the exact memory addresses where its variables are stored. Fortunately, that task is left to the environment where the program is run - generally, an operating system that decides the particular memory locations on runtime. However, it may be useful for a program to be able to obtain the address of a variable during runtime in order to access data cells that are at a certain position relative to it.

Address-of operator (&)


The address of a variable can be obtained by preceding the name of a variable with an ampersand sign (&), known as address-of operator. For example:

foo = &myvar;

This would assign the address of variable myvar to foo; by preceding the name of the variable myvar with the address-of operator (&), we are no longer assigning the content of the variable itself to foo, but its address.

The actual address of a variable in memory cannot be known before runtime, but let's assume, in order to help clarify some concepts, that myvar is placed during runtime in the memory address 1776.

In this case, consider the following code fragment:

myvar = 25;
foo = &myvar;
bar = myvar;

The values contained in each variable after the execution of this are shown in the following diagram:

First, we have assigned the value 25 to myvar (a variable whose address in memory we assumed to be 1776).

The second statement assigns foo the address of myvar, which we have assumed to be 1776.

Finally, the third statement, assigns the value contained in myvar to bar. This is a standard assignment operation, as already done many times in earlier chapters.

The main difference between the second and third statements is the appearance of the address-of operator (&).

The variable that stores the address of another variable (like foo in the previous example) is what in C++ is called a pointer. Pointers are a very powerful feature of the language that has many uses in lower level programming. A bit later, we will see how to declare and use pointers.

Dereference operator (*)


As just seen, a variable which stores the address of another variable is called a pointer. Pointers are said to "point to" the variable whose address they store.

An interesting property of pointers is that they can be used to access the variable they point to directly. This is done by preceding the pointer name with the dereference operator (*). The operator itself can be read as "value pointed to by".

Therefore, following with the values of the previous example, the following statement:

baz = *foo;

This could be read as: "baz equal to value pointed to by foo", and the statement would actually assign the value 25 to baz, since foo is 1776, and the value pointed to by 1776 (following the example above) would be 25.

It is important to clearly differentiate that foo refers to the value 1776, while *foo (with an asterisk * preceding the identifier) refers to the value stored at address 1776, which in this case is 25. Notice the difference of including or not including the dereference operator (I have added an explanatory comment of how each of these two expressions could be read):

The reference and dereference operators are thus complementary:

  • & is the address-of operator, and can be read simply as "address of"
  • * is the dereference operator, and can be read as "value pointed to by"

Thus, they have sort of opposite meanings: An address obtained with & can be dereferenced with *.

Earlier, we performed the following two assignment operations:

myvar = 25;
foo = &myvar;

Right after these two statements, all of the following expressions would give true as result:

myvar == 25
&myvar == 1776
foo == 1776
*foo == 25

The first expression is quite clear, considering that the assignment operation performed on myvar was myvar=25. The second one uses the address-of operator (&), which returns the address of myvar, which we assumed it to have a value of 1776. The third one is somewhat obvious, since the second expression was true and the assignment operation performed on foo was foo=&myvar. The fourth expression uses the dereference operator (*) that can be read as "value pointed to by", and the value pointed to by foo is indeed 25.

So, after all that, you may also infer that for as long as the address pointed to by foo remains unchanged, the following expression will also be true:

*foo == myvar

Declaring pointers


Due to the ability of a pointer to directly refer to the value that it points to, a pointer has different properties when it points to a char than when it points to an int or a float. Once dereferenced, the type needs to be known. And for that, the declaration of a pointer needs to include the data type the pointer is going to point to.

The declaration of pointers follows this syntax:
type * name;

where type is the data type pointed to by the pointer. This type is not the type of the pointer itself, but the type of the data the pointer points to. For example:

int * number;
char * character;
double * decimals;

These are three declarations of pointers. Each one is intended to point to a different data type, but, in fact, all of them are pointers and all of them are likely going to occupy the same amount of space in memory (the size in memory of a pointer depends on the platform where the program runs). Nevertheless, the data to which they point to do not occupy the same amount of space nor are of the same type: the first one points to an int, the second one to a char, and the last one to a double. Therefore, although these three example variables are all of them pointers, they actually have different types: int*, char*, and double* respectively, depending on the type they point to.

Note that the asterisk (*) used when declaring a pointer only means that it is a pointer (it is part of its type compound specifier), and should not be confused with the dereference operator seen a bit earlier, but which is also written with an asterisk (*). They are simply two different things represented with the same sign.

Let's see an example on pointers:

firstvalue is 10
secondvalue is 20

Notice that even though neither firstvalue nor secondvalue are directly set any value in the program, both end up with a value set indirectly through the use of mypointer. This is how it happens:

First, mypointer is assigned the address of firstvalue using the address-of operator (&). Then, the value pointed to by mypointer is assigned a value of 10. Because, at this moment, mypointer is pointing to the memory location of firstvalue, this in fact modifies the value of firstvalue.

In order to demonstrate that a pointer may point to different variables during its lifetime in a program, the example repeats the process with secondvalue and that same pointer, mypointer.

Here is an example a little bit more elaborated:

firstvalue is 10
secondvalue is 20

Each assignment operation includes a comment on how each line could be read: i.e., replacing ampersands (&) by "address of", and asterisks (*) by "value pointed to by".

Notice that there are expressions with pointers p1 and p2, both with and without the dereference operator (*). The meaning of an expression using the dereference operator (*) is very different from one that does not. When this operator precedes the pointer name, the expression refers to the value being pointed, while when a pointer name appears without this operator, it refers to the value of the pointer itself (i.e., the address of what the pointer is pointing to).

Another thing that may call your attention is the line:

int * p1, * p2;

This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have type int* (pointer to int). This is required due to the precedence rules. Note that if, instead, the code was:

int * p1, p2;

p1 would indeed be of type int*, but p2 would be of type int. Spaces do not matter at all for this purpose. But anyway, simply remembering to put one asterisk per pointer is enough for most pointer users interested in declaring multiple pointers per statement. Or even better: use a different statemet for each variable.

Pointers and arrays


The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type. For example, consider these two declarations:

int myarray [20];
int * mypointer;

The following assignment operation would be valid:

mypointer = myarray;

After that, mypointer and myarray would be equivalent and would have very similar properties. The main difference being that mypointer can be assigned a different address, whereas myarray can never be assigned anything, and will always represent the same block of 20 elements of type int. Therefore, the following assignment would not be valid:

myarray = mypointer;

Let's see an example that mixes arrays and pointers:

10, 20, 30, 40, 50,

Pointers and arrays support the same set of operations, with the same meaning for both. The main difference being that pointers can be assigned new addresses, while arrays cannot.

In the chapter about arrays, brackets ([]) were explained as specifying the index of an element of the array. Well, in fact these brackets are a dereferencing operator known as offset operator. They dereference the variable they follow just as * does, but they also add the number between brackets to the address being dereferenced. For example:

a[5] = 0; // a [offset of 5] = 0
*(a+5) = 0; // pointed to by (a+5) = 0
<p.These two expressions are equivalent and valid, not only if a is a pointer, but also if a is an array. Remember that if an array, its name can be used just like a pointer to its first element.

Pointer initialization


Pointers can be initialized to point to specific locations at the very moment they are defined:

int myvar;
int * myptr = &myvar;

The resulting state of variables after this code is the same as after:

int myvar;
int * myptr;
myptr = &myvar;

When pointers are initialized, what is initialized is the address they point to (i.e., myptr), never the value being pointed (i.e., *myptr). Therefore, the code above shall not be confused with:

int myvar;
int * myptr;
*myptr = &myvar;

Which anyway would not make much sense (and is not valid code).

The asterisk (*) in the pointer declaration (line 2) only indicates that it is a pointer, it is not the dereference operator (as in line 3). Both things just happen to use the same sign: *. As always, spaces are not relevant, and never change the meaning of an expression.

Pointers can be initialized either to the address of a variable (such as in the case above), or to the value of another pointer (or array):

int myvar;
int *foo = &myvar;
int *bar = foo;

Pointer arithmetics


To conduct arithmetical operations on pointers is a little different than to conduct them on regular integer types. To begin with, only addition and subtraction operations are allowed; the others make no sense in the world of pointers. But both addition and subtraction have a slightly different behavior with pointers, according to the size of the data type to which they point.

When fundamental data types were introduced, we saw that types have different sizes. For example: char always has a size of 1 byte, short is generally larger than that, and int and long are even larger; the exact size of these being dependent on the system. For example, let's imagine that in a given system, char takes 1 byte, short takes 2 bytes, and long takes 4.

Suppose now that we define three pointers in this compiler:

char *mychar;
short *myshort;
long *mylong;

and that we know that they point to the memory locations 1000, 2000, and 3000, respectively.

Therefore, if we write:

++mychar;
++myshort;
++mylong;

mychar, as one would expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each been incremented only once. The reason is that, when adding one to a pointer, the pointer is made to point to the following element of the same type, and, therefore, the size in bytes of the type it points to is added to the pointer.

This is applicable both when adding and subtracting any number to a pointer. It would happen exactly the same if we wrote:

mychar = mychar + 1;
myshort = myshort + 1;
mylong = mylong + 1;

Regarding the increment (++) and decrement (--) operators, they both can be used as either prefix or suffix of an expression, with a slight difference in behavior: as a prefix, the increment happens before the expression is evaluated, and as a suffix, the increment happens after the expression is evaluated. This also applies to expressions incrementing and decrementing pointers, which can become part of more complicated expressions that also include dereference operators (*). Remembering operator precedence rules, we can recall that postfix operators, such as increment and decrement, have higher precedence than prefix operators, such as the dereference operator (*). Therefore, the following expression:

*p++

is equivalent to *(p++). And what it does is to increase the value of p (so it now points to the next element), but because ++ is used as postfix, the whole expression is evaluated as the value pointed originally by the pointer (the address it pointed to before being incremented).

Essentially, these are the four possible combinations of the dereference operator with both the prefix and suffix versions of the increment operator (the same being applicable also to the decrement operator):

A typical -but not so simple- statement involving these operators is:

*p++ = *q++;

Because ++ has a higher precedence than *, both p and q are incremented, but because both increment operators (++) are used as postfix and not prefix, the value assigned to *p is *q before both p and q are incremented. And then both are incremented. It would be roughly equivalent to:

*p = *q;
++p;
++q;

Like always, parentheses reduce confusion by adding legibility to expressions.

Pointers and const


Pointers can be used to access a variable by its address, and this access may include modifying the value pointed. But it is also possible to declare pointers that can access the pointed value to read it, but not to modify it. For this, it is enough with qualifying the type pointed to by the pointer as const. For example:

Here p points to a variable, but points to it in a const-qualified manner, meaning that it can read the value pointed, but it cannot modify it. Note also, that the expression &y is of type int*, but this is assigned to a pointer of type const int*. This is allowed: a pointer to non-const can be implicitly converted to a pointer to const. But not the other way around! As a safety feature, pointers to const are not implicitly convertible to pointers to non-const.

One of the use cases of pointers to const elements is as function parameters: a function that takes a pointer to non-const as parameter can modify the value passed as argument, while a function that takes a pointer to const as parameter cannot.

11
21
31

Note that print_all uses pointers that point to constant elements. These pointers point to constant content they cannot modify, but they are not constant themselves: i.e., the pointers can still be incremented or assigned different addresses, although they cannot modify the content they point to.

And this is where a second dimension to constness is added to pointers: Pointers can also be themselves const. And this is specified by appending const to the pointed type (after the asterisk):

The syntax with const and pointers is definitely tricky, and recognizing the cases that best suit each use tends to require some experience. In any case, it is important to get constness with pointers (and references) right sooner rather than later, but you should not worry too much about grasping everything if this is the first time you are exposed to the mix of const and pointers. More use cases will show up in coming chapters.

To add a little bit more confusion to the syntax of const with pointers, the const qualifier can either precede or follow the pointed type, with the exact same meaning:

As with the spaces surrounding the asterisk, the order of const in this case is simply a matter of style. This chapter uses a prefix const, as for historical reasons this seems to be more extended, but both are exactly equivalent. The merits of each style are still intensely debated on the internet.

Pointers and string literals


As pointed earlier, string literals are arrays containing null-terminated character sequences. In earlier sections, string literals have been used to be directly inserted into cout, to initialize strings and to initialize arrays of characters.

But they can also be accessed directly. String literals are arrays of the proper array type to contain all its characters plus the terminating null-character, with each of the elements being of type const char (as literals, they can never be modified). For example:

const char * foo = "hello";

This declares an array with the literal representation for "hello", and then a pointer to its first element is assigned to foo. If we imagine that "hello" is stored at the memory locations that start at address 1702, we can represent the previous declaration as:

Note that here foo is a pointer and contains the value 1702, and not 'h', nor "hello", although 1702 indeed is the address of both of these.

The pointer foo points to a sequence of characters. And because pointers and arrays behave essentially in the same way in expressions, foo can be used to access the characters in the same way arrays of null-terminated character sequences are. For example:

*(foo+4)
foo[4]

Both expressions have a value of 'o' (the fifth element of the array).

Pointers to pointers


C++ allows the use of pointers that point to pointers, that these, in its turn, point to data (or even to other pointers). The syntax simply requires an asterisk (*) for each level of indirection in the declaration of the pointer:

This, assuming the randomly chosen memory locations for each variable of 7230, 8092, and 10502, could be represented as:


With the value of each variable represented inside its corresponding cell, and their respective addresses in memory represented by the value under them.

The new thing in this example is variable c, which is a pointer to a pointer, and can be used in three different levels of indirection, each one of them would correspond to a different value:

  • c is of type char** and a value of 8092
  • *c is of type char* and a value of 7230
  • **c is of type char and a value of 'z'

void pointers


The void type of pointer is a special type of pointer. In C++, void represents the absence of type. Therefore, void pointers are pointers that point to a value that has no type (and thus also an undetermined length and undetermined dereferencing properties).

This gives void pointers a great flexibility, by being able to point to any data type, from an integer value or a float to a string of characters. In exchange, they have a great limitation: the data pointed to by them cannot be directly dereferenced (which is logical, since we have no type to dereference to), and for that reason, any address in a void pointer needs to be transformed into some other pointer type that points to a concrete data type before being dereferenced.

One of its possible uses may be to pass generic parameters to a function. For example:

y, 1603

sizeof is an operator integrated in the C++ language that returns the size in bytes of its argument. For non-dynamic data types, this value is a constant. Therefore, for example, sizeof(char) is 1, because char has always a size of one byte.

Invalid pointers and null pointers


In principle, pointers are meant to point to valid addresses, such as the address of a variable or the address of an element in an array. But pointers can actually point to any address, including addresses that do not refer to any valid element. Typical examples of this are uninitialized pointers and pointers to nonexistent elements of an array:

Neither p nor q point to addresses known to contain a value, but none of the above statements causes an error. In C++, pointers are allowed to take any address value, no matter whether there actually is something at that address or not. What can cause an error is to dereference such a pointer (i.e., actually accessing the value they point to). Accessing such a pointer causes undefined behavior, ranging from an error during runtime to accessing some random value.

But, sometimes, a pointer really needs to explicitly point to nowhere, and not just an invalid address. For such cases, there exists a special value that any pointer type can take: the null pointer value. This value can be expressed in C++ in two ways: either with an integer value of zero, or with the nullptr keyword:

int * p = 0;
int * q = nullptr;

Here, both p and q are null pointers, meaning that they explicitly point to nowhere, and they both actually compare equal: all null pointers compare equal to other null pointers. It is also quite usual to see the defined constant NULL be used in older code to refer to the null pointer value:

int * r = NULL;

NULL is defined in several headers of the standard library, and is defined as an alias of some null pointer constant value (such as 0 or nullptr).

Do not confuse null pointers with void pointers! A null pointer is a value that any pointer can take to represent that it is pointing to "nowhere", while a void pointer is a type of pointer that can point to somewhere without a specific type. One refers to the value stored in the pointer, and the other to the type of data it points to.

Pointers to functions


C++ allows operations with pointers to functions. The typical use of this is for passing a function as an argument to another function. Pointers to functions are declared with the same syntax as a regular function declaration, except that the name of the function is enclosed between parentheses () and an asterisk (*) is inserted before the name:

8

In the example above, minus is a pointer to a function that has two parameters of type int. It is directly initialized to point to the function subtraction:

int (* minus)(int,int) = subtraction;

13 - C++ DYNAMIC MEMORY

In the programs seen in previous chapters, all memory needs were determined before program execution by defining the variables needed. But there may be cases where the memory needs of a program can only be determined during runtime. For example, when the memory needed depends on user input. On these cases, programs need to dynamically allocate memory, for which the C++ language integrates the operators new and delete.

Operators new and new[]


Dynamic memory is allocated using operator new. new is followed by a data type specifier and, if a sequence of more than one element is required, the number of these within brackets []. It returns a pointer to the beginning of the new block of memory allocated. Its syntax is: pointer = new type
pointer = new type [number_of_elements]
The first expression is used to allocate memory to contain one single element of type type. The second one is used to allocate a block (an array) of elements of type type, where number_of_elements is an integer value representing the amount of these. For example:

int * foo;
foo = new int [5];

In this case, the system dynamically allocates space for five elements of type int and returns a pointer to the first element of the sequence, which is assigned to foo (a pointer). Therefore, foo now points to a valid block of memory with space for five elements of type int.

Here, foo is a pointer, and thus, the first element pointed to by foo can be accessed either with the expression foo[0] or the expression *foo (both are equivalent). The second element can be accessed either with foo[1] or *(foo+1), and so on... There is a substantial difference between declaring a normal array and allocating dynamic memory for a block of memory using new. The most important difference is that the size of a regular array needs to be a constant expression, and thus its size has to be determined at the moment of designing the program, before it is run, whereas the dynamic memory allocation performed by new allows to assign memory during runtime using any variable value as size.

The dynamic memory requested by our program is allocated by the system from the memory heap. However, computer memory is a limited resource, and it can be exhausted. Therefore, there are no guarantees that all requests to allocate memory using operator new are going to be granted by the system.

C++ provides two standard mechanisms to check if the allocation was successful:

One is by handling exceptions. Using this method, an exception of type bad_alloc is thrown when the allocation fails. Exceptions are a powerful C++ feature explained later in these tutorials. But for now, you should know that if this exception is thrown and it is not handled by a specific handler, the program execution is terminated.

This exception method is the method used by default by new, and is the one used in a declaration like:

foo = new int [5]; // if allocation fails, an exception is thrown

The other method is known as nothrow, and what happens when it is used is that when a memory allocation fails, instead of throwing a bad_alloc exception or terminating the program, the pointer returned by new is a null pointer, and the program continues its execution normally.

This method can be specified by using a special object called nothrow, declared in header <new>, as argument for new:

foo = new (nothrow) int [5];

In this case, if the allocation of this block of memory fails, the failure can be detected by checking if foo is a null pointer:

This nothrow method is likely to produce less efficient code than exceptions, since it implies explicitly checking the pointer value returned after each and every allocation. Therefore, the exception mechanism is generally preferred, at least for critical allocations. Still, most of the coming examples will use the nothrow mechanism due to its simplicity.

Operators delete and delete[]


In most cases, memory allocated dynamically is only needed during specific periods of time within a program; once it is no longer needed, it can be freed so that the memory becomes available again for other requests of dynamic memory. This is the purpose of operator delete, whose syntax is:

delete pointer;
delete[] pointer;

he first statement releases the memory of a single element allocated using new, and the second one releases the memory allocated for arrays of elements using new and a size in brackets ([]).

The value passed as argument to delete shall be either a pointer to a memory block previously allocated with new, or a null pointer (in the case of a null pointer, delete produces no effect).

How many numbers would you like to type? 5
Enter number : 75
Enter number : 436
Enter number : 1067
Enter number : 8
Enter number : 32
You have entered: 75, 436, 1067, 8, 32,

Notice how the value within brackets in the new statement is a variable value entered by the user (i), not a constant expression:

p= new (nothrow) int[i];

There always exists the possibility that the user introduces a value for i so big that the system cannot allocate enough memory for it. For example, when I tried to give a value of 1 billion to the "How many numbers" question, my system could not allocate that much memory for the program, and I got the text message we prepared for this case (Error: memory could not be allocated).

It is considered good practice for programs to always be able to handle failures to allocate memory, either by checking the pointer value (if nothrow) or by catching the proper exception.

14 - C++ DATA STRUCTURES

Data structures


A data structure is a group of data elements grouped together under one name. These data elements, known as members, can have different types and different lengths. Data structures can be declared in C++ using the following syntax:

struct type_name { member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;

Where type_name is a name for the structure type, object_name can be a set of valid identifiers for objects that have the type of this structure. Within braces {}, there is a list with the data members, each one is specified with a type and a valid identifier as its name.

For example:

This declares a structure type, called product, and defines it having two members: weight and price, each of a different fundamental type. This declaration creates a new type (product), which is then used to declare three objects (variables) of this type: apple, banana, and melon. Note how once product is declared, it is used just like any other type.

Right at the end of the struct definition, and before the ending semicolon (;), the optional field object_names can be used to directly declare objects of the structure type. For example, the structure objects apple, banana, and melon can be declared at the moment the data structure type is defined:

In this case, where object_names are specified, the type name (product) becomes optional: struct requires either a type_name or at least one name in object_names, but not necessarily both.

It is important to clearly differentiate between what is the structure type name (product), and what is an object of this type (apple, banana, and melon). Many objects (such as apple, banana, and melon) can be declared from a single structure type (product).

Once the three objects of a determined structure type are declared (apple, banana, and melon) its members can be accessed directly. The syntax for that is simply to insert a dot (.) between the object name and the member name. For example, we could operate with any of these elements as if they were standard variables of their respective types:

Each one of these has the data type corresponding to the member they refer to: apple.weight, banana.weight, and melon.weight are of type int, while apple.price, banana.price, and melon.price are of type double.

Here is a real example with structure types in action:

Enter title: Alien
Enter year: 1979

My favorite movie is:
2001 A Space Odyssey (1968)
And yours is:
Alien (1979)

The example shows how the members of an object act just as regular variables. For example, the member yours.year is a valid variable of type int, and mine.title is a valid variable of type string.

But the objects mine and yours are also variables with a type (of type movies_t). For example, both have been passed to function printmovie just as if they were simple variables. Therefore, one of the features of data structures is the ability to refer to both their members individually or to the entire structure as a whole. In both cases using the same identifier: the name of the structure.

Because structures are types, they can also be used as the type of arrays to construct tables or databases of them:

Enter title: Blade Runner
Enter year: 1982
Enter title: The Matrix
Enter year: 1999
Enter title: Taxi Driver
Enter year: 1976

You have entered these movies:
Blade Runner (1982)
The Matrix (1999)
Taxi Driver (1976)

Pointers to structures


Like any other type, structures can be pointed to by its own type of pointers:

Here amovie is an object of structure type movies_t, and pmovie is a pointer to point to objects of structure type movies_t. Therefore, the following code would also be valid:

pmovie = &amovie;

The value of the pointer pmovie would be assigned the address of object amovie.

Now, let's see another example that mixes pointers and structures, and will serve to introduce a new operator: the arrow operator (->):

Enter title: Invasion of the body snatchers
Enter year: 1978

You have entered:
Invasion of the body snatchers (1978)

The arrow operator (->) is a dereference operator that is used exclusively with pointers to objects that have members. This operator serves to access the member of an object directly from its address. For example, in the example above:

pmovie->title

is, for all purposes, equivalent to:

(*pmovie).title

Both expressions, pmovie->title and (*pmovie).title are valid, and both access the member title of the data structure pointed by a pointer called pmovie. It is definitely something different than:

*pmovie.title

which is rather equivalent to:

*(pmovie.title)

This would access the value pointed by a hypothetical pointer member called title of the structure object pmovie (which is not the case, since title is not a pointer type). The following panel summarizes possible combinations of the operators for pointers and for structure members:

ExpressionWhat is evaluatedEquivalent
a.bMember b of object a
a->bMember b of object pointed to by a(*a).b
*a.bValue pointed to by member b of object a*(a.b)

Nesting structures


Structures can also be nested in such a way that an element of a structure is itself another structure:

After the previous declarations, all of the following expressions would be valid:

(where, by the way, the last two expressions refer to the same member).

15 - C++ CLASSES (1)


Classes are an expanded concept of data structures: like data structures, they can contain data members, but they can also contain functions as members.

An object is an instantiation of a class. In terms of variables, a class would be the type, and an object would be the variable.

Classes are defined using either keyword class or keyword struct, with the following syntax:

Where class_name is a valid identifier for the class, object_names is an optional list of names for objects of this class. The body of the declaration can contain members, which can either be data or function declarations, and optionally access specifiers.

Classes have the same format as plain data structures, except that they can also include functions and have these new things called access specifiers. An access specifier is one of the following three keywords: private, public or protected. These specifiers modify the access rights for the members that follow them:

  • private members of a class are accessible only from within other members of the same class (or from their "friends").
  • protected members are accessible from other members of the same class (or from their "friends"), but also from members of their derived classes.
  • Finally, public members are accessible from anywhere where the object is visible.

By default, all members of a class declared with the class keyword have private access for all its members. Therefore, any member that is declared before any other access specifier has private access automatically. For example:

Declares a class (i.e., a type) called Rectangle and an object (i.e., a variable) of this class, called rect. This class contains four members: two data members of type int (member width and member height) with private access (because private is the default access level) and two member functions with public access: the functions set_values and area, of which for now we have only included their declaration, but not their definition.

Notice the difference between the class name and the object name: In the previous example, Rectangle was the class name (i.e., the type), whereas rect was an object of type Rectangle. It is the same relationship int and a have in the following declaration:

int a;

where int is the type name (the class) and a is the variable name (the object).

After the declarations of Rectangle and rect, any of the public members of object rect can be accessed as if they were normal functions or normal variables, by simply inserting a dot (.) between object name and member name. This follows the same syntax as accessing the members of plain data structures. For example:

rect.set_values (3,4);
myarea = rect.area();

The only members of rect that cannot be accessed from outside the class are width and height, since they have private access and they can only be referred to from within other members of that same class.

Here is the complete example of class Rectangle:

area: 12

This example reintroduces the scope operator (::, two colons), seen in earlier chapters in relation to namespaces. Here it is used in the definition of function set_values to define a member of a class outside the class itself.

Notice that the definition of the member function area has been included directly within the definition of class Rectangle given its extreme simplicity. Conversely, set_values it is merely declared with its prototype within the class, but its definition is outside it. In this outside definition, the operator of scope (::) is used to specify that the function being defined is a member of the class Rectangle and not a regular non-member function.

The scope operator (::) specifies the class to which the member being declared belongs, granting exactly the same scope properties as if this function definition was directly included within the class definition. For example, the function set_values in the previous example has access to the variables width and height, which are private members of class Rectangle, and thus only accessible from other members of the class, such as this.

The only difference between defining a member function completely within the class definition or to just include its declaration in the function and define it later outside the class, is that in the first case the function is automatically considered an inline member function by the compiler, while in the second it is a normal (not-inline) class member function. This causes no differences in behavior, but only on possible compiler optimizations.

Members width and height have private access (remember that if nothing else is specified, all members of a class defined with keyword class have private access). By declaring them private, access from outside the class is not allowed. This makes sense, since we have already defined a member function to set values for those members within the object: the member function set_values. Therefore, the rest of the program does not need to have direct access to them. Perhaps in a so simple example as this, it is difficult to see how restricting access to these variables may be useful, but in greater projects it may be very important that values cannot be modified in an unexpected way (unexpected from the point of view of the object).

The most important property of a class is that it is a type, and as such, we can declare multiple objects of it. For example, following with the previous example of class Rectangle, we could have declared the object rectb in addition to object rect:

n this particular case, the class (type of the objects) is Rectangle, of which there are two instances (i.e., objects): rect and rectb. Each one of them has its own member variables and member functions.

Notice that the call to rect.area() does not give the same result as the call to rectb.area(). This is because each object of class Rectangle has its own variables width and height, as they -in some way- have also their own function members set_value and area that operate on the object's own member variables.

Classes allow programming using object-oriented paradigms: Data and functions are both members of the object, reducing the need to pass and carry handlers or other state variables as arguments to functions, because they are part of the object whose member is called. Notice that no arguments were passed on the calls to rect.area or rectb.area. Those member functions directly used the data members of their respective objects rect and rectb.

Constructors


What would happen in the previous example if we called the member function area before having called set_values? An undetermined result, since the members width and height had never been assigned a value.

In order to avoid that, a class can include a special function called its constructor, which is automatically called whenever a new object of this class is created, allowing the class to initialize member variables or allocate storage.

This constructor function is declared just like a regular member function, but with a name that matches the class name and without any return type; not even void.

The Rectangle class above can easily be improved by implementing a constructor:

rect area: 12
rectb area: 30

The results of this example are identical to those of the previous example. But now, class Rectangle has no member function set_values, and has instead a constructor that performs a similar action: it initializes the values of width and height with the arguments passed to it.

Notice how these arguments are passed to the constructor at the moment at which the objects of this class are created:

Rectangle rect (3,4);
Rectangle rectb (5,6);

Constructors cannot be called explicitly as if they were regular member functions. They are only executed once, when a new object of that class is created.

Notice how neither the constructor prototype declaration (within the class) nor the latter constructor definition, have return values; not even void: Constructors never return values, they simply initialize the object.

Overloading constructors


Like any other function, a constructor can also be overloaded with different versions taking different parameters: with a different number of parameters and/or parameters of different types. The compiler will automatically call the one whose parameters match the arguments:

In the above example, two objects of class Rectangle are constructed: rect and rectb. rect is constructed with two arguments, like in the example before. But this example also introduces a special kind constructor: the default constructor. The default constructor is the constructor that takes no parameters, and it is special because it is called when an object is declared but is not initialized with any arguments. In the example above, the default constructor is called for rectb. Note how rectb is not even constructed with an empty set of parentheses - in fact, empty parentheses cannot be used to call the default constructor:

This is because the empty set of parentheses would make of rectc a function declaration instead of an object declaration: It would be a function that takes no arguments and returns a value of type Rectangle.

Uniform initialization


The way of calling constructors by enclosing their arguments in parentheses, as shown above, is known as functional form. But constructors can also be called with other syntaxes: First, constructors with a single parameter can be called using the variable initialization syntax (an equal sign followed by the argument):

class_name object_name = initialization_value;

More recently, C++ introduced the possibility of constructors to be called using uniform initialization, which essentially is the same as the functional form, but using braces ({}) instead of parentheses (()):

class_name object_name { value, value, value, ... }
Optionally, this last syntax can include an equal sign before the braces.

Here is an example with four ways to construct objects of a class whose constructor takes a single parameter:

foo's circumference: 62.8319

An advantage of uniform initialization over functional form is that, unlike parentheses, braces cannot be confused with function declarations, and thus can be used to explicitly call default constructors:

The choice of syntax to call constructors is largely a matter of style. Most existing code currently uses functional form, and some newer style guides suggest to choose uniform initialization over the others, even though it also has its potential pitfalls for its preference of initializer_list as its type.

Member initialization in constructors


When a constructor is used to initialize other members, these other members can be initialized directly, without resorting to statements in its body. This is done by inserting, before the constructor's body, a colon (:) and a list of initializations for class members. For example, consider a class with the following declaration:

The constructor for this class could be defined, as usual, as:

Rectangle::Rectangle (int x, int y) { width=x; height=y; }

But it could also be defined using member initialization as:

Rectangle::Rectangle (int x, int y) : width(x) { height=y; }

Or even:

Rectangle::Rectangle (int x, int y) : width(x), height(y) { }

Note how in this last case, the constructor does nothing else than initialize its members, hence it has an empty function body.

For members of fundamental types, it makes no difference which of the ways above the constructor is defined, because they are not initialized by default, but for member objects (those whose type is a class), if they are not initialized after the colon, they are default-constructed.

Default-constructing all members of a class may or may always not be convenient: in some cases, this is a waste (when the member is then reinitialized otherwise in the constructor), but in some other cases, default-construction is not even possible (when the class does not have a default constructor). In these cases, members shall be initialized in the member initialization list. For example:

In this example, class Cylinder has a member object whose type is another class (base's type is Circle). Because objects of class Circle can only be constructed with a parameter, Cylinder's constructor needs to call base's constructor, and the only way to do this is in the member initializer list.

These initializations can also use uniform initializer syntax, using braces {} instead of parentheses ():

Pointers to classes


Objects can also be pointed to by pointers: Once declared, a class becomes a valid type, so it can be used as the type pointed to by a pointer. For example:

Rectangle * prect;

is a pointer to an object of class Rectangle. Similarly as with plain data structures, the members of an object can be accessed directly from a pointer by using the arrow operator (->). Here is an example with some possible combinations:

This example makes use of several operators to operate on objects and pointers (operators *, &, ., ->, []). They can be interpreted as:

expressioncan be read as
*xpointed to by x
&xaddress of x
x.ymember y of object x
x->ymember y of object pointed to by x
(*x).ymember y of object pointed to by x (equivalent to the previous one)
x[0]first object pointed to by x
x[1]second object pointed to by x
x[n](n+1)th object pointed to by x

Most of these expressions have been introduced in earlier chapters. Most notably, the chapter about arrays introduced the offset operator ([]) and the chapter about plain data structures introduced the arrow operator (->).

Classes defined with struct and union


Classes can be defined not only with keyword class, but also with keywords struct and union.

The keyword struct, generally used to declare plain data structures, can also be used to declare classes that have member functions, with the same syntax as with keyword class. The only difference between both is that members of classes declared with the keyword struct have public access by default, while members of classes declared with the keyword class have private access by default. For all other purposes both keywords are equivalent in this context.

Conversely, the concept of unions is different from that of classes declared with struct and class, since unions only store one data member at a time, but nevertheless they are also classes and can thus also hold member functions. The default access in union classes is public.

16 - C++ CLASSES (2)

Overloading operators


Classes, essentially, define new types to be used in C++ code. And types in C++ not only interact with code by means of constructions and assignments. They also interact by means of operators. For example, take the following operation on fundamental types:

int a, b, c;
a = b + c;

Here, different variables of a fundamental type (int) are applied the addition operator, and then the assignment operator. For a fundamental arithmetic type, the meaning of such operations is generally obvious and unambiguous, but it may not be so for certain class types. For example:

struct myclass {
string product;
float price;
} a, b, c;
a = b + c;

Here, it is not obvious what the result of the addition operation on b and c does. In fact, this code alone would cause a compilation error, since the type myclass has no defined behavior for additions. However, C++ allows most operators to be overloaded so that their behavior can be defined for just about any type, including classes. Here is a list of all the operators that can be overloaded:

Overloadable operators
+    -    *    /    =    <    >    +=   -=   *=   /=   <<   >>
<<=  >>=  ==   !=   <=   >=   ++   --   %    &    ^    !    |
~    &=   ^=   |=   &&   ||   %=   []   ()   ,    ->*  ->   new 
delete    new[]     delete[]

Operators are overloaded by means of operator functions, which are regular functions with special names: their name begins by the operator keyword followed by the operator sign that is overloaded. The syntax is:

type operator sign (parameters) { /*... body ...*/ } For example, cartesian vectors are sets of two coordinates: x and y. The addition operation of two cartesian vectors is defined as the addition both x coordinates together, and both y coordinates together. For example, adding the cartesian vectors (3,1) and (1,2) together would result in (3+1,1+2) = (4,3). This could be implemented in C++ with the following code:

4,3

If confused about so many appearances of CVector, consider that some of them refer to the class name (i.e., the type) CVector and some others are functions with that name (i.e., constructors, which must have the same name as the class). For example:

The function operator+ of class CVector overloads the addition operator (+) for that type. Once declared, this function can be called either implicitly using the operator, or explicitly using its functional name:

Both expressions are equivalent.

The operator overloads are just regular functions which can have any behavior; there is actually no requirement that the operation performed by that overload bears a relation to the mathematical or usual meaning of the operator, although it is strongly recommended. For example, a class that overloads operator+ to actually subtract or that overloads operator== to fill the object with zeros, is perfectly valid, although using such a class could be challenging.

The parameter expected for a member function overload for operations such as operator+ is naturally the operand to the right hand side of the operator. This is common to all binary operators (those with an operand to its left and one operand to its right). But operators can come in diverse forms. Here you have a table with a summary of the parameters needed for each of the different operators than can be overloaded (please, replace @ by the operator in each case):

ExpressionOperatorMember functionNon-member function
@a+ - * & ! ~ ++ --A::operator@()operator@(A)
a@++ --A::operator@(int)operator@(A,int)
a@b+ - * / % ^ & | < > == != <= >= << >> && || ,A::operator@(B)operator@(A,B)
a@b= += -= *= /= %= ^= &= |= <<= >>= []A::operator@(B)-
a(b,c...)()A::operator()(B,C...)-
a->b->A::operator->()-
(TYPE) aTYPEA::operator TYPE()-

Where a is an object of class A, b is an object of class B and c is an object of class C. TYPE is just any type (that operators overloads the conversion to type TYPE).

Notice that some operators may be overloaded in two forms: either as a member function or as a non-member function: The first case has been used in the example above for operator+. But some operators can also be overloaded as non-member functions; In this case, the operator function takes an object of the proper class as first argument. For example:

4,3

The keyword this


The keyword this represents a pointer to the object whose member function is being executed. It is used within a class's member function to refer to the object itself. One of its uses can be to check if a parameter passed to a member function is the object itself. For example:

yes, &a is b

It is also frequently used in operator= member functions that return objects by reference. Following with the examples on cartesian vector seen before, its operator= function could have been defined as:

In fact, this function is very similar to the code that the compiler generates implicitly for this class for operator=.

Static members


A class can contain static members, either data or functions.

A static data member of a class is also known as a "class variable", because there is only one common variable for all the objects of that same class, sharing the same value: i.e., its value is not different from one object of this class to another.

For example, it may be used for a variable within a class that can contain a counter with the number of objects of that class that are currently allocated, as in the following example:

6
7

In fact, static members have the same properties as non-member variables but they enjoy class scope. For that reason, and to avoid them to be declared several times, they cannot be initialized directly in the class, but need to be initialized somewhere outside it. As in the previous example:

int Dummy::n=0;

Because it is a common variable value for all the objects of the same class, it can be referred to as a member of any object of that class or even directly by the class name (of course this is only valid for static members):

cout << a.n;
cout << Dummy::n;

These two calls above are referring to the same variable: the static variable n within class Dummy shared by all objects of this class.

Again, it is just like a non-member variable, but with a name that requires to be accessed like a member of a class (or an object).

Classes can also have static member functions. These represent the same: members of a class that are common to all object of that class, acting exactly as non-member functions but being accessed like members of the class. Because they are like non-member functions, they cannot access non-static members of the class (neither member variables nor member functions). They neither can use the keyword this.

Const member functions


When an object of a class is qualified as a const object:

const MyClass myobject;

The access to its data members from outside the class is restricted to read-only, as if all its data members were const for those accessing them from outside the class. Note though, that the constructor is still called and is allowed to initialize and modify these data members:

10

The member functions of a const object can only be called if they are themselves specified as const members; in the example above, member get (which is not specified as const) cannot be called from foo. To specify that a member is a const member, the const keyword shall follow the function prototype, after the closing parenthesis for its parameters:

int get() const {return x;}

Note that const can be used to qualify the type returned by a member function. This const is not the same as the one which specifies a member as const. Both are independent and are located at different places in the function prototype:

int get() const {return x;} // const member function const int< get() {return x;} // member function returning a const< const int< get() const {return x;} // const member function returning a const<

Member functions specified to be const cannot modify non-static data members nor call other non-const member functions. In essence, const members shall not modify the state of an object.

const objects are limited to access only member functions marked as const, but non-const objects are not restricted and thus can access both const and non-const member functions alike.

You may think that anyway you are seldom going to declare const objects, and thus marking all members that don't modify the object as const is not worth the effort, but const objects are actually very common. Most functions taking classes as parameters actually take them by const reference, and thus, these functions can only access their const members:

10

If in this example, get was not specified as a const member, the call to arg.get() in the print function would not be possible, because const objects only have access to const member functions.

Member functions can be overloaded on their constness: i.e., a class may have two member functions with identical signatures except that one is const and the other is not: in this case, the const version is called only when the object is itself const, and the non-const version is called when the object is itself non-const.

15
20

Class templates


Just like we can create function templates, we can also create class templates, allowing classes to have members that use template parameters as types. For example:

template <class T> class mypair { T values [2]; public: mypair (T first, T second) { values[0]=first; values[1]=second; } };

The class that we have just defined serves to store two elements of any valid type. For example, if we wanted to declare an object of this class to store two integer values of type int with the values 115 and 36 we would write:

mypair<int> myobject (115, 36);

This same class could also be used to create an object to store any other type, such as:

mypair<double> myfloats (3.0, 2.18);

The constructor is the only member function in the previous class template and it has been defined inline within the class definition itself. In case that a member function is defined outside the defintion of the class template, it shall be preceded with the template <...> prefix:

100

Notice the syntax of the definition of member function getmax:

template <class T>
T mypair<T>::getmax ()

Confused by so many T's? There are three T's in this declaration: The first one is the template parameter. The second T refers to the type returned by the function. And the third T (the one between angle brackets) is also a requirement: It specifies that this function's template parameter is also the class template parameter.

Template specialization


It is possible to define a different implementation for a template when a specific type is passed as template argument. This is called a template specialization. For example, let's suppose that we have a very simple class called mycontainer that can store one element of any type and that has just one member function called increase, which increases its value. But we find that when it stores an element of type char it would be more convenient to have a completely different implementation with a function member uppercase, so we decide to declare a class template specialization for that type:

// template specialization #include <iostream> using namespace std; // class template: template <class T> class mycontainer { T element; public: mycontainer (T arg) {element=arg;} T increase () {return ++element;} }; // class template specialization: template <> class mycontainer <char> { char element; public: mycontainer (char arg) {element=arg;} char uppercase () { if ((element>='a')&&(element<='z')) element+='A'-'a'; return element; } }; int main () { mycontainer<int> myint (7); mycontainer<char> mychar ('j'); cout << myint.increase() << endl; cout << mychar.uppercase() << endl; return 0; }

8
J

This is the syntax used for the class template specialization:

template <> class mycontainer <char> { ... };

First of all, notice that we precede the class name with template<> , including an empty parameter list. This is because all types are known and no template arguments are required for this specialization, but still, it is the specialization of a class template, and thus it requires to be noted as such.

But more important than this prefix, is the <char> specialization parameter after the class template name. This specialization parameter itself identifies the type for which the template class is being specialized (char). Notice the differences between the generic class template and the specialization:

template <class T> class mycontainer { ... };
template <> class mycontainer <char> { ... };

The first line is the generic template, and the second one is the specialization.

When we declare specializations for a template class, we must also define all its members, even those identical to the generic template class, because there is no "inheritance" of members from the generic template to the specialization.

17 - C++ SPECIAL MEMBERS

[NOTE: This chapter requires proper understanding of dynamically allocated memory]

Special member functions are member functions that are implicitly defined as member of classes under certain circumstances. There are six:
Member functiontypical form for class C:
Default constructorC::C();
DestructorC::~C();
Copy constructorC::C (const C&);
Copy assignmentC& operator= (const C&);
Move constructorC::C (C&&);
Move assignmentC& operator= (C&&);

Let's examine each of these:

Default constructor


The default constructor is the constructor called when objects of a class are declared, but are not initialized with any arguments.

If a class definition has no constructors, the compiler assumes the class to have an implicitly defined default constructor. Therefore, after declaring a class like this:

The compiler assumes that Example has a default constructor. Therefore, objects of this class can be constructed by simply declaring them without any arguments:

But as soon as a class has some constructor taking any number of parameters explicitly declared, the compiler no longer provides an implicit default constructor, and no longer allows the declaration of new objects of that class without arguments. For example, the following class:

Here, we have declared a constructor with a parameter of type int. Therefore the following object declaration would be correct:

But the following:

Would not be valid, since the class has been declared with an explicit constructor taking one argument and that replaces the implicit default constructor taking none.

Therefore, if objects of this class need to be constructed without arguments, the proper default constructor shall also be declared in the class. For example:

bar's content: Example

Here, Example3 has a default constructor (i.e., a constructor without parameters) defined as an empty block:

This allows objects of class Example3 to be constructed without arguments (like foo was declared in this example). Normally, a default constructor like this is implicitly defined for all classes that have no other constructors and thus no explicit definition is required. But in this case, Example3 has another constructor:

Example3 (const string& str);

And when any constructor is explicitly declared in a class, no implicit default constructors is automatically provided.

Destructor


Destructors fulfill the opposite functionality of constructors: They are responsible for the necessary cleanup needed by a class when its lifetime ends. The classes we have defined in previous chapters did not allocate any resource and thus did not really require any clean up.

But now, let's imagine that the class in the last example allocates dynamic memory to store the string it had as data member; in this case, it would be very useful to have a function called automatically at the end of the object's life in charge of releasing this memory. To do this, we use a destructor. A destructor is a member function very similar to a default constructor: it takes no arguments and returns nothing, not even void. It also uses the class name as its own name, but preceded with a tilde sign (~):

bar's content: Example

On construction, Example4 allocates storage for a string. Storage that is later released by the destructor.

The destructor for an object is called at the end of its lifetime; in the case of foo and bar this happens at the end of function main.

Copy constructor


When an object is passed a named object of its own type as argument, its copy constructor is invoked in order to construct a copy.

A copy constructor is a constructor whose first parameter is of type reference to the class itself (possibly const qualified) and which can be invoked with a single argument of this type. For example, for a class MyClass, the copy constructor may have the following signature:

If a class has no custom copy nor move constructors (or assignments) defined, an implicit copy constructor is provided. This copy constructor simply performs a copy of its own members. For example, for a class such as:

An implicit copy constructor is automatically defined. The definition assumed for this function performs a shallow copy, roughly equivalent to:

This default copy constructor may suit the needs of many classes. But shallow copies only copy the members of the class themselves, and this is probably not what we expect for classes like class Example4 we defined above, because it contains pointers of which it handles its storage. For that class, performing a shallow copy means that the pointer value is copied, but not the content itself; This means that both objects (the copy and the original) would be sharing a single string object (they would both be pointing to the same object), and at some point (on destruction) both objects would try to delete the same block of memory, probably causing the program to crash on runtime. This can be solved by defining the following custom copy constructor that performs a deep copy:

bar's content: Example

The deep copy performed by this copy constructor allocates storage for a new string, which is initialized to contain a copy of the original object. In this way, both objects (copy and original) have distinct copies of the content stored in different locations.

Copy assignment


Objects are not only copied on construction, when they are initialized: They can also be copied on any assignment operation. See the difference:

Note that baz is initialized on construction using an equal sign, but this is not an assignment operation! (although it may look like one): The declaration of an object is not an assignment operation, it is just another of the syntaxes to call single-argument constructors.

The assignment on foo is an assignment operation. No object is being declared here, but an operation is being performed on an existing object; foo.

The copy assignment operator is an overload of operator= which takes a value or reference of the class itself as parameter. The return value is generally a reference to *this (although this is not required). For example, for a class MyClass, the copy assignment may have the following signature:

The copy assignment operator is also a special function and is also defined implicitly if a class has no custom copy nor move assignments (nor move constructor) defined.

But again, the implicit version performs a shallow copy which is suitable for many classes, but not for classes with pointers to objects they handle its storage, as is the case in Example5. In this case, not only the class incurs the risk of deleting the pointed object twice, but the assignment creates memory leaks by not deleting the object pointed by the object before the assignment. These issues could be solved with a copy assignment that deletes the previous object and performs a deep copy:

Or even better, since its string member is not constant, it could re-utilize the same string object:

Move constructor and assignment


Similar to copying, moving also uses the value of an object to set the value to another object. But, unlike copying, the content is actually transferred from one object (the source) to the other (the destination): the source loses that content, which is taken over by the destination. This moving only happens when the source of the value is an unnamed object.

Unnamed objects are objects that are temporary in nature, and thus haven't even been given a name. Typical examples of unnamed objects are return values of functions or type-casts.

Using the value of a temporary object such as these to initialize another object or to assign its value, does not really require a copy: the object is never going to be used for anything else, and thus, its value can be moved into the destination object. These cases trigger the move constructor and move assignments:

The move constructor is called when an object is initialized on construction using an unnamed temporary. Likewise, the move assignment is called when an object is assigned the value of an unnamed temporary:

Both the value returned by fn and the value constructed with MyClass are unnamed temporaries. In these cases, there is no need to make a copy, because the unnamed object is very short-lived and can be acquired by the other object when this is a more efficient operation.

The move constructor and move assignment are members that take a parameter of type rvalue reference to the class itself:

An rvalue reference is specified by following the type with two ampersands (&&). As a parameter, an rvalue reference matches arguments of temporaries of this type.

The concept of moving is most useful for objects that manage the storage they use, such as objects that allocate storage with new and delete. In such objects, copying and moving are really different operations:
- Copying from A to B means that new memory is allocated to B and then the entire content of A is copied to this new memory allocated for B.
- Moving from A to B means that the memory already allocated to A is transferred to B without allocating any new storage. It involves simply copying the pointer.

For example:

foo's content: Example

Compilers already optimize many cases that formally require a move-construction call in what is known as Return Value Optimization. Most notably, when the value returned by a function is used to initialize an object. In these cases, the move constructor may actually never get called.

Note that even though rvalue references can be used for the type of any function parameter, it is seldom useful for uses other than the move constructor. Rvalue references are tricky, and unnecessary uses may be the source of errors quite difficult to track.

Implicit members


The six special members functions described above are members implicitly declared on classes under certain circumstances:

Member functionimplicitly defined:default definition:
Default constructorif no other constructorsdoes nothing
Destructorif no destructordoes nothing
Copy constructorif no move constructor and no move assignmentcopies all members
Copy assignmentif no move constructor and no move assignmentcopies all members
Move constructorif no destructor, no copy constructor and no copy nor move assignmentmoves all members
Move assignmentif no destructor, no copy constructor and no copy nor move assignmentmoves all members

Notice how not all special member functions are implicitly defined in the same cases. This is mostly due to backwards compatibility with C structures and earlier C++ versions, and in fact some include deprecated cases. Fortunately, each class can select explicitly which of these members exist with their default definition or which are deleted by using the keywords default and delete, respectively. The syntax is either one of:

For example:

Here, Rectangle can be constructed either with two int arguments or be default-constructed (with no arguments). It cannot however be copy-constructed from another Rectangle object, because this function has been deleted. Therefore, assuming the objects of the last example, the following statement would not be valid:

It could, however, be made explicitly valid by defining its copy constructor as:

Which would be essentially equivalent to:

Note that, the keyword default does not define a member function equal to the default constructor (i.e., where default constructor means constructor with no parameters), but equal to the constructor that would be implicitly defined if not deleted. In general, and for future compatibility, classes that explicitly define one copy/move constructor or one copy/move assignment but not both, are encouraged to specify either delete or default on the other special member functions they don't explicitly define.

18 - C++ FRIENDSHIP AND INHERITANCE

Friend functions


In principle, private and protected members of a class cannot be accessed from outside the same class in which they are declared. However, this rule does not apply to "friends".

Friends are functions or classes declared with the friend keyword.

A non-member function can access the private and protected members of a class if it is declared a friend of that class. That is done by including a declaration of this external function within the class, and preceding it with the keyword friend:

24

The duplicate function is a friend of class Rectangle. Therefore, function duplicate is able to access the members width and height (which are private) of different objects of type Rectangle. Notice though that neither in the declaration of duplicate nor in its later use in main, function duplicate is considered a member of class Rectangle. It isn't! It simply has access to its private and protected members without being a member.

Typical use cases of friend functions are operations that are conducted between two different classes accessing private or protected members of both.

Friend classes


Similar to friend functions, a friend class is a class whose members have access to the private or protected members of another class:

16

In this example, class Rectangle is a friend of class Square allowing Rectangle's member functions to access private and protected members of Square. More concretely, Rectangle accesses the member variable Square::side, which describes the side of the square.

There is something else new in this example: at the beginning of the program, there is an empty declaration of class Square. This is necessary because class Rectangle uses Square (as a parameter in member convert), and Square uses Rectangle (declaring it a friend).

Friendships are never corresponded unless specified: In our example, Rectangle is considered a friend class by Square, but Square is not considered a friend by Rectangle. Therefore, the member functions of Rectangle can access the protected and private members of Square but not the other way around. Of course, Square could also be declared friend of Rectangle, if needed, granting such an access.

Another property of friendships is that they are not transitive: The friend of a friend is not considered a friend unless explicitly specified.

Inheritance between classes


Classes in C++ can be extended, creating new classes which retain characteristics of the base class. This process, known as inheritance, involves a base class and a derived class: The derived class inherits the members of the base class, on top of which it can add its own members.

For example, let's imagine a series of classes to describe two kinds of polygons: rectangles and triangles. These two polygons have certain common properties, such as the values needed to calculate their areas: they both can be described simply with a height and a width (or base).

This could be represented in the world of classes with a class Polygon from which we would derive the two other ones: Rectangle and Triangle:

The Polygon class would contain members that are common for both types of polygon. In our case: width and height. And Rectangle and Triangle would be its derived classes, with specific features that are different from one type of polygon to the other.

Classes that are derived from others inherit all the accessible members of the base class. That means that if a base class includes a member A and we derive a class from it with another member called B, the derived class will contain both member A and member B.

The inheritance relationship of two classes is declared in the derived class. Derived classes definitions use the following syntax:

class derived_class_name: public base_class_name { /*...*/ };

Where derived_class_name is the name of the derived class and base_class_name is the name of the class on which it is based. The public access specifier may be replaced by any one of the other access specifiers (protected or private). This access specifier limits the most accessible level for the members inherited from the base class: The members with a more accessible level are inherited with this level instead, while the members with an equal or more restrictive access level keep their restrictive level in the derived class.

20
10

The objects of the classes Rectangle and Triangle each contain members inherited from Polygon. These are: width, height and set_values.

The protected access specifier used in class Polygon is similar to private. Its only difference occurs in fact with inheritance: When a class inherits another one, the members of the derived class can access the protected members inherited from the base class, but not its private members.

By declaring width and height as protected instead of private, these members are also accessible from the derived classes Rectangle and Triangle, instead of just from members of Polygon. If they were public, they could be accessed just from anywhere.

We can summarize the different access types according to which functions can access them in the following way:

Accesspublicprotectedprivate
members of the same classyesyesyes
members of derived classyesyesno
not membersyesnono

Where "not members" represents any access from outside the class, such as from main, from another class or from a function.

In the example above, the members inherited by Rectangle and Triangle have the same access permissions as they had in their base class Polygon:

This is because the inheritance relation has been declared using the public keyword on each of the derived classes:

This public keyword after the colon (:) denotes the most accessible level the members inherited from the class that follows it (in this case Polygon) will have from the derived class (in this case Rectangle). Since public is the most accessible level, by specifying this keyword the derived class will inherit all the members with the same levels they had in the base class.

With protected, all public members of the base class are inherited as protected in the derived class. Conversely, if the most restricting access level is specified (private), all the base class members are inherited as private.

For example, if daughter were a class derived from mother that we defined as:

This would set protected as the less restrictive access level for the members of Daughter that it inherited from mother. That is, all members that were public in Mother would become protected in Daughter. Of course, this would not restrict Daughter from declaring its own public members. That less restrictive access level is only set for the members inherited from Mother.

If no access level is specified for the inheritance, the compiler assumes private for classes declared with keyword class and public for those declared with struct.

Actually, most use cases of inheritance in C++ should use public inheritance. When other access levels are needed for base classes, they can usually be better represented as member variables instead.

What is inherited from the base class?


In principle, a publicly derived class inherits access to every member of a base class except:

  • its constructors and its destructor
  • its assignment operator members (operator=)
  • its friends
  • its private members

Even though access to the constructors and destructor of the base class is not inherited as such, they are automatically called by the constructors and destructor of the derived class.

Unless otherwise specified, the constructors of a derived class calls the default constructor of its base classes (i.e., the constructor taking no arguments). Calling a different constructor of a base class is possible, using the same syntax used to initialize member variables in the initialization list:

derived_constructor_name (parameters) : base_constructor_name (parameters) {...}

For example:

Notice the difference between which Mother's constructor is called when a new Daughter object is created and which when it is a Son object. The difference is due to the different constructor declarations of Daughter and Son:

Multiple inheritance


A class may inherit from more than one class by simply specifying more base classes, separated by commas, in the list of a class's base classes (i.e., after the colon). For example, if the program had a specific class to print on screen called Output, and we wanted our classes Rectangle and Triangle to also inherit its members in addition to those of Polygon we could write:

Here is the complete example:

20
10

19 - C++ POLYMORPHISM

Before getting any deeper into this chapter, you should have a proper understanding of pointers and class inheritance. If you are not really sure of the meaning of any of the following expressions, you should review the indicated sections:

Statement:Explained in:
int A::b(int c) { }Classes
a->bData structures
class A: public B {};Friendship and inheritance

Pointers to base class


One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.

The example about the rectangle and triangle classes can be rewritten using pointers taking this feature into account:

20
10

Function main declares two pointers to Polygon (named ppoly1 and ppoly2). These are assigned the addresses of rect and trgl, respectively, which are objects of type Rectangle and Triangle. Such assignments are valid, since both Rectangle and Triangle are classes derived from Polygon.

Dereferencing ppoly1 and ppoly2 (with *ppoly1 and *ppoly2) is valid and allows us to access the members of their pointed objects. For example, the following two statements would be equivalent in the previous example:

But because the type of ppoly1 and ppoly2 is pointer to Polygon (and not pointer to Rectangle nor pointer to Triangle), only the members inherited from Polygon can be accessed, and not those of the derived classes Rectangle and Triangle. That is why the program above accesses the area members of both objects using rect and trgl directly, instead of the pointers; the pointers to the base class cannot access the area members.

Member area could have been accessed with the pointers to Polygon if area were a member of Polygon instead of a member of its derived classes, but the problem is that Rectangle and Triangle implement different versions of area, therefore there is not a single common version that could be implemented in the base class.

Virtual members


A virtual member is a member function that can be redefined in a derived class, while preserving its calling properties through references. The syntax for a function to become virtual is to precede its declaration with the virtual keyword:

20
10
0

In this example, all three classes (Polygon, Rectangle and Triangle) have the same members: width, height, and functions set_values and area.

The member function area has been declared as virtual in the base class because it is later redefined in each of the derived classes. Non-virtual members can also be redefined in derived classes, but non-virtual members of derived classes cannot be accessed through a reference of the base class: i.e., if virtual is removed from the declaration of area in the example above, all three calls to area would return zero, because in all cases, the version of the base class would have been called instead.

Therefore, essentially, what the virtual keyword does is to allow a member of a derived class with the same name as one in the base class to be appropriately called from a pointer, and more precisely when the type of the pointer is a pointer to the base class that is pointing to an object of the derived class, as in the above example.

A class that declares or inherits a virtual function is called a polymorphic class.

Note that despite of the virtuality of one of its members, Polygon was a regular class, of which even an object was instantiated (poly), with its own definition of member area that always returns 0.

Abstract base classes


Abstract base classes are something very similar to the Polygon class in the previous example. They are classes that can only be used as base classes, and thus are allowed to have virtual member functions without definition (known as pure virtual functions). The syntax is to replace their definition by =0 (an equal sign and a zero):

An abstract base Polygon class could look like this:

Notice that area has no definition; this has been replaced by =0, which makes it a pure virtual function. Classes that contain at least one pure virtual function are known as abstract base classes.

Abstract base classes cannot be used to instantiate objects. Therefore, this last abstract base class version of Polygon could not be used to declare objects like:

But an abstract base class is not totally useless. It can be used to create pointers to it, and take advantage of all its polymorphic abilities. For example, the following pointer declarations would be valid:

And can actually be dereferenced when pointing to objects of derived (non-abstract) classes. Here is the entire example:

// abstract base class #include <iostream> using namespace std; class Polygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) =0; }; class Rectangle: public Polygon { public: int area (void) { return (width * height); } }; class Triangle: public Polygon { public: int area (void) { return (width * height / 2); } }; int main () { Rectangle rect; Triangle trgl; Polygon * ppoly1 = ▭ Polygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << '\n'; cout << ppoly2->area() << '\n'; return 0; }

20
10

In this example, objects of different but related types are referred to using a unique type of pointer (Polygon*) and the proper member function is called every time, just because they are virtual. This can be really useful in some circumstances. For example, it is even possible for a member of the abstract base class Polygon to use the special pointer this to access the proper virtual members, even though Polygon itself has no implementation for this function:

20
10

Virtual members and abstract classes grant C++ polymorphic characteristics, most useful for object-oriented projects. Of course, the examples above are very simple use cases, but these features can be applied to arrays of objects or dynamically allocated objects.

Here is an example that combines some of the features in the latest chapters, such as dynamic memory, constructor initializers and polymorphism:

20
10

Notice that the ppoly pointers:


are declared being of type "pointer to Polygon", but the objects allocated have been declared having the derived class type directly (Rectangle and Triangle).

20 - C++ TYPE CONVERSIONS

Implicit conversion


Implicit conversions are automatically performed when a value is copied to a compatible type. For example:

Here, the value of a is promoted from short to int without the need of any explicit operator. This is known as a standard conversion. Standard conversions affect fundamental data types, and allow the conversions between numerical types (short to int, int to float, double to int...), to or from bool, and some pointer conversions.

Converting to int from some smaller integer type, or to double from float is known as promotion, and is guaranteed to produce the exact same value in the destination type. Other conversions between arithmetic types may not always be able to represent the same value exactly:

  • If a negative integer value is converted to an unsigned type, the resulting value corresponds to its 2's complement bitwise representation (i.e., -1 becomes the largest value representable by the type, -2 the second largest, ...).
  • The conversions from/to bool consider false equivalent to zero (for numeric types) and to null pointer (for pointer types); true is equivalent to all other values and is converted to the equivalent of 1.
  • If the conversion is from a floating-point type to an integer type, the value is truncated (the decimal part is removed). If the result lies outside the range of representable values by the type, the conversion causes undefined behavior.
  • Otherwise, if the conversion is between numeric types of the same kind (integer-to-integer or floating-to-floating), the conversion is valid, but the value is implementation-specific (and may not be portable).

Some of these conversions may imply a loss of precision, which the compiler can signal with a warning. This warning can be avoided with an explicit conversion.

For non-fundamental types, arrays and functions implicitly convert to pointers, and pointers in general allow the following conversions:

  • Null pointers can be converted to pointers of any type
  • Pointers to any type can be converted to void pointers.
  • Pointer upcast: pointers to a derived class can be converted to a pointer of an accessible and unambiguous base class, without modifying its const or volatile qualification.

Implicit conversions with classes


In the world of classes, implicit conversions can be controlled by means of three member functions:

  • Single-argument constructors: allow implicit conversion from a particular type to initialize an object.
  • Assignment operator: allow implicit conversion from a particular type on assignments.
  • Type-cast operator: allow implicit conversion to a particular type.

For example:

The type-cast operator uses a particular syntax: it uses the operator keyword followed by the destination type and an empty set of parentheses. Notice that the return type is the destination type and thus is not specified before the operator keyword.

Keyword explicit


On a function call, C++ allows one implicit conversion to happen for each argument. This may be somewhat problematic for classes, because it is not always what is intended. For example, if we add the following function to the last example:

This function takes an argument of type B, but it could as well be called with an object of type A as argument:

This may or may not be what was intended. But, in any case, it can be prevented by marking the affected constructor with the explicit keyword:

Additionally, constructors marked with explicit cannot be called with the assignment-like syntax; In the above example, bar could not have been constructed with:

Type-cast member functions (those described in the previous section) can also be specified as explicit. This prevents implicit conversions in the same way as explicit-specified constructors do for the destination type.

Type casting


C++ is a strong-typed language. Many conversions, specially those that imply a different interpretation of the value, require an explicit conversion, known in C++ as type-casting. There exist two main syntaxes for generic type-casting: functional and c-like:

The functionality of these generic forms of type-casting is enough for most needs with fundamental data types. However, these operators can be applied indiscriminately on classes and pointers to classes, which can lead to code that -while being syntactically correct- can cause runtime errors. For example, the following code compiles without errors:

The program declares a pointer to Addition, but then it assigns to it a reference to an object of another unrelated type using explicit type-casting:

Unrestricted explicit type-casting allows to convert any pointer into any other pointer type, independently of the types they point to. The subsequent call to member result will produce either a run-time error or some other unexpected results. In order to control these types of conversions between classes, we have four specific casting operators: dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses. dynamic_cast <new_type> (expression) reinterpret_cast <new_type> (expression) static_cast <new_type> (expression) const_cast <new_type> (expression) The traditional type-casting equivalents to these expressions would be: (new_type) expression new_type (expression) but each one with its own special characteristics:

dynamic_cast


dynamic_cast can only be used with pointers and references to classes (or with void*). Its purpose is to ensure that the result of the type conversion points to a valid complete object of the destination pointer type.

This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base), in the same way as allowed as an implicit conversion.

But dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type. For example:

Null pointer on second type-cast.

Compatibility note: This type of dynamic_cast requires Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This needs to be enabled for runtime type checking using dynamic_cast to work properly with these types.

The code above tries to perform two dynamic casts from pointer objects of type Base* (pba and pbb) to a pointer object of type Derived*, but only the first one is successful. Notice their respective initializations:

Even though both are pointers of type Base*, pba actually points to an object of type Derived, while pbb points to an object of type Base. Therefore, when their respective type-casts are performed using dynamic_cast, pba is pointing to a full object of class Derived, whereas pbb is pointing to an object of class Base, which is an incomplete object of class Derived.

When dynamic_cast cannot cast a pointer because it is not a complete object of the required class -as in the second conversion in the previous example- it returns a null pointer to indicate the failure. If dynamic_cast is used to convert to a reference type and the conversion is not possible, an exception of type bad_cast is thrown instead.

dynamic_cast can also perform the other implicit casts allowed on pointers: casting null pointers between pointers types (even between unrelated classes), and casting any pointer of any type to a void* pointer.

static_cast


static_cast can perform conversions between pointers to related classes, not only upcasts (from pointer-to-derived to pointer-to-base), but also downcasts (from pointer-to-base to pointer-to-derived). No checks are performed during runtime to guarantee that the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, it does not incur the overhead of the type-safety checks of dynamic_cast.

This would be valid code, although b would point to an incomplete object of the class and could lead to runtime errors if dereferenced.

Therefore, static_cast is able to perform with pointers to classes not only the conversions allowed implicitly, but also their opposite conversions.

static_cast is also able to perform all conversions allowed implicitly (not only those with pointers to classes), and is also able to perform the opposite of these. It can:

  • Convert from void* to any pointer type. In this case, it guarantees that if the void* value was obtained by converting from that same pointer type, the resulting pointer value is the same.
  • Convert integers, floating-point values and enum types to enum types.

Additionally, static_cast can also perform the following:

  • Explicitly call a single-argument constructor or a conversion operator.
  • Convert to rvalue references.
  • Convert enum class values into integers or floating-point values.
  • Convert any type to void, evaluating and discarding the value.

reinterpret_cast


reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.

It can also cast pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific. The only guarantee is that a pointer cast to an integer type large enough to fully contain it (such as intptr_t), is guaranteed to be able to be cast back to a valid pointer.

The conversions that can be performed by reinterpret_cast but not by static_cast are low-level operations based on reinterpreting the binary representations of the types, which on most cases results in code which is system-specific, and thus non-portable. For example:

This code compiles, although it does not make much sense, since now b points to an object of a totally unrelated and likely incompatible class. Dereferencing b is unsafe.

const_cast


This type of casting manipulates the constness of the object pointed by a pointer, either to be set or to be removed. For example, in order to pass a const pointer to a function that expects a non-const argument:

sample text

The example above is guaranteed to work because function print does not write to the pointed object. Note though, that removing the constness of a pointed object to actually write to it causes undefined behavior.

typeid


typeid allows to check the type of an expression:

typeid (expression)

This operator returns a reference to a constant object of type type_info that is defined in the standard header <typeinfo>. A value returned by typeid can be compared with another value returned by typeid using operators == and != or can serve to obtain a null-terminated character sequence representing the data type or class name by using its name() member.

a and b are of different types:
a is: int *
b is: int

When typeid is applied to classes, typeid uses the RTTI to keep track of the type of dynamic objects. When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object:

a is: class Base *
b is: class Base *
*a is: class Base
*b is: class Derived

Note: The string returned by member name of type_info depends on the specific implementation of your compiler and library. It is not necessarily a simple string with its typical type name, like in the compiler used to produce this output.

Notice how the type that typeid considers for pointers is the pointer type itself (both a and b are of type class Base *). However, when typeid is applied to objects (like *a and *b) typeid yields their dynamic type (i.e. the type of their most derived complete object).

If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.

21 - C++ EXCEPTIONS

Exceptions provide a way to react to exceptional circumstances (like runtime errors) in programs by transferring control to special functions called handlers.

To catch exceptions, a portion of code is placed under exception inspection. This is done by enclosing that portion of code in a try-block. When an exceptional circumstance arises within that block, an exception is thrown that transfers the control to the exception handler. If no exception is thrown, the code continues normally and all handlers are ignored.

An exception is thrown by using the throw keyword from inside the try block. Exception handlers are declared with the keyword catch, which must be placed immediately after the try block:

An exception occurred. Exception Nr. 20

The code under exception handling is enclosed in a try block. In this example this code simply throws an exception:

A throw expression accepts one parameter (in this case the integer value 20), which is passed as an argument to the exception handler.

The exception handler is declared with the catch keyword immediately after the closing brace of the try block. The syntax for catch is similar to a regular function with one parameter. The type of this parameter is very important, since the type of the argument passed by the throw expression is checked against it, and only in the case they match, the exception is caught by that handler.

Multiple handlers (i.e., catch expressions) can be chained; each one with a different parameter type. Only the handler whose argument type matches the type of the exception specified in the throw statement is executed.

If an ellipsis (...) is used as the parameter of catch, that handler will catch any exception no matter what the type of the exception thrown. This can be used as a default handler that catches all exceptions not caught by other handlers:

In this case, the last handler would catch any exception thrown of a type that is neither int nor char.

After an exception has been handled the program, execution resumes after the try-catch block, not after the throw statement!.

It is also possible to nest try-catch blocks within more external try blocks. In these cases, we have the possibility that an internal catch block forwards the exception to its external level. This is done with the expression throw; with no arguments. For example:

Exception specification


Older code may contain dynamic exception specifications. They are now deprecated in C++, but still supported. A dynamic exception specification follows the declaration of a function, appending a throw specifier to it. For example:

This declares a function called myfunction, which takes one argument of type char and returns a value of type double. If this function throws an exception of some type other than int, the function calls std::unexpected instead of looking for a handler or calling std::terminate.

If this throw specifier is left empty with no type, this means that std::unexpected is called for any exception. Functions with no throw specifier (regular functions) never call std::unexpected, but follow the normal path of looking for their exception handler.

Standard exceptions


The C++ Standard library provides a base class specifically designed to declare objects to be thrown as exceptions. It is called std::exception and is defined in the <exception> header. This class has a virtual member function called what that returns a null-terminated character sequence (of type char *) and that can be overwritten in derived classes to contain some sort of description of the exception.

My exception happened.

We have placed a handler that catches exception objects by reference (notice the ampersand & after the type), therefore this catches also classes derived from exception, like our myex object of type myexception.

All exceptions thrown by components of the C++ Standard library throw exceptions derived from this exception class. These are:

exceptiondescription
bad_allocthrown by new on allocation failure
bad_castthrown by dynamic_cast when it fails in a dynamic cast
bad_exceptionthrown by certain dynamic exception specifiers
bad_typeidthrown by typeid
bad_function_callthrown by empty function objects
bad_weak_ptrthrown by shared_ptr when passed a bad weak_ptr

Also deriving from exception, header <exception> defines two generic exception types that can be inherited by custom exceptions to report errors:

exceptiondescription
logic_errorerror related to the internal logic of the program
runtime_errorerror detected during runtime

A typical example where standard exceptions need to be checked for is on memory allocation:

The exception that may be caught by the exception handler in this example is a bad_alloc. Because bad_alloc is derived from the standard base class exception, it can be caught (capturing by reference, captures all related classes).

22 - C++ PREPROCESSOR DIRECTIVE

Preprocessor directives are lines included in the code of programs preceded by a hash sign (#). These lines are not program statements but directives for the preprocessor. The preprocessor examines the code before actual compilation of code begins and resolves all these directives before any code is actually generated by regular statements.

These preprocessor directives extend only across a single line of code. As soon as a newline character is found, the preprocessor directive is ends. No semicolon (;) is expected at the end of a preprocessor directive. The only way a preprocessor directive can extend through more than one line is by preceding the newline character at the end of the line by a backslash (\).

macro definitions (#define, #undef)


To define preprocessor macros we can use #define. Its syntax is:

#define identifier replacement

When the preprocessor encounters this directive, it replaces any occurrence of identifier in the rest of the code by replacement. This replacement can be an expression, a statement, a block or simply anything. The preprocessor does not understand C++ proper, it simply replaces any occurrence of identifier by replacement.

After the preprocessor has replaced TABLE_SIZE, the code becomes equivalent to:

#define can work also with parameters to define function macros:

This would replace any occurrence of getmax followed by two arguments by the replacement expression, but also replacing each argument by its identifier, exactly as you would expect if it was a function:

5
7

Defined macros are not affected by block structure. A macro lasts until it is undefined with the #undef preprocessor directive:

This would generate the same code as:

Function macro definitions accept two special operators (# and ##) in the replacement sequence:
The operator #, followed by a parameter name, is replaced by a string literal that contains the argument passed (as if enclosed between double quotes):

This would be translated into:

The operator ## concatenates two arguments leaving no blank spaces between them:

This would also be translated into:

Because preprocessor replacements happen before any C++ syntax check, macro definitions can be a tricky feature. But, be careful: code that relies heavily on complicated macros become less readable, since the syntax expected is on many occasions different from the normal expressions programmers expect in C++.

Conditional inclusions (#ifdef, #ifndef, #if, #endif, #else and #elif)


These directives allow to include or discard part of the code of a program if a certain condition is met.

#ifdef allows a section of a program to be compiled only if the macro that is specified as the parameter has been defined, no matter which its value is. For example:

In this case, the line of code int table[TABLE_SIZE]; is only compiled if TABLE_SIZE was previously defined with #define, independently of its value. If it was not defined, that line will not be included in the program compilation.

#ifndef serves for the exact opposite: the code between #ifndef and #endif directives is only compiled if the specified identifier has not been previously defined. For example:

In this case, if when arriving at this piece of code, the TABLE_SIZE macro has not been defined yet, it would be defined to a value of 100. If it already existed it would keep its previous value since the #define directive would not be executed.

The #if, #else and #elif (i.e., "else if") directives serve to specify some condition to be met in order for the portion of code they surround to be compiled. The condition that follows #if or #elif can only evaluate constant expressions, including macro expressions. For example:

Notice how the entire structure of #if, #elif and #else chained directives ends with #endif.

The behavior of #ifdef and #ifndef can also be achieved by using the special operators defined and !defined respectively in any #if or #elif directive:

Line control (#line)


When we compile a program and some error happens during the compiling process, the compiler shows an error message with references to the name of the file where the error happened and a line number, so it is easier to find the code generating the error.

The #line directive allows us to control both things, the line numbers within the code files as well as the file name that we want that appears when an error takes place. Its format is:

#line number "filename"

Where number is the new line number that will be assigned to the next code line. The line numbers of successive lines will be increased one by one from this point on.

"filename" is an optional parameter that allows to redefine the file name that will be shown. For example:

This code will generate an error that will be shown as error in file "assigning variable", line 20.

Error directive (#error)


This directive aborts the compilation process when it is found, generating a compilation error that can be specified as its parameter:

This example aborts the compilation process if the macro name __cplusplus is not defined (this macro name is defined by default in all C++ compilers).

Source file inclusion (#include)


This directive has been used assiduously in other sections of this tutorial. When the preprocessor finds an #include directive it replaces it by the entire content of the specified header or file. There are two ways to use #include:

In the first case, a header is specified between angle-brackets <>. This is used to include headers provided by the implementation, such as the headers that compose the standard library (iostream, string,...). Whether the headers are actually files or exist in some other form is implementation-defined, but in any case they shall be properly included with this directive.

The syntax used in the second #include uses quotes, and includes a file. The file is searched for in an implementation-defined manner, which generally includes the current path. In the case that the file is not found, the compiler interprets the directive as a header inclusion, just as if the quotes ("") were replaced by angle-brackets (<>).

Pragma directive (#pragma)


This directive is used to specify diverse options to the compiler. These options are specific for the platform and the compiler you use. Consult the manual or the reference of your compiler for more information on the possible parameters that you can define with #pragma.

If the compiler does not support a specific argument for #pragma, it is ignored - no syntax error is generated.

Predefined macro names


The following macro names are always defined (they all begin and end with two underscore characters, _):

macrovalue
__LINE__Integer value representing the current line in the source code file being compiled.
__FILE__A string literal containing the presumed name of the source file being compiled.
__DATE__A string literal in the form "Mmm dd yyyy" containing the date in which the compilation process began.
__TIME__A string literal in the form "hh:mm:ss" containing the time at which the compilation process began.
__cplusplusAn integer value. All C++ compilers have this constant defined to some value. Its value depends on the version of the standard supported by the compiler:
  • 199711L: ISO C++ 1998/2003
  • 201103L: ISO C++ 2011
Non conforming compilers define this constant as some value at most five digits long. Note that many compilers are not fully conforming and thus will have this constant defined as neither of the values above.
__STDC_HOSTED__1 if the implementation is a hosted implementation (with all standard headers available)
0 otherwise.

The following macros are optionally defined, generally depending on whether a feature is available:

macrovalue
__STDC__In C: if defined to 1, the implementation conforms to the C standard.
In C++: Implementation defined.
__STDC_VERSION__In C:
  • 199401L: ISO C 1990, Ammendment 1
  • 199901L: ISO C 1999
  • 201112L: ISO C 2011
In C++: Implementation defined.
__STDC_MB_MIGHT_NEQ_WC__1 if multibyte encoding might give a character a different value in character literals
__STDC_ISO_10646__A value in the form yyyymmL, specifying the date of the Unicode standard followed by the encoding of wchar_t characters
__STDCPP_STRICT_POINTER_SAFETY__1 if the implementation has strict pointer safety (see get_pointer_safety)
__STDCPP_THREADS__1 if the program can have more than one thread

Particular implementations may define additional constants.

For example:

This is the line number 7 of file /home/jay/stdmacronames.cpp.
Its compilation began Nov 1 2005 at 10:12:29.
The compiler gives a __cplusplus value of 1

23 - C++ INPUT / OUTPUT

C++ provides the following classes to perform output and input of characters to/from files:

  • ofstream: Stream class to write on files
  • ifstream: Stream class to read from files
  • fstream: Stream class to both read and write from/to files
  • .

These classes are derived directly or indirectly from the classes istream and ostream. We have already used objects whose types were these classes: cin is an object of class istream and cout is an object of class ostream. Therefore, we have already been using classes that are related to our file streams. And in fact, we can use our file streams the same way we are already used to use cin and cout, with the only difference that we have to associate these streams with physical files. Let's see an example:

[file example.txt]
Writing this to a file.

This code creates a file called example.txt and inserts a sentence into it in the same way we are used to do with cout, but using the file stream myfile instead.

But let's go step by step:

Open a file


The first operation generally performed on an object of one of these classes is to associate it to a real file. This procedure is known as to open a file. An open file is represented within a program by a stream (i.e., an object of one of these classes; in the previous example, this was myfile) and any input or output operation performed on this stream object will be applied to the physical file associated to it.

In order to open a file with a stream object we use its member function open:

open (filename, mode);

Where filename is a string representing the name of the file to be opened, and mode is an optional parameter with a combination of the following flags:

ios::inOpen for input operations.
ios::outOpen for output operations.
ios::binaryOpen in binary mode.
ios::ateSet the initial position at the end of the file.
If this flag is not set, the initial position is the beginning of the file.
ios::appAll output operations are performed at the end of the file, appending the content to the current content of the file.
ios::truncIf the file is opened for output operations and it already existed, its previous content is deleted and replaced by the new one.

All these flags can be combined using the bitwise operator OR (|). For example, if we want to open the file example.bin in binary mode to add data we could do it by the following call to member function open:

Each of the open member functions of classes ofstream, ifstream and fstream has a default mode that is used if the file is opened without a second argument:

classdefault mode parameter
ofstreamios::out
ifstreamios::in
fstreamios::in | ios::out

For ifstream and ofstream classes, ios::in and ios::out are automatically and respectively assumed, even if a mode that does not include them is passed as second argument to the open member function (the flags are combined).

For fstream, the default value is only applied if the function is called without specifying any value for the mode parameter. If the function is called with any value in that parameter the default mode is overridden, not combined.

File streams opened in binary mode perform input and output operations independently of any format considerations. Non-binary files are known as text files, and some translations may occur due to formatting of some special characters (like newline and carriage return characters).

Since the first task that is performed on a file stream is generally to open a file, these three classes include a constructor that automatically calls the open member function and has the exact same parameters as this member. Therefore, we could also have declared the previous myfile object and conduct the same opening operation in our previous example by writing:

Combining object construction and stream opening in a single statement. Both forms to open a file are valid and equivalent.

To check if a file stream was successful opening a file, you can do it by calling to member is_open. This member function returns a bool value of true in the case that indeed the stream object is associated with an open file, or false otherwise:

Closing a file


When we are finished with our input and output operations on a file we shall close it so that the operating system is notified and its resources become available again. For that, we call the stream's member function close. This member function takes flushes the associated buffers and closes the file:

Once this member function is called, the stream object can be re-used to open another file, and the file is available again to be opened by other processes.

In case that an object is destroyed while still associated with an open file, the destructor automatically calls the member function close.

Text files


Text file streams are those where the ios::binary flag is not included in their opening mode. These files are designed to store text and thus all values that are input or output from/to them can suffer some formatting transformations, which do not necessarily correspond to their literal binary value.

Writing operations on text files are performed in the same way we operated with cout:

[file example.txt]
This is a line.
This is another line.

Reading from a file can also be performed in the same way that we did with cin:

This is a line.
This is another line.

This last example reads a text file and prints out its content on the screen. We have created a while loop that reads the file line by line, using getline. The value returned by getline is a reference to the stream object itself, which when evaluated as a boolean expression (as in this while-loop) is true if the stream is ready for more operations, and false if either the end of the file has been reached or if some other error occurred.

Checking state flags


The following member functions exist to check for specific states of a stream (all of them return a bool value):
bad()
Returns true if a reading or writing operation fails. For example, in the case that we try to write to a file that is not open for writing or if the device where we try to write has no space left.
fail()
Returns true in the same cases as bad(), but also in the case that a format error happens, like when an alphabetical character is extracted when we are trying to read an integer number.
eof()
Returns true if a file open for reading has reached the end.
good()
It is the most generic state flag: it returns false in the same cases in which calling any of the previous functions would return true. Note that good and bad are not exact opposites (good checks more state flags at once).

The member function clear() can be used to reset the state flags.

get and put stream positioning


All i/o streams objects keep internally -at least- one internal position:

ifstream, like istream, keeps an internal get position with the location of the element to be read in the next input operation.

ofstream, like ostream, keeps an internal put position with the location where the next element has to be written.

Finally, fstream, keeps both, the get and the put position, like iostream.

These internal stream positions point to the locations within the stream where the next reading or writing operation is performed. These positions can be observed and modified using the following member functions:

tellg() and tellp()
These two member functions with no parameters return a value of the member type streampos, which is a type representing the current get position (in the case of tellg) or the put position (in the case of tellp).

seekg() and seekp()
These functions allow to change the location of the get and put positions. Both functions are overloaded with two different prototypes. The first form is:

seekg ( position );
seekp ( position );

Using this prototype, the stream pointer is changed to the absolute position position (counting from the beginning of the file). The type for this parameter is streampos, which is the same type as returned by functions tellg and tellp.

The other form for these functions is:

seekg ( offset, direction );
seekp ( offset, direction );

Using this prototype, the get or put position is set to an offset value relative to some specific point determined by the parameter direction. offset is of type streamoff. And direction is of type seekdir, which is an enumerated type that determines the point from where offset is counted from, and that can take any of the following values:

ios::begoffset counted from the beginning of the stream
ios::curoffset counted from the current position
ios::endoffset counted from the end of the stream

The following example uses the member functions we have just seen to obtain the size of a file:

size is: 40 bytes.

Notice the type we have used for variables begin and end:

streampos is a specific type used for buffer and file positioning and is the type returned by file.tellg(). Values of this type can safely be subtracted from other values of the same type, and can also be converted to an integer type large enough to contain the size of the file.

These stream positioning functions use two particular types: streampos and streamoff. These types are also defined as member types of the stream class:

TypeMember typeDescription
streamposios::pos_typeDefined as fpos<mbstate_t>.
It can be converted to/from streamoff and can be added or subtracted values of these types.
streamoffios::off_typeIt is an alias of one of the fundamental integral types (such as int or long long).

Each of the member types above is an alias of its non-member equivalent (they are the exact same type). It does not matter which one is used. The member types are more generic, because they are the same on all stream objects (even on streams using exotic types of characters), but the non-member types are widely used in existing code for historical reasons.

Binary files


For binary files, reading and writing data with the extraction and insertion operators (<< and >>) and functions like getline is not efficient, since we do not need to format any data and data is likely not formatted in lines. File streams include two member functions specifically designed to read and write binary data sequentially: write and read. The first one (write) is a member function of ostream (inherited by ofstream). And read is a member function of istream (inherited by ifstream). Objects of class fstream have both. Their prototypes are:

write ( memory_block, size );
read ( memory_block, size );

Where memory_block is of type char* (pointer to char), and represents the address of an array of bytes where the read data elements are stored or from where the data elements to be written are taken. The size parameter is an integer value that specifies the number of characters to be read or written from/to the memory block.

the entire file content is in memory

In this example, the entire file is read and stored in a memory block. Let's examine how this is done:

First, the file is open with the ios::ate flag, which means that the get pointer will be positioned at the end of the file. This way, when we call to member tellg(), we will directly obtain the size of the file.

Once we have obtained the size of the file, we request the allocation of a memory block large enough to hold the entire file:

Right after that, we proceed to set the get position at the beginning of the file (remember that we opened the file with this pointer at the end), then we read the entire file, and finally close it:

At this point we could operate with the data obtained from the file. But our program simply announces that the content of the file is in memory and then finishes.

Buffers and Synchronization


When we operate with file streams, these are associated to an internal buffer object of type streambuf. This buffer object may represent a memory block that acts as an intermediary between the stream and the physical file. For example, with an ofstream, each time the member function put (which writes a single character) is called, the character may be inserted in this intermediate buffer instead of being written directly to the physical file with which the stream is associated.

The operating system may also define other layers of buffering for reading and writing to files.

When the buffer is flushed, all the data contained in it is written to the physical medium (if it is an output stream). This process is called synchronization and takes place under any of the following circumstances:

  • When the file is closed: before closing a file, all buffers that have not yet been flushed are synchronized and all pending data is written or read to the physical medium.
  • When the buffer is full: Buffers have a certain size. When the buffer is full it is automatically synchronized.
  • Explicitly, with manipulators: When certain manipulators are used on streams, an explicit synchronization takes place. These manipulators are: flush and endl.
  • Explicitly, with member function sync(): Calling the stream's member function sync() causes an immediate synchronization. This function returns an int value equal to -1 if the stream has no associated buffer or in case of failure. Otherwise (if the stream buffer was successfully synchronized) it returns 0.

50-game

C#

1 - C# OVERVIEW

C# is a modern, general-purpose, object-oriented programming language developed by Microsoft and approved by European Computer Manufacturers Association (ECMA) and International Standards Organization (ISO).

C# was developed by Anders Hejlsberg and his team during the development of .Net Framework.

C# is designed for Common Language Infrastructure (CLI), which consists of the executable code and runtime environment that allows use of various high-level languages on different computer platforms and architectures.

The following reasons make C# a widely used professional language:

  • It is a modern, general-purpose programming language
  • It is object oriented.
  • It is component oriented.
  • It is easy to learn.
  • It is a structured language.
  • It produces efficient programs.
  • It can be compiled on a variety of computer platforms.
  • It is a part of .Net Framework.

Strong Programming Features of C#


Although C# constructs closely follow traditional high-level languages, C and C++ and being an object-oriented programming language. It has strong resemblance with Java, it has numerous strong programming features that make it endearing to a number of programmers worldwide.

Following is the list of few important features of C#:

  • Boolean Conditions
  • Automatic Garbage Collection
  • Standard Library
  • Assembly Versioning
  • Properties and Events
  • Delegates and Events Management
  • Easy-to-use Generics
  • Indexers
  • Conditional Compilation
  • Simple Multithreading
  • LINQ and Lambda Expressions
  • Integration with Windows

2 - C# ENVIRONMENT

Try it Option Online


We have set up the C# Programming environment online, so that you can compile and execute all the available examples online. It gives you confidence in what you are reading and enables you to verify the programs with different options. Feel free to modify any example and execute it online.

Try the following example using our online compiler available at CodingGround

For most of the examples given in this tutorial, you will find a Try it option in our website code sections at the top right corner that will take you to the online compiler. So just make use of it and enjoy your learning.

In this chapter, we will discuss the tools required for creating C# programming. We have already mentioned that C# is part of .Net framework and is used for writing .Net applications. Therefore, before discussing the available tools for running a C# program, let us understand how C# relates to the .Net framework.

The .Net Framework


The .Net framework is a revolutionary platform that helps you to write the following types of applications:

  • Windows applications
  • Web applications
  • Web services

The .Net framework applications are multi-platform applications. The framework has been designed in such a way that it can be used from any of the following languages: C#, C++, Visual Basic, Jscript, COBOL, etc. All these languages can access the framework as well as communicate with each other.

The .Net framework consists of an enormous library of codes used by the client languages such as C#. Following are some of the components of the .Net framework:

  • Common Language Runtime (CLR)
  • The .Net Framework Class Library
  • Common Language Specification
  • Common Type System
  • Metadata and Assemblies
  • Windows Forms
  • ASP.Net and ASP.Net AJAX
  • ADO.Net
  • Windows Workflow Foundation (WF)
  • Windows Presentation Foundation
  • Windows Communication Foundation (WCF)
  • LINQ

For the jobs each of these components perform, please see ASP.Net - Introduction, and for details of each component, please consult Microsoft's documentation.

Integrated Development Environment (IDE) for C#


Microsoft provides the following development tools for C# programming

  • Visual Studio 2010 (VS)
  • Visual C# 2010 Express (VCE)
  • Visual Web Developer

The last two are freely available from Microsoft official website. Using these tools, you can write all kinds of C# programs from simple command-line applications to more complex applications. You can also write C# source code files using a basic text editor, like Notepad, and compile the code into assemblies using the command-line compiler, which is again a part of the .NET Framework.

Visual C# Express and Visual Web Developer Express edition are trimmed down versions of Visual Studio and has the same appearance. They retain most features of Visual Studio. In this tutorial, we have used Visual C# 2010 Express.

You can download it from Microsoft Visual Studio. It gets installed automatically on your machine.

Note: You need an active internet connection for installing the express edition.

Writing C# Programs on Linux or Mac OS


Although the.NET Framework runs on the Windows operating system, there are some alternative versions that work on other operating systems. Mono is an open-source version of the .NET Framework which includes a C# compiler and runs on several operating systems, including various flavors of Linux and Mac OS.

The stated purpose of Mono is not only to be able to run Microsoft .NET applications cross-platform, but also to bring better development tools for Linux developers. Mono can be run on many operating systems including Android, BSD, iOS, Linux, OS X, Windows, Solaris, and UNIX.

3 - C# PROGRAM STRUCTURE

Before we study basic building blocks of the C# programming language, let us look at a bare minimum C# program structure so that we can take it as a reference in upcoming chapters.

Creating Hello World Program


A C# program consists of the following parts:

  • Namespace declaration
  • A class
  • Class methods
  • Class attributes
  • A Main method
  • Statements and Expressions
  • Comments

Let us look at a simple code that prints the words "Hello World":

When this code is compiled and executed, it produces the following result:

Hello World

Let us look at the various parts of the given program:

  • The first line of the program using System; - the using keyword is used to include the System namespace in the program. A program generally has multiple using statements.
  • The next line has the namespace declaration. A namespace is a collection of classes. The HelloWorldApplication namespace contains the class HelloWorld.
  • The next line has a class declaration, the class HelloWorld contains the data and method definitions that your program uses. Classes generally contain multiple methods. Methods define the behavior of the class. However, the HelloWorld class has only one method Main.
  • The next line defines the Main method, which is the entry point for all C# programs. The Main method states what the class does when executed.
  • The next line /*...*/ is ignored by the compiler and it is put to add comments in the program.
  • The Main method specifies its behavior with the statement Console.WriteLine("Hello World");
  • WriteLine is a method of the Console class defined in the System namespace. This statement causes the message "Hello, World!" to be displayed on the screen.
  • The last line Console.ReadKey(); is for the VS.NET Users. This makes the program wait for a key press and it prevents the screen from running and closing quickly when the program is launched from Visual Studio .NET.
  • It is worth to note the following points:
  • C# is case sensitive.
  • All statements and expression must end with a semicolon (;).
  • The program execution starts at the Main method.
  • Unlike Java, program file name could be different from the class name.

Compiling and Executing the Program


If you are using Visual Studio.Net for compiling and executing C# programs, take the following steps:

  • Start Visual Studio.
  • On the menu bar, choose File -> New -> Project.
  • Choose Visual C# from templates, and then choose Windows.
  • Choose Console Application.
  • Specify a name for your project and click OK button.
  • This creates a new project in Solution Explorer.
  • Write code in the Code Editor.
  • Click the Run button or press F5 key to execute the project. A Command Prompt window appears that contains the line Hello World.

You can compile a C# program by using the command-line instead of the Visual Studio IDE:

  • Open a text editor and add the above-mentioned code.
  • Save the file as helloworld.cs
  • Open the command prompt tool and go to the directory where you saved the file.
  • Type csc helloworld.cs and press enter to compile your code.
  • If there are no errors in your code, the command prompt takes you to the next line and generates helloworld.exe executable file.
  • Type helloworld to execute your program.
  • You can see the output Hello World printed on the screen.

4 - C# SYNTAX

C# is an object-oriented programming language. In Object-Oriented Programming methodology, a program consists of various objects that interact with each other by means of actions. The actions that an object may take are called methods. Objects of the same kind are said to have the same type or, are said to be in the same class.

For example, let us consider a Rectangle object. It has attributes such as length and width. Depending upon the design, it may need ways for accepting the values of these attributes, calculating the area, and displaying details.

Let us look at implementation of a Rectangle class and discuss C# basic syntax:

When the above code is compiled and executed, it produces the following result:

Length: 4.5
Width: 3.5
Area: 15.75

The using Keyword


The first statement in any C# program is

The using keyword is used for including the namespaces in the program. A program can include multiple using statements.

The class Keyword


The class keyword is used for declaring a class.

Comments in C#


Comments are used for explaining code. Compilers ignore the comment entries. The multiline comments in C# programs start with /* and terminates with the characters */ as shown below:

Single-line comments are indicated by the '//' symbol. For example,

Member Variables


Variables are attributes or data members of a class, used for storing data. In the preceding program, the Rectangle class has two member variables named length and width.

Member Functions


Functions are set of statements that perform a specific task. The member functions of a class are declared within the class. Our sample class Rectangle contains three member functions: AcceptDetails, GetArea and Display.

Instantiating a Class


In the preceding program, the class ExecuteRectangle contains the Main() method and instantiates the Rectangle class.

Identifiers


An identifier is a name used to identify a class, variable, function, or any other user-defined item. The basic rules for naming classes in C# are as follows:

  • A name must begin with a letter that could be followed by a sequence of letters, digits (0 - 9) or underscore. The first character in an identifier cannot be a digit.
  • It must not contain any embedded space or symbol such as? - + ! @ # % ^ & * ( ) [ ] { } . ; : " ' / and \. However, an underscore ( _ ) can be used.
  • It should not be a C# keyword.

5 - C# DATA TYPES

The varibles in C#, are categorized into the following types:

  • Value types
  • Reference types
  • Pointer types

Value Type


Value type variables can be assigned a value directly. They are derived from the class System.ValueType.

The value types directly contain data. Some examples are int, char, and float, which stores numbers, alphabets, and floating point numbers, respectively. When you declare an int type, the system allocates memory to store the value.

The following table lists the available value types in C# 2010:

Type Represents Range Default Value
bool Boolean value True or False False
byte 8-bit unsigned integer 0 to 255 0
char 16-bit Unicode character U +0000 to U +ffff '\0'
decimal 128-bit precise decimal values with 28-29 significant digits (-7.9 x 1028 to 7.9 x 1028) / 100 to 28 0.0M
double 64-bit double-precision floating point type (+/-)5.0 x 10-324 to (+/-)1.7 x 10308 0.0D
float 32-bit single-precision floating point type -3.4 x 1038 to + 3.4 x 1038 0.0F
int 32-bit signed integer type -2,147,483,648 to 2,147,483,647 0
long 64-bit signed integer type -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 0L
sbyte 8-bit signed integer type -128 to 127 0
short 16-bit signed integer type -32,768 to 32,767 0
uint 32-bit unsigned integer type 0 to 4,294,967,295 0
ulong 64-bit unsigned integer type 0 to 18,446,744,073,709,551,615 0
ushort 16-bit unsigned integer type 0 to 65,535 0

To get the exact size of a type or a variable on a particular platform, you can use the sizeof method. The expression sizeof(type) yields the storage size of the object or type in bytes. Following is an example to get the size of int type on any machine:

When the above code is compiled and executed, it produces the following result:

Size of int: 4

Reference Type


he reference types do not contain the actual data stored in a variable, but they contain a reference to the variables.

In other words, they refer to a memory location. Using multiple variables, the reference types can refer to a memory location. If the data in the memory location is changed by one of the variables, the other variable automatically reflects this change in value. Example of built-in reference types are: object, dynamic, and string.

Object Type

The Object Type is the ultimate base class for all data types in C# Common Type System (CTS). Object is an alias for System.Object class. The object types can be assigned values of any other types, value types, reference types, predefined or user-defined types. However, before assigning values, it needs type conversion.

When a value type is converted to object type, it is called boxing and on the other hand, when an object type is converted to a value type, it is called unboxing.

Dynamic Type

You can store any type of value in the dynamic data type variable. Type checking for these types of variables takes place at run-time.

Syntax for declaring a dynamic type is:

For example,

Dynamic types are similar to object types except that type checking for object type variables takes place at compile time, whereas that for the dynamic type variables takes place at run time.

String Type

The String Type allows you to assign any string values to a variable. The string type is an alias for the System.String class. It is derived from object type. The value for a string type can be assigned using string literals in two forms: quoted and @quoted.

For example,

A @quoted string literal looks as follows:

The user-defined reference types are: class, interface, or delegate. We will discuss these types in later chapter.

Pointer Type


Pointer type variables store the memory address of another type. Pointers in C# have the same capabilities as the pointers in C or C++.

Syntax for declaring a pointer type is:

For example,

We will discuss pointer types in the chapter 'Unsafe Codes'.

6 - C# TYPE CONVERSION


Type conversion is converting one type of data to another type. It is also known as Type Casting. In C#, type casting has two forms:

  • Implicit type conversion - These conversions are performed by C# in a type-safe manner. For example, are conversions from smaller to larger integral types and conversions from derived classes to base classes.
  • Explicit type conversion - These conversions are done explicitly by users using the pre-defined functions. Explicit conversions require a cast operator.
  • The following example shows an explicit type conversion:

    When the above code is compiled and executed, it produces the following result:

    5673

    C# Type Conversion Methods


    C# provides the following built-in type conversion methods:

    Sr.No Methods & Description
    1 ToBoolean

    Converts a type to a Boolean value, where possible.

    2 ToByte

    Converts a type to a byte.

    3 ToChar

    Converts a type to a single Unicode character, where possible.

    4 ToDateTime

    Converts a type (integer or string type) to date-time structures.

    5 ToDecimal

    Converts a floating point or integer type to a decimal type.

    6 ToDouble

    Converts a type to a double type.

    7 ToInt16

    Converts a type to a 16-bit integer.

    8 ToInt32

    Converts a type to a 32-bit integer.

    9 ToInt64

    Converts a type to a 64-bit integer.

    10 ToSbyte

    Converts a type to a signed byte type.

    11 ToSingle

    Converts a type to a small floating point number.

    12 ToString

    Converts a type to a string.

    13 ToType

    Converts a type to a specified type.

    14 ToUInt16

    Converts a type to an unsigned int type.

    15 ToUInt32

    Converts a type to an unsigned long type.

    16 ToUInt64

    Converts a type to an unsigned big integer.

    The following example converts various value types to string type:

    When the above code is compiled and executed, it produces the following result:

    75
    53.005
    2345.7652
    True

    7 - C# VARIABLES

    A variable is nothing but a name given to a storage area that our programs can manipulate. Each variable in C# has a specific type, which determines the size and layout of the variable's memory the range of values that can be stored within that memory and the set of operations that can be applied to the variable.

    The basic value types provided in C# can be categorized as:

    Type Example
    Integral types sbyte, byte, short, ushort, int, uint, long, ulong, and char
    Floating point types float and double
    Decimal types decimal
    Boolean types true or false values, as assigned
    Nullable types Nullable data types

    C# also allows defining other value types of variable such as enum and reference types of variables such as class, which we will cover in subsequent chapters.

    Defining Variables


    Syntax for variable definition in C# is:

    Here, data_type must be a valid C# data type including char, int, float, double, or any user-defined data type, and variable_list may consist of one or more identifier names separated by commas.

    Some valid variable definitions are shown here:

    You can initialize a variable at the time of definition as:

    Initializing Variables


    Variables are initialized (assigned a value) with an equal sign followed by a constant expression. The general form of initialization is:

    variable_name = value;

    Variables can be initialized in their declaration. The initializer consists of an equal sign followed by a constant expression as:

    Some examples are:

    int d = 3, f = 5; /* initializing d and f. */ byte z = 22; /* initializes z. */ double pi = 3.14159; /* declares an approximation of pi. */ char x = 'x'; /* the variable x has the value 'x'. */

    It is a good programming practice to initialize variables properly, otherwise sometimes program may produce unexpected result.

    The following example uses various types of variables:

    When the above code is compiled and executed, it produces the following result:

    a = 10, b = 20, c = 30

    Accepting Values from User


    The Console class in the System namespace provides a function ReadLine() for accepting input from the user and store it into a variable.

    For example,

    The function Convert.ToInt32() converts the data entered by the user to int data type, because Console.ReadLine() accepts the data in string format.

    Lvalue and Rvalue Expressions in C#:


    There are two kinds of expressions in C#:

  • lvalue: An expression that is an lvalue may appear as either the left-hand or right-hand side of an assignment.
  • rvalue: An expression that is an rvalue may appear on the right- but not left-hand side of an assignment.
  • Variables are lvalues and hence they may appear on the left-hand side of an assignment. Numeric literals are rvalues and hence they may not be assigned and can not appear on the left-hand side. Following is a valid C# statement:

    But following is not a valid statement and would generate compile-time error:

    10 = 20;

    8 - C# CONSTANTS AND LITERALS

    The constants refer to fixed values that the program may not alter during its execution. These fixed values are also called literals. Constants can be of any of the basic data types like an integer constant, a floating constant, a character constant, or a string literal. There are also enumeration constants as well.

    The constants are treated just like regular variables except that their values cannot be modified after their definition.

    Integer Literals


    An integer literal can be a decimal, or hexadecimal constant. A prefix specifies the base or radix: 0x or 0X for hexadecimal, and there is no prefix id for decimal.

    An integer literal can also have a suffix that is a combination of U and L, for unsigned and long, respectively. The suffix can be uppercase or lowercase and can be in any order.

    Here are some examples of integer literals:

    Following are other examples of various types of Integer literals:

    Floating-point Literals


    A floating-point literal has an integer part, a decimal point, a fractional part, and an exponent part. You can represent floating point literals either in decimal form or exponential form.

    Here are some examples of floating-point literals:

    While representing in decimal form, you must include the decimal point, the exponent, or both; and while representing using exponential form you must include the integer part, the fractional part, or both. The signed exponent is introduced by e or E.

    Character Constants


    Character literals are enclosed in single quotes. For example, 'x' and can be stored in a simple variable of char type. A character literal can be a plain character (such as 'x'), an escape sequence (such as '\t'), or a universal character (such as '\u02C0').

    There are certain characters in C# when they are preceded by a backslash. The have special meaning and they are used to represent like newline (\n) or tab (\t). Here, is a list of some of such escape sequence codes:

    Escape sequence Meaning
    \\ \ character
    \' ' character
    \" " character
    \? ? character
    \a Alert or bell
    \b Backspace
    \f Form feed
    \n Newline
    \r Carriage return
    \t Horizontal tab
    \v Vertical tab
    \xhh . . . Hexadecimal number of one or more digits

    Following is the example to show few escape sequence characters:

    When the above code is compiled and executed, it produces the following result:

    Hello World

    String Literals


    String literals or constants are enclosed in double quotes "" or with @"". A string contains characters that are similar to character literals: plain characters, escape sequences, and universal characters.

    You can break a long line into multiple lines using string literals and separating the parts using whitespaces.

    Here are some examples of string literals. All the three forms are identical strings.

    Defining Constants


    Constants are defined using the const keyword. Syntax for defining a constant is:

    The following program demonstrates defining and using a constant in your program:

    When the above code is compiled and executed, it produces the following result:

    Enter Radius:
    3
    Radius: 3, Area: 28.27431

    9 - C# OPERATORS

    An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. C# has rich set of built-in operators and provides the following type of operators:

    • Arithmetic Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Assignment Operators
    • Misc Operators

    This tutorial explains the arithmetic, relational, logical, bitwise, assignment, and other operators one by one.

    Arithmetic Operators


    Following table shows all the arithmetic operators supported by C#. Assume variable A holds 10 and variable B holds 20 then:

    Show Examples

    Operator Description Example
    + Adds two operands A + B = 30
    - Subtracts second operand from the first A - B = -10
    * Multiplies both operands A * B = 200
    / Divides numerator by de-numerator B / A = 2
    % Modulus Operator and remainder of after an integer division B % A = 0
    ++ Increment operator increases integer value by one A++ = 11
    -- Decrement operator decreases integer value by one A-- = 9

    Relational Operators


    Following table shows all the relational operators supported by C#. Assume variable A holds 10 and variable B holds 20, then:

    Show Examples

    Operator Description Example
    == Checks if the values of two operands are equal or not, if yes then condition becomes true. (A == B) is not true.
    != Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. (A != B) is true.
    > Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. (A > B) is not true.
    < Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. (A < B) is true.
    >= Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. (A >= B) is not true.
    <= Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. (A <= B) is true.

    Logical Operators


    Following table shows all the logical operators supported by C#. Assume variable A holds Boolean value true and variable B holds Boolean value false, then:

    Show Examples

    Operator Description Example
    && Called Logical AND operator. If both the operands are non zero then condition becomes true. (A && B) is false.
    || Called Logical OR Operator. If any of the two operands is non zero then condition becomes true. (A || B) is true.
    ! Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false. !(A && B) is true.

    Bitwise Operators


    Bitwise operator works on bits and perform bit by bit operation. The truth tables for &, |, and ^ are as follows:

    p q p & q p | q p ^ q
    0 0 0 0 0
    0 1 0 1 1
    1 1 1 1 0
    1 0 0 1 1

    Assume if A = 60; and B = 13; then in the binary format they are as follows: A = 0011 1100 B = 0000 1101 ----------------- A&B = 0000 1100 A|B = 0011 1101 A^B = 0011 0001

    ~A = 1100 0011

    The Bitwise operators supported by C# are listed in the following table. Assume variable A holds 60 and variable B holds 13, then:

    Show Examples

    Operator Description Example
    & Binary AND Operator copies a bit to the result if it exists in both operands. (A & B) = 12, which is 0000 1100
    | Binary OR Operator copies a bit if it exists in either operand. (A | B) = 61, which is 0011 1101
    ^ Binary XOR Operator copies the bit if it is set in one operand but not both. (A ^ B) = 49, which is 0011 0001
    ~ Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. (~A ) = 61, which is 1100 0011 in 2's complement due to a signed binary number.
    << Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. A << 2 = 240, which is 1111 0000
    >> Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. A >> 2 = 15, which is 0000 1111

    Assignment Operators


    There are following assignment operators supported by C#:

    Show Examples

    Operator Description Example
    = Simple assignment operator, Assigns values from right side operands to left side operand C = A + B assigns value of A + B into C
    += Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand C += A is equivalent to C = C + A
    -= Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand C -= A is equivalent to C = C - A
    *= Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand C *= A is equivalent to C = C * A
    /= Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand C /= A is equivalent to C = C / A
    %= Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand C %= A is equivalent to C = C % A
    <<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
    >>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
    &= Bitwise AND assignment operator C &= 2 is same as C = C & 2
    ^= bitwise exclusive OR and assignment operator C ^= 2 is same as C = C ^ 2
    |= bitwise inclusive OR and assignment operator C |= 2 is same as C = C | 2

    Miscillaneous Operators


    There are few other important operators including sizeof, typeof and ? : supported by C#.

    Show Examples

    Operator Description Example
    sizeof() Returns the size of a data type. sizeof(int), returns 4.
    typeof() Returns the type of a class. typeof(StreamReader);
    & Returns the address of an variable. &a; returns actual address of the variable.
    * Pointer to a variable. *a; creates pointer named 'a' to a variable.
    ? : Conditional Expression If Condition is true ? Then value X : Otherwise value Y
    is Determines whether an object is of a certain type. If( Ford is Car) // checks if Ford is an object of the Car class.
    as Cast without raising an exception if the cast fails. Object obj = new StringReader("Hello");

    StringReader r = obj as StringReader;

    Operator Precedence in C#


    Operator precedence determines the grouping of terms in an expression. This affects evaluation of an expression. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.

    For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so the first evaluation takes place for 3*2 and then 7 is added into it.

    Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators are evaluated first.

    Show Examples

    Category Operator Associativity
    Postfix () [] -> . ++ - - Left to right
    Unary + - ! ~ ++ - - (type)* & sizeof Right to left
    Multiplicative * / % Left to right
    Additive + - Left to right
    Shift << >> Left to right
    Relational < <= > >= Left to right
    Equality == != Left to right
    Bitwise AND & Left to right
    Bitwise XOR ^ Left to right
    Bitwise OR | Left to right
    Logical AND && Left to right
    Logical OR || Left to right
    Conditional ?: Right to left
    Assignment = += -= *= /= %=>>= <<= &= ^= |= Right to left
    Comma , Left to right

    10 - C# DECISION MAKING

    Decision making structures requires the programmer to specify one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.

    Following is the general from of a typical decision making structure found in most of the programming languages:

    C# provides following types of decision making statements. Click the following links to check their detail.

    Statement Description

    if statement

    An if statement consists of a boolean expression followed by one or more statements.

    if...else statement

    An if statement can be followed by an optional else statement, which executes when the boolean expression is false.

    nested if statements

    You can use one if or else if statement inside another if or else if statement(s).

    switch statement

    A switch statement allows a variable to be tested for equality against a list of values.

    nested switch statements

    You can use one switch statement inside another switch statement(s).

    The ? : Operator:


    We have covered conditional operator ? : in previous chapter which can be used to replace if...else statements. It has the following general form:

    Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.

    The value of a ? expression is determined as follows: Exp1 is evaluated. If it is true, then Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then Exp3 is evaluated and its value becomes the value of the expression.

    11 - C# LOOPS

    There may be a situation, when you need to execute a block of code several number of times. In general, the statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.

    Programming languages provide various control structures that allow for more complicated execution paths.

    A loop statement allows us to execute a statement or a group of statements multiple times and following is the general from of a loop statement in most of the programming languages:

    C# provides following types of loop to handle looping requirements. Click the following links to check their detail.

    Loop Type Description

    while loop

    It repeats a statement or a group of statements while a given condition is true. It tests the condition before executing the loop body.

    for loop

    It executes a sequence of statements multiple times and abbreviates the code that manages the loop variable.

    do...while loop

    It is similar to a while statement, except that it tests the condition at the end of the loop body

    nested loops

    You can use one or more loop inside any another while, for or do..while loop.

    Loop Control Statements


    Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.

    C# provides the following control statements. Click the following links to check their details.

    Control Statement Description

    break statement

    Terminates the loop or switch statement and transfers execution to the statement immediately following the loop or switch.

    continue statement

    Causes the loop to skip the remainder of its body and immediately retest its condition prior to reiterating.

    Infinite Loop


    A loop becomes infinite loop if a condition never becomes false. The for loop is traditionally used for this purpose. Since none of the three expressions that form the for loop are required, you can make an endless loop by leaving the conditional expression empty.

    Example

    When the conditional expression is absent, it is assumed to be true. You may have an initialization and increment expression, but programmers more commonly use the for(;;) construct to signify an infinite loop.

    12 - C# ENCAPSULATION


    Encapsulation is defined 'as the process of enclosing one or more items within a physical or logical package'. Encapsulation, in object oriented programming methodology, prevents access to implementation details.

    Abstraction and encapsulation are related features in object oriented programming.
    Abstraction allows making relevant information visible and encapsulation enables a programmer to implement the desired level of abstraction.

    Encapsulation is implemented by using access specifiers. An access specifier defines the scope and visibility of a class member. C# supports the following access specifiers:

    • Public
    • Private
    • Protected
    • Internal
    • Protected internal

    Public Access Specifier


    Public access specifier allows a class to expose its member variables and member functions to other functions and objects. Any public member can be accessed from outside the class.

    The following example illustrates this:

    When the above code is compiled and executed, it produces the following result:

    Length: 4.5
    Width: 3.5
    Area: 15.75

    In the preceding example, the member variables length and width are declared public, so they can be accessed from the function Main() using an instance of the Rectangle class, named r.

    The member function Display() and GetArea() can also access these variables directly without using any instance of the class.

    The member functions Display() is also declared public, so it can also be accessed from Main() using an instance of the Rectangle class, named r.

    Private Access Specifier


    Private access specifier allows a class to hide its member variables and member functions from other functions and objects. Only functions of the same class can access its private members. Even an instance of a class cannot access its private members.

    The following example illustrates this:

    When the above code is compiled and executed, it produces the following result:

    Enter Length:
    4.4
    Enter Width:
    3.3
    Length: 4.4
    Width: 3.3
    Area: 14.52

    In the preceding example, the member variables length and width are declared private, so they cannot be accessed from the function Main(). The member functions AcceptDetails() and Display() can access these variables. Since the member functions AcceptDetails() and Display() are declared public, they can be accessed from Main() using an instance of the Rectangle class, named r.

    Protected Access Specifier


    Protected access specifier allows a child class to access the member variables and member functions of its base class. This way it helps in implementing inheritance. We will discuss this in more details in the inheritance chapter.

    Internal Access Specifier


    Internal access specifier allows a class to expose its member variables and member functions to other functions and objects in the current assembly. In other words, any member with internal access specifier can be accessed from any class or method defined within the application in which the member is defined.

    The following program illustrates this:

    When the above code is compiled and executed, it produces the following result:

    Length: 4.5
    Width: 3.5
    Area: 15.75

    In the preceding example, notice that the member function GetArea() is not declared with any access specifier. Then what would be the default access specifier of a class member if we don't mention any? It is private.

    Protected Internal Access Specifier


    The protected internal access specifier allows a class to hide its member variables and member functions from other class objects and functions, except a child class within the same application. This is also used while implementing inheritance.

    13 - C# Methods

    A method is a group of statements that together perform a task. Every C# program has at least one class with a method named Main.

    To use a method, you need to:

      Define the method
      Call the method

    Defining Methods in C#


    When you define a method, you basically declare the elements of its structure. The syntax for defining a method in C# is as follows:

    Following are the various elements of a method:

    • Access Specifier: This determines the visibility of a variable or a method from another class.
    • Return type: A method may return a value. The return type is the data type of the value the method returns. If the method is not returning any values, then the return type is void.
    • Method name: Method name is a unique identifier and it is case sensitive. It cannot be same as any other identifier declared in the class.
    • Parameter list: Enclosed between parentheses, the parameters are used to pass and receive data from a method. The parameter list refers to the type, order, and number of the parameters of a method. Parameters are optional; that is, a method may contain no parameters.
    • Method body: This contains the set of instructions needed to complete the required activity.

    Example

    Following code snippet shows a function FindMax that takes two integer values and returns the larger of the two. It has public access specifier, so it can be accessed from outside the class using an instance of the class.

    Calling Methods in C#


    You can call a method using the name of the method. The following example illustrates this:

    When the above code is compiled and executed, it produces the following result:

    Max value is : 200

    You can also call public method from other classes by using the instance of the class. For example, the method FindMax belongs to the NumberManipulator class, you can call it from another class Test.

    When the above code is compiled and executed, it produces the following result:

    Max value is : 200

    Recursive Method Call


    A method can call itself. This is known as recursion. Following is an example that calculates factorial for a given number using a recursive function:

    When the above code is compiled and executed, it produces the following result:

    Factorial of 6 is: 720
    Factorial of 7 is: 5040
    Factorial of 8 is: 40320

    Passing Parameters to a Method


    When method with parameters is called, you need to pass the parameters to the method. There are three ways that parameters can be passed to a method:

    Mechanism Description

    Value parameters

    This method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.

    Reference parameters

    This method copies the reference to the memory location of an argument into the formal parameter. This means that changes made to the parameter affect the argument.

    Output parameters

    This method helps in returning more than one value.

    14 - C# NULLABLES

    C# provides a special data types, the nullable types, to which you can assign normal range of values as well as null values.

    For example, you can store any value from -2,147,483,648 to 2,147,483,647 or null in a Nullable<<Int32> variable. Similarly, you can assign true, false, or null in a Nullable<<bool> variable. Syntax for declaring a nullable type is as follows:

    The following example demonstrates use of nullable data types:

    When the above code is compiled and executed, it produces the following result:

    Nullables at Show: , 45, , 3.14157
    A Nullable boolean value:

    The Null Coalescing Operator (??)


    The null coalescing operator is used with the nullable value types and reference types. It is used for converting an operand to the type of another nullable (or not) value type operand, where an implicit conversion is possible.

    If the value of the first operand is null, then the operator returns the value of the second operand, otherwise it returns the value of the first operand. The following example explains this:

    When the above code is compiled and executed, it produces the following result:

    An array stores a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type stored at contiguous memory locations.

    Instead of declaring individual variables, such as number0, number1, ..., and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and ..., numbers[99] to represent individual variables. A specific element in an array is accessed by an index.

    All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.

    Declaring Arrays


    To declare an array in C#, you can use the following syntax:

    where

    • datatype is used to specify the type of elements in the array.
    • [ ] specifies the rank of the array. The rank specifies the size of the array.
    • arrayName specifies the name of the array.

    For example,

    Initializing an Array


    Declaring an array does not initialize the array in the memory. When the array variable is initialized, you can assign values to the array.

    Array is a reference type, so you need to use the new keyword to create an instance of the array. For example,

    Assigning Values to an Array


    You can assign values to individual array elements, by using the index number, like:

    You can assign values to the array at the time of declaration, as shown:

    You can also create and initialize an array, as shown:

    You may also omit the size of the array, as shown:

    You can copy an array variable into another target array variable. In such case, both the target and source point to the same memory location:

    When you create an array, C# compiler implicitly initializes each array element to a default value depending on the array type. For example, for an int array all elements are initialized to 0.

    Accessing Array Elements


    An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example,

    The following example, demonstrates the above-mentioned concepts declaration, assignment, and accessing arrays:

    When the above code is compiled and executed, it produces the following result:

    Element[0] = 100
    Element[1] = 101
    Element[2] = 102
    Element[3] = 103
    Element[4] = 104
    Element[5] = 105
    Element[6] = 106
    Element[7] = 107
    Element[8] = 108
    Element[9] = 109

    Using the foreach Loop


    In the previous example, we used a for loop for accessing each array element. You can also use a foreach statement to iterate through an array.

    When the above code is compiled and executed, it produces the following result:

    Element[0] = 100
    Element[1] = 101
    Element[2] = 102
    Element[3] = 103
    Element[4] = 104
    Element[5] = 105
    Element[6] = 106
    Element[7] = 107
    Element[8] = 108
    Element[9] = 109

    C# Arrays


    There are following few important concepts related to array which should be clear to a C# programmer:

    Concept Description

    Multi-dimensional arrays

    C# supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array.

    Jagged arrays

    C# supports multidimensional arrays, which are arrays of arrays.

    Passing arrays to functions

    You can pass to the function a pointer to an array by specifying the array's name without an index.

    Param arrays

    This is used for passing unknown number of parameters to a function.

    The Array Class

    Defined in System namespace, it is the base class to all arrays, and provides various properties and methods for working with arrays.

    15 - C# STRINGS

    In C#, you can use strings as array of characters, However, more common practice is to use the string keyword to declare a string variable. The string keyword is an alias for the System.String class.

    Creating a String Object


    You can create string object using one of the following methods:

      By assigning a string literal to a String variable

      By using a String class constructor

      By using the string concatenation operator (+)

      By retrieving a property or calling a method that returns a string

      By calling a formatting method to convert a value or an object to its string representation

    The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Full Name: Rowan Atkinson
    Greetings: Hello
    Message: Hello From Tutorials Point
    Message: Message sent at 5:58 PM on Wednesday, October 10, 2012

    Properties of the String Class


    The String class has the following two properties:

    Sr.No Property
    1 Chars

    Gets the Char object at a specified position in the current String object.

    2 Length

    Gets the number of characters in the current String object.

    Methods of the String Class


    The String class has numerous methods that help you in working with the string objects. The following table provides some of the most commonly used methods:

    Sr.No Methods
    1 public static int Compare(string strA, string strB)

    Compares two specified string objects and returns an integer that indicates their relative position in the sort order.

    2 public static int Compare(string strA, string strB, bool ignoreCase )

    Compares two specified string objects and returns an integer that indicates their relative position in the sort order. However, it ignores case if the Boolean parameter is true.

    3 public static string Concat(string str0, string str1)

    Concatenates two string objects.

    4 public static string Concat(string str0, string str1, string str2)

    Concatenates three string objects.

    5 public static string Concat(string str0, string str1, string str2, string str3)

    Concatenates four string objects.

    6 public bool Contains(string value)

    Returns a value indicating whether the specified String object occurs within this string.

    7 public static string Copy(string str)

    Creates a new String object with the same value as the specified string.

    8 public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)

    Copies a specified number of characters from a specified position of the String object to a specified position in an array of Unicode characters.

    9 public bool EndsWith(string value)

    Determines whether the end of the string object matches the specified string.

    10 public bool Equals(string value)

    Determines whether the current String object and the specified String object have the same value.

    11 public static bool Equals(string a, string b)

    Determines whether two specified String objects have the same value.

    12 public static string Format(string format, Object arg0)

    Replaces one or more format items in a specified string with the string representation of a specified object.

    13 public int IndexOf(char value)

    Returns the zero-based index of the first occurrence of the specified Unicode character in the current string.

    14 public int IndexOf(string value)

    Returns the zero-based index of the first occurrence of the specified string in this instance.

    15 public int IndexOf(char value, int startIndex)

    Returns the zero-based index of the first occurrence of the specified Unicode character in this string, starting search at the specified character position.

    16 public int IndexOf(string value, int startIndex)

    Returns the zero-based index of the first occurrence of the specified string in this instance, starting search at the specified character position.

    17 public int IndexOfAny(char[] anyOf)

    Returns the zero-based index of the first occurrence in this instance of any character in a specified array of Unicode characters.

    18 public int IndexOfAny(char[] anyOf, int startIndex)

    Returns the zero-based index of the first occurrence in this instance of any character in a specified array of Unicode characters, starting search at the specified character position.

    19 public string Insert(int startIndex, string value)

    Returns a new string in which a specified string is inserted at a specified index position in the current string object.

    20 public static bool IsNullOrEmpty(string value)

    Indicates whether the specified string is null or an Empty string.

    21 public static string Join(string separator, params string[] value)

    Concatenates all the elements of a string array, using the specified separator between each element.

    22 public static string Join(string separator, string[] value, int startIndex, int count)

    Concatenates the specified elements of a string array, using the specified separator between each element.

    23 public int LastIndexOf(char value)

    Returns the zero-based index position of the last occurrence of the specified Unicode character within the current string object.

    24 public int LastIndexOf(string value)

    Returns the zero-based index position of the last occurrence of a specified string within the current string object.

    25 public string Remove(int startIndex)

    Removes all the characters in the current instance, beginning at a specified position and continuing through the last position, and returns the string.

    26 public string Remove(int startIndex, int count)

    Removes the specified number of characters in the current string beginning at a specified position and returns the string.

    27 public string Replace(char oldChar, char newChar)

    Replaces all occurrences of a specified Unicode character in the current string object with the specified Unicode character and returns the new string.

    28 public string Replace(string oldValue, string newValue)

    Replaces all occurrences of a specified string in the current string object with the specified string and returns the new string.

    29 public string[] Split(params char[] separator)

    Returns a string array that contains the substrings in the current string object, delimited by elements of a specified Unicode character array.

    30 public string[] Split(char[] separator, int count)

    Returns a string array that contains the substrings in the current string object, delimited by elements of a specified Unicode character array. The int parameter specifies the maximum number of substrings to return.

    31 public bool StartsWith(string value)

    Determines whether the beginning of this string instance matches the specified string.

    32 public char[] ToCharArray()

    Returns a Unicode character array with all the characters in the current string object.

    33 public char[] ToCharArray(int startIndex, int length)

    Returns a Unicode character array with all the characters in the current string object, starting from the specified index and up to the specified length.

    34 public string ToLower()

    Returns a copy of this string converted to lowercase.

    35 public string ToUpper()

    Returns a copy of this string converted to uppercase.

    36 public string Trim()

    Removes all leading and trailing white-space characters from the current String object.

    You can visit MSDN library for the complete list of methods and String class constructors.

    Examples

    The following example demonstrates some of the methods mentioned above:

    Comparing Strings:

    When the above code is compiled and executed, it produces the following result:

    This is test and This is text are not equal.

    String Contains String:

    When the above code is compiled and executed, it produces the following result:

    The sequence 'test' was found.

    Getting a Substring:

    When the above code is compiled and executed, it produces the following result:

    San Pedro

    Joining Strings:

    When the above code is compiled and executed, it produces the following result:

    Down the way nights are dark
    And the sun shines daily on the mountain top
    I took a trip on a sailing ship
    And when I reached Jamaica
    I made a stop

    16 - C# STRUCTURES

    In C#, a structure is a value type data type. It helps you to make a single variable hold related data of various data types. The struct keyword is used for creating a structure.

    Structures are used to represent a record. Suppose you want to keep track of your books in a library. You might want to track the following attributes about each book:

    • Title
    • Author
    • Subject
    • Book ID

    Defining a Structure


    To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than one member for your program.

    For example, here is the way you can declare the Book structure:

    The following program shows the use of the structure:

    When the above code is compiled and executed, it produces the following result:

    Book 1 title : C Programming
    Book 1 author : Nuha Ali
    Book 1 subject : C Programming Tutorial
    Book 1 book_id : 6495407
    Book 2 title : Telecom Billing
    Book 2 author : Zara Ali
    Book 2 subject : Telecom Billing Tutorial
    Book 2 book_id : 6495700

    Features of C# Structures


    You have already used a simple structure named Books. Structures in C# are quite different from that in traditional C or C++. The C# structures have the following features:

    • Structures can have methods, fields, indexers, properties, operator methods, and events.
    • Structures can have defined constructors, but not destructors. However, you cannot define a default constructor for a structure. The default constructor is automatically defined and cannot be changed.
    • Unlike classes, structures cannot inherit other structures or classes.
    • Structures cannot be used as a base for other structures or classes.
    • A structure can implement one or more interfaces.
    • Structure members cannot be specified as abstract, virtual, or protected.
    • When you create a struct object using the New operator, it gets created and the appropriate constructor is called. Unlike classes, structs can be instantiated without using the New operator.
    • If the New operator is not used, the fields remain unassigned and the object cannot be used until all the fields are initialized.

    Class versus Structure


    Classes and Structures have the following basic differences:

    • classes are reference types and structs are value types
    • structures do not support inheritance
    • structures cannot have default constructor

    In the light of the above discussions, let us rewrite the previous example:

    When the above code is compiled and executed, it produces the following result:

    Title : C Programming
    Author : Nuha Ali
    Subject : C Programming Tutorial
    Book_id : 6495407
    Title : Telecom Billing
    Author : Zara Ali
    Subject : Telecom Billing Tutorial
    Book_id : 6495700

    17 - C# ENUMS

    An enumeration is a set of named integer constants. An enumerated type is declared using the enum keyword.

    C# enumerations are value data type. In other words, enumeration contains its own values and cannot inherit or cannot pass inheritance.

    Declaring enum Variable


    The general syntax for declaring an enumeration is:

    Where,

    • The enum_name specifies the enumeration type name.
    • The enumeration list is a comma-separated list of identifiers.

    Each of the symbols in the enumeration list stands for an integer value, one greater than the symbol that precedes it. By default, the value of the first enumeration symbol is 0. For example:

    Example

    The following example demonstrates use of enum variable:

    When the above code is compiled and executed, it produces the following result:

    Monday: 1
    Friday: 5

    18 - C# CLASSES

    When you define a class, you define a blueprint for a data type. This does not actually define any data, but it does define what the class name means. That is, what an object of the class consists of and what operations can be performed on that object. Objects are instances of a class. The methods and variables that constitute a class are called members of the class.

    Defining a Class


    A class definition starts with the keyword class followed by the class name; and the class body enclosed by a pair of curly braces. Following is the general form of a class definition:

    Note:
    • Access specifiers specify the access rules for the members as well as the class itself. If not mentioned, then the default access specifier for a class type is internal. Default access for the members is private.
    • Data type specifies the type of variable, and return type specifies the data type of the data the method returns, if any.
    • To access the class members, you use the dot (.) operator.
    • The dot operator links the name of an object with the name of a member.

    The following example illustrates the concepts discussed so far:

    When the above code is compiled and executed, it produces the following result:

    Volume of Box1 : 210
    Volume of Box2 : 1560

    Member Functions and Encapsulation


    A member function of a class is a function that has its definition or its prototype within the class definition similar to any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object.

    Member variables are the attributes of an object (from design perspective) and they are kept private to implement encapsulation. These variables can only be accessed using the public member functions.

    Let us put above concepts to set and get the value of different class members in a class:

    When the above code is compiled and executed, it produces the following result:

    Volume of Box1 : 210
    Volume of Box2 : 1560

    C# Constructors


    A class constructor is a special member function of a class that is executed whenever we create new objects of that class.

    A constructor has exactly the same name as that of class and it does not have any return type. Following example explains the concept of constructor:

    When the above code is compiled and executed, it produces the following result:

    Object is being created
    Length of line : 6

    A default constructor does not have any parameter but if you need, a constructor can have parameters. Such constructors are called parameterized constructors. This technique helps you to assign initial value to an object at the time of its creation as shown in the following example:

    When the above code is compiled and executed, it produces the following result:

    Object is being created, length = 10
    Length of line : 10
    Length of line : 6

    C# Destructors


    A destructor is a special member function of a class that is executed whenever an object of its class goes out of scope. A destructor has exactly the same name as that of the class with a prefixed tilde (~) and it can neither return a value nor can it take any parameters.

    Destructor can be very useful for releasing memory resources before exiting the program. Destructors cannot be inherited or overloaded.

    Following example explains the concept of destructor:

    When the above code is compiled and executed, it produces the following result:

    Object is being created
    Length of line : 6
    Object is being deleted

    Static Members of a C# Class


    We can define class members as static using the static keyword. When we declare a member of a class as static, it means no matter how many objects of the class are created, there is only one copy of the static member.

    The keyword static implies that only one instance of the member exists for a class. Static variables are used for defining constants because their values can be retrieved by invoking the class without creating an instance of it. Static variables can be initialized outside the member function or class definition. You can also initialize static variables inside the class definition.

    The following example demonstrates the use of static variables:

    When the above code is compiled and executed, it produces the following result:

    Variable num for s1: 6
    Variable num for s2: 6

    You can also declare a member function as static. Such functions can access only static variables. The static functions exist even before the object is created. The following example demonstrates the use of static functions:

    When the above code is compiled and executed, it produces the following result:

    Variable num: 3

    19 - C# INHERITANCE

    One of the most important concepts in object-oriented programming is inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application. This also provides an opportunity to reuse the code functionality and speeds up implementation time.

    When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class.

    The idea of inheritance implements the IS-A relationship. For example, mammal IS A animal, dog IS-A mammal hence dog IS-A animal as well, and so on.

    Base and Derived Classes


    A class can be derived from more than one class or interface, which means that it can inherit data and functions from multiple base classes or interfaces.

    The syntax used in C# for creating derived classes is as follows:

    Consider a base class Shape and its derived class Rectangle:

    When the above code is compiled and executed, it produces the following result:

    Total area: 35

    Initializing Base Class


    The derived class inherits the base class member variables and member methods. Therefore the super class object should be created before the subclass is created. You can give instructions for superclass initialization in the member initialization list.

    The following program demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Length: 4.5
    Width: 7.5
    Area: 33.75
    Cost: 2362.5

    Multiple Inheritance in C#


    C# does not support multiple inheritance. However, you can use interfaces to implement multiple inheritance. The following program demonstrates this:

    using System; namespace InheritanceApplication { class Shape { public void setWidth(int w) { width = w; } public void setHeight(int h) { height = h; } protected int width; protected int height; } // Base class PaintCost public interface PaintCost { int getCost(int area); } // Derived class class Rectangle : Shape, PaintCost { public int getArea() { return (width * height); } public int getCost(int area) { return area * 70; } } class RectangleTester { static void Main(string[] args) { Rectangle Rect = new Rectangle(); int area; Rect.setWidth(5); Rect.setHeight(7); area = Rect.getArea(); // Print the area of the object. Console.WriteLine("Total area: {0}", Rect.getArea()); Console.WriteLine("Total paint cost: ${0}" , Rect.getCost(area)); Console.ReadKey(); } } }

    When the above code is compiled and executed, it produces the following result:

    Total area: 35
    Total paint cost: $2450

    20 - C# POLYMORPHISM

    The word polymorphism means having many forms. In object-oriented programming paradigm, polymorphism is often expressed as 'one interface, multiple functions'.

    Polymorphism can be static or dynamic. In static polymorphism, the response to a function is determined at the compile time. In dynamic polymorphism, it is decided at run-time.

    Static Polymorphism


    The mechanism of linking a function with an object during compile time is called early binding. It is also called static binding. C# provides two techniques to implement static polymorphism. They are:

    • Function overloading
    • Operator overloading

    We discuss operator overloading in next chapter.

    Function Overloading


    You can have multiple definitions for the same function name in the same scope. The definition of the function must differ from each other by the types and/or the number of arguments in the argument list. You cannot overload function declarations that differ only by return type.

    The following example shows using function print() to print different data types:

    When the above code is compiled and executed, it produces the following result:

    Printing int: 5
    Printing float: 500.263
    Printing string: Hello C++

    Dynamic Polymorphism


    C# allows you to create abstract classes that are used to provide partial class implementation of an interface. Implementation is completed when a derived class inherits from it. Abstract classes contain abstract methods, which are implemented by the derived class. The derived classes have more specialized functionality.

    Here are the rules about abstract classes:

    • You cannot create an instance of an abstract class
    • You cannot declare an abstract method outside an abstract class
    • When a class is declared sealed, it cannot be inherited, abstract classes cannot be
    • declared sealed.

      The following program demonstrates an abstract class:

    When the above code is compiled and executed, it produces the following result:

    Rectangle class area :
    Area: 70

    When you have a function defined in a class that you want to be implemented in an inherited class(es), you use virtual functions. The virtual functions could be implemented differently in different inherited class and the call to these functions will be decided at runtime.

    Dynamic polymorphism is implemented by abstract classes and virtual functions.

    The following program demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Rectangle class area:
    Area: 70
    Triangle class area:
    Area: 25

    21 - C# OPERATOR OVERLOADING

    You can redefine or overload most of the built-in operators available in C#. Thus a programmer can use operators with user-defined types as well. Overloaded operators are functions with special names the keyword operator followed by the symbol for the operator being defined. similar to any other function, an overloaded operator has a return type and a parameter list.>
    >
    For example, go through the following function:

    The above function implements the addition operator (+) for a user-defined class Box. It adds the attributes of two Box objects and returns the resultant Box object.

    Implementing the Operator Overloading


    The following program shows the complete implementation:

    When the above code is compiled and executed, it produces the following result:

    Volume of Box1 : 210
    Volume of Box2 : 1560
    Volume of Box3 : 5400

    Overloadable and Non-Overloadable Operators


    The following table describes the overload ability of the operators in C#:

    Operators Description
    +, -, !, ~, ++, -- These unary operators take one operand and can be overloaded.
    +, -, *, /, % These binary operators take one operand and can be overloaded.
    ==, !=, <, >, <=, >= The comparison operators can be overloaded
    &&, || The conditional logical operators cannot be overloaded directly.
    +=, -=, *=, /=, %= The assignment operators cannot be overloaded.
    =, ., ?:, ->, new, is, sizeof, typeof These operators cannot be overloaded.

    Example

    In the light of the above discussions, let us extend the preceding example, and overload few more operators:

    When the above code is compiled and executed, it produces the following result:

    Box 1: (6, 7, 5)
    Box 2: (12, 13, 10)
    Volume of Box1 : 210
    Volume of Box2 : 1560
    Box 3: (18, 20, 15)
    Volume of Box3 : 5400
    Box1 is not greater than Box2
    Box1 is less than Box2
    Box1 is not greater or equal to Box2
    Box1 is less or equal to Box2
    Box1 is not equal to Box2
    Box3 is equal to Box4

    22 - C# INTERFACES

    An interface is defined as a syntactical contract that all the classes inheriting the interface should follow. The interface defines the 'what' part of the syntactical contract and the deriving classes define the 'how' part of the syntactical contract.

    Interfaces define properties, methods, and events, which are the members of the interface. Interfaces contain only the declaration of the members. It is the responsibility of the deriving class to define the members. It often helps in providing a standard structure that the deriving classes would follow.

    Abstract classes to some extent serve the same purpose, however, they are mostly used when only few methods are to be declared by the base class and the deriving class implements the functionalities.

    Declaring Interfaces


    Interfaces are declared using the interface keyword. It is similar to class declaration. Interface statements are public by default. Following is an example of an interface declaration:

    Example

    The following example demonstrates implementation of the above interface:

    When the above code is compiled and executed, it produces the following result:

    Transaction: 001
    Date: 8/10/2012
    Amount: 78900
    Transaction: 002
    Date: 9/10/2012
    Amount: 451900

    23 - C# NAMESPACES

    A namespace is designed for providing a way to keep one set of names separate from another. The class names declared in one namespace does not conflict with the same class names declared in another.

    Defining a Namespace


    A namespace definition begins with the keyword namespace followed by the namespace name as follows:

    To call the namespace-enabled version of either function or variable, prepend the namespace name as follows:

    The following program demonstrates use of namespaces:

    When the above code is compiled and executed, it produces the following result:

    Inside first_space
    Inside second_space

    The using Keyword


    The using keyword states that the program is using the names in the given namespace. For example, we are using the System namespace in our programs. The class Console is defined there. We just write:

    We could have written the fully qualified name as:

    You can also avoid prepending of namespaces with the using namespace directive. This directive tells the compiler that the subsequent code is making use of names in the specified namespace. The namespace is thus implied for the following code:

    Let us rewrite our preceding example, with using directive:

    When the above code is compiled and executed, it produces the following result:

    Inside first_space Inside second_space

    Nested Namespaces


    You can define one namespace inside another namespace as follows:

    You can access members of nested namespace by using the dot (.) operator as follows:

    When the above code is compiled and executed, it produces the following result:

    Inside first_space
    Inside second_space

    24 - C# PREPROCESSOR DIRECTIVES

    The preprocessor directives give instruction to the compiler to preprocess the information before actual compilation starts.

    All preprocessor directives begin with #, and only white-space characters may appear before a preprocessor directive on a line. Preprocessor directives are not statements, so they do not end with a semicolon (;).

    C# compiler does not have a separate preprocessor; however, the directives are processed as if there was one. In C# the preprocessor directives are used to help in conditional compilation. Unlike C and C++ directives, they are not used to create macros. A preprocessor directive must be the only instruction on a line.

    Preprocessor Directives in C#


    The following table lists the preprocessor directives available in C#:

    Preprocessor Directive Description.
    #define It defines a sequence of characters, called symbol.
    #undef It allows you to undefine a symbol.
    #if It allows testing a symbol or symbols to see if they evaluate to true.
    #else It allows to create a compound conditional directive, along with #if.
    #elif It allows creating a compound conditional directive.
    #endif Specifies the end of a conditional directive.
    #line It lets you modify the compiler's line number and (optionally) the file name output for errors and warnings.
    #error It allows generating an error from a specific location in your code.
    #warning It allows generating a level one warning from a specific location in your code.
    #region It lets you specify a block of code that you can expand or collapse when using the outlining feature of the Visual Studio Code Editor.
    #endregion It marks the end of a #region block.

    The #define Preprocessor


    The #define preprocessor directive creates symbolic constants.

    #define lets you define a symbol such that, by using the symbol as the expression passed to the #if directive, the expression evaluates to true. Its syntax is as follows:

    The following program illustrates this:

    When the above code is compiled and executed, it produces the following result:

    PI is defined

    Conditional Directives


    You can use the #if directive to create a conditional directive. Conditional directives are useful for testing a symbol or symbols to check if they evaluate to true. If they do evaluate to true, the compiler evaluates all the code between the #if and the next directive.

    Syntax for conditional directive is:

    Where, symbol is the name of the symbol you want to test. You can also use true and false or prepend the symbol with the negation operator.

    The operator symbol is the operator used for evaluating the symbol. Operators could be either of the following:

    • == (equality)
    • != (inequality)
    • && (and)
    • || (or)

    ou can also group symbols and operators with parentheses. Conditional directives are used for compiling code for a debug build or when compiling for a specific configuration. A conditional directive beginning with a #if directive must explicitly be terminated with a #endif directive.

    The following program demonstrates use of conditional directives:

    When the above code is compiled and executed, it produces the following result:

    DEBUG and VC_V10 are defined

    24 - C# REGULAR EXPRESSIONS

    A regular expression is a pattern that could be matched against an input text. The .Net framework provides a regular expression engine that allows such matching. A pattern consists of one or more character literals, operators, or constructs.

    Constructs for Defining Regular Expressions


    There are various categories of characters, operators, and constructs that lets you to define regular expressions. Click the follwoing links to find these constructs.

    • Character escapes
    • Character classes
    • Anchors
    • Grouping constructs
    • Quantifiers
    • Backreference constructs
    • Alternation constructs
    • Substitutions
    • Miscellaneous constructs

    The Regex Class


    The Regex class is used for representing a regular expression. It has the following commonly used methods:

    Sr.No Methods
    1 public bool IsMatch(string input)

    Indicates whether the regular expression specified in the Regex constructor finds a match in a specified input string.

    2 public bool IsMatch(string input, int startat)

    Indicates whether the regular expression specified in the Regex constructor finds a match in the specified input string, beginning at the specified starting position in the string.

    3 public static bool IsMatch(string input, string pattern)

    Indicates whether the specified regular expression finds a match in the specified input string.

    4 public MatchCollection Matches(string input)

    Searches the specified input string for all occurrences of a regular expression.

    5 public string Replace(string input, string replacement)

    In a specified input string, replaces all strings that match a regular expression pattern with a specified replacement string.

    6 public string[] Split(string input)

    Splits an input string into an array of substrings at the positions defined by a regular expression pattern specified in the Regex constructor.

    For the complete list of methods and properties, please read the Microsoft documentation on C#.

    Example 1

    The following example matches words that start with 'S':

    When the above code is compiled and executed, it produces the following result:

    Matching words that start with 'S':
    The Expression: \bS\S*
    Splendid
    Suns

    Example 2

    The following example matches words that start with 'm' and ends with 'e':

    When the above code is compiled and executed, it produces the following result:

    Matching words start with 'm' and ends with 'e':
    The Expression: \bm\S*e\b
    make
    maze
    manage
    measure

    Example 3

    When the above code is compiled and executed, it produces the following result:

    Original String: Hello World
    Replacement String: Hello World

    This example replaces extra white space:

    25 - C# ECEPTION HANDLING

    An exception is a problem that arises during the execution of a program. A C# exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero.

    Exceptions provide a way to transfer control from one part of a program to another. C# exception handling is built upon four keywords: try, catch, finally, and throw.

    • try: A try block identifies a block of code for which particular exceptions is activated. It is followed by one or more catch blocks.
    • catch: A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The catch keyword indicates the catching of an exception.
    • finally: The finally block is used to execute a given set of statements, whether an exception is thrown or not thrown. For example, if you open a file, it must be closed whether an exception is raised or not.
    • throw: A program throws an exception when a problem shows up. This is done using a throw keyword.

    Syntax


    Assuming a block raises an exception, a method catches an exception using a combination of the try and catch keywords. A try/catch block is placed around the code that might generate an exception. Code within a try/catch block is referred to as protected code, and the syntax for using try/catch looks like the following:

    You can list down multiple catch statements to catch different type of exceptions in case your try block raises more than one exception in different situations.

    Exception Classes in C#


    C# exceptions are represented by classes. The exception classes in C# are mainly directly or indirectly derived from the System.Exception class. Some of the exception classes derived from the System.Exception class are the System.ApplicationException and System.SystemException classes.

    The System.ApplicationException class supports exceptions generated by application programs.
    Hence the exceptions defined by the programmers should derive from this class.

    The System.SystemException class is the base class for all predefined system exception.

    The following table provides some of the predefined exception classes derived from the Sytem.SystemException class:

    Exception Class Description
    System.IO.IOException Handles I/O errors.
    System.IndexOutOfRangeException Handles errors generated when a method refers to an array index out of range.
    System.ArrayTypeMismatchException Handles errors generated when type is mismatched with the array type.
    System.NullReferenceException Handles errors generated from deferencing a null object.
    System.DivideByZeroException Handles errors generated from dividing a dividend with zero.
    System.InvalidCastException Handles errors generated during typecasting.
    System.OutOfMemoryException Handles errors generated from insufficient free memory.
    System.StackOverflowException Handles errors generated from stack overflow.

    Handling Exceptions


    C# provides a structured solution to the exception handling in the form of try and catch blocks. Using these blocks the core program statements are separated from the error-handling statements.

    These error handling blocks are implemented using the try, catch, and finally keywords. Following is an example of throwing an exception when dividing by zero condition occurs:

    When the above code is compiled and executed, it produces the following result:

    Exception caught: System.DivideByZeroException: Attempted to divide by zero.
    at ...
    Result: 0

    Creating User-Defined Exceptions


    You can also define your own exception. User-defined exception classes are derived from the Exception class. The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    TempIsZeroException: Zero Temperature found

    Throwing Objects


    You can throw an object if it is either directly or indirectly derived from the System.Exception class. You can use a throw statement in the catch block to throw the present object as:

    26 - C# FILE INPUT / OUTPUT

    file is a collection of data stored in a disk with a specific name and a directory path. When a file is opened for reading or writing, it becomes a stream.

    The stream is basically the sequence of bytes passing through the communication path. There are two main streams: the input stream and the output stream. The input stream is used for reading data from file (read operation) and the output stream is used for writing into the file (write operation).

    C# I/O Classes


    The System.IO namespace has various classes that are used for performing numerous operations with files, such as creating and deleting files, reading from or writing to a file, closing a file etc.

    The following table shows some commonly used non-abstract classes in the System.IO namespace:

    I/O Class Description
    BinaryReader Reads primitive data from a binary stream.
    BinaryWriter Writes primitive data in binary format.
    BufferedStream A temporary storage for a stream of bytes.
    Directory Helps in manipulating a directory structure.
    DirectoryInfo Used for performing operations on directories.
    DriveInfo Provides information for the drives.
    File Helps in manipulating files.
    FileInfo Used for performing operations on files.
    FileStream Used to read from and write to any location in a file.
    MemoryStream Used for random access to streamed data stored in memory.
    Path Performs operations on path information.
    StreamReader Used for reading characters from a byte stream.
    StreamWriter Is used for writing characters to a stream.
    StringReader Is used for reading from a string buffer.
    StringWriter Is used for writing into a string buffer.

    The FileStream Class


    The FileStream class in the System.IO namespace helps in reading from, writing to and closing files. This class derives from the abstract class Stream.

    You need to create a FileStream object to create a new file or open an existing file. The syntax for creating a FileStream object is as follows:

    For example, we create a FileStream object F for reading a file named sample.txt as shown:

    Parameter Description
    FileMode

    The FileMode enumerator defines various methods for opening files. The members of the FileMode enumerator are:

    • Append: It opens an existing file and puts cursor at the end of file, or creates the file, if the file does not exist.

    • Create: It creates a new file.

    • CreateNew: It specifies to the operating system, that it should create a new file.

    • Open: It opens an existing file.

    • OpenOrCreate: It specifies to the operating system that it should open a file if it exists, otherwise it should create a new file.

    • Truncate: It opens an existing file and truncates its size to zero bytes.

    FileAccess

    FileAccess enumerators have members: Read, ReadWrite and Write.

    FileShare

    FileShare enumerators have the following members:

    • Inheritable: It allows a file handle to pass inheritance to the child processes

    • None: It declines sharing of the current file

    • Read: It allows opening the file for reading

    • ReadWrite: It allows opening the file for reading and writing

    • Write: It allows opening the file for writing

    Example

    The following program demonstrates use of the FileStream class:

    When the above code is compiled and executed, it produces the following result:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1

    Advanced File Operations in C#


    The preceding example provides simple file operations in C#. However, to utilize the immense powers of C# System.IO classes, you need to know the commonly used properties and methods of these classes.

    Topic and Description

    Reading from and Writing into Text files

    It involves reading from and writing into text files. The StreamReader and StreamWriter class helps to accomplish it.

    Reading from and Writing into Binary files

    It involves reading from and writing into binary files. The BinaryReader and BinaryWriter class helps to accomplish this.

    Manipulating the Windows file system

    It gives a C# programamer the ability to browse and locate Windows files and directories.

    50-game

    VB.NET

    1 - VB.NET OVERVIEW

    Visual Basic .NET (VB.NET) is an object-oriented computer programming language implemented on the .NET Framework. Although it is an evolution of classic Visual Basic language, it is not backwards-compatible with VB6, and any code written in the old version does not compile under VB.NET.

    Like all other .NET languages, VB.NET has complete support for object-oriented concepts. Everything in VB.NET is an object, including all of the primitive types (Short, Integer, Long, String, Boolean, etc.) and user-defined types, events, and even assemblies. All objects inherits from the base class Object.

    VB.NET is implemented by Microsoft's .NET framework. Therefore, it has full access to all the libraries in the .Net Framework. It's also possible to run VB.NET programs on Mono, the open-source alternative to .NET, not only under Windows, but even Linux or Mac OSX.

    The following reasons make VB.Net a widely used professional language:

    • Modern, general purpose.
    • Object oriented.
    • Component oriented.
    • Easy to learn.
    • Structured language.
    • It produces efficient programs.
    • It can be compiled on a variety of computer platforms.
    • Part of .Net Framework.

    Strong Programming Features VB.Net


    VB.Net has numerous strong programming features that make it endearing to multitude of programmers worldwide. Let us mention some of these features:

    • Boolean Conditions
    • Automatic Garbage Collection
    • Standard Library
    • Assembly Versioning
    • Properties and Events
    • Delegates and Events Management
    • Easy-to-use Generics
    • Indexers
    • Conditional Compilation
    • Simple Multithreading

    2 - VB.NET ENVIRONMENT SETUP

    In this chapter, we will discuss the tools available for creating VB.Net applications.

    We have already mentioned that VB.Net is part of .Net framework and used for writing .Net applications. Therefore before discussing the available tools for running a VB.Net program, let us understand how VB.Net relates to the .Net framework.

    The .Net Framework


    The .Net framework is a revolutionary platform that helps you to write the following types of applications:

    • Windows applications
    • Web applications
    • Web services

    The .Net framework applications are multi-platform applications. The framework has been designed in such a way that it can be used from any of the following languages: Visual Basic, C#, C++, Jscript, and COBOL, etc.

    All these languages can access the framework as well as communicate with each other.

    The .Net framework consists of an enormous library of codes used by the client languages like VB.Net. These languages use object-oriented methodology.

    Following are some of the components of the .Net framework:

    • Common Language Runtime (CLR)
    • The .Net Framework Class Library
    • Common Language Specification
    • Common Type System
    • Metadata and Assemblies
    • Windows Forms
    • ASP.Net and ASP.Net AJAX
    • ADO.Net
    • Windows Workflow Foundation (WF)
    • Windows Presentation Foundation
    • Windows Communication Foundation (WCF)
    • LINQ

    Integrated Development Environment (IDE) For VB.Net


    Microsoft provides the following development tools for VB.Net programming:

    • Visual Studio 2010 (VS)
    • Visual Basic 2010 Express (VBE)
    • Visual Web Developer

    The last two are free. Using these tools, you can write all kinds of VB.Net programs from simple command-line applications to more complex applications. Visual Basic Express and Visual Web Developer Express edition are trimmed down versions of Visual Studio and has the same look and feel. They retain most features of Visual Studio. In this tutorial, we have used Visual Basic 2010 Express and Visual Web Developer (for the web programming chapter).

    You can download it from HERE. It gets automatically installed in your machine. Please note that you need an active internet connection for installing the express edition.

    Writing VB.Net Programs on Linux or Mac OS


    Although the.NET Framework runs on the Windows operating system, there are some alternative versions that work on other operating systems. Mono is an open-source version of the .NET Framework which includes a Visual Basic compiler and runs on several operating systems, including various flavors of Linux and Mac OS. The most recent version is VB 2012.

    The stated purpose of Mono is not only to be able to run Microsoft .NET applications cross-platform, but also to bring better development tools to Linux developers. Mono can be run on many operating systems including Android, BSD, iOS, Linux, OS X, Windows, Solaris and UNIX.

    3 - VB PROGRAM STRUCTURE.NET

    Before we study basic building blocks of the VB.Net programming language, let us look a bare minimum VB.Net program structure so that we can take it as a reference in upcoming chapters.

    VB.Net Hello World Example


    A VB.Net program basically consists of the following parts:

    • Namespace declaration
    • A class or module
    • One or more procedures
    • Variables
    • The Main procedure
    • Statements & Expressions
    • Comments

    Let us look at a simple code that would print the words "Hello World":

    When the above code is compiled and executed, it produces the following result:

    Hello, World!

    Let us look various parts of the above program:

    • The first line of the program Imports System is used to include the System namespace in the program.
    • The next line has a Module declaration, the module Module1. VB.Net is completely object oriented, so every program must contain a module of a class that contains the data and procedures that your program uses.
    • Classes or Modules generally would contain more than one procedure. Procedures contain the executable code, or in other words, they define the behavior of the class. A procedure could be any of the following:
      • Function
      • Sub
      • Operator
      • Get
      • Set
      • AddHandler
      • RemoveHandler
      • RaiseEvent
    • The next line( 'This program) will be ignored by the compiler and it has been put to add additional comments in the program.
    • The next line defines the Main procedure, which is the entry point for all VB.Net programs. The Main procedure states what the module or class will do when executed.
    • The Main procedure specifies its behavior with the statement
    • Console.WriteLine("Hello World")
    • WriteLine is a method of the Console class defined in the System namespace. This statement causes the message "Hello, World!" to be displayed on the screen. The last line Console.ReadKey() is for the VS.NET Users. This will prevent the screen from running and closing quickly when the program is launched from Visual Studio .NET.

    Compile & Execute VB.Net Program:


    If you are using Visual Studio.Net IDE, take the following steps:

    • Start Visual Studio.
    • On the menu bar, choose File, New, Project.
    • Choose Visual Basic from templates
    • Choose Console Application.
    • Specify a name and location for your project using the Browse button, and then choose the OK button.
    • The new project appears in Solution Explorer.
    • Write code in the Code Editor.
    • Click the Run button or the F5 key to run the project. A Command Prompt window appears that contains the line Hello World.
    • You can compile a VB.Net program by using the command line instead of the Visual Studio IDE:

    • Open a text editor and add the above mentioned code.
    • Save the file as helloworld.vb
    • Open the command prompt tool and go to the directory where you saved the file.
    • Type vbc helloworld.vb and press enter to compile your code.
    • If there are no errors in your code the command prompt will take you to the next line and would generate helloworld.exe executable file.
    • Next, type helloworld to execute your program.
    • You will be able to see "Hello World" printed on the screen.

    4 - VB.NET BASIC SYNTAX

    VB.Net is an object-oriented programming language. In Object-Oriented Programming methodology, a program consists of various objects that interact with each other by means of actions. The actions that an object may take are called methods. Objects of the same kind are said to have the same type or, more often, are said to be in the same class.

    When we consider a VB.Net program, it can be defined as a collection of objects that communicate via invoking each other's methods. Let us now briefly look into what do class, object, methods and instance variables mean.

    • Object - Objects have states and behaviors. Example: A dog has states - color, name, breed as well as behaviors - wagging, barking, eating, etc. An object is an instance of a class.
    • Class - A class can be defined as a template/blueprint that describes the behaviors/states that objects of its type support.
    • Methods - A method is basically a behavior. A class can contain many methods. It is in methods where the logics are written, data is manipulated and all the actions are executed.
    • Instance Variables - Each object has its unique set of instance variables. An object's state is created by the values assigned to these instance variables.

    A Rectangle Class in VB.Net


    For example, let us consider a Rectangle object. It has attributes like length and width. Depending upon the design, it may need ways for accepting the values of these attributes, calculating area and displaying details.

    Let us look at an implementation of a Rectangle class and discuss VB.Net basic syntax on the basis of our observations in it:

    When the above code is compiled and executed, it produces the following result:

    Length: 4.5
    Width: 3.5
    Area: 15.75

    In previous chapter, we created a Visual Basic module that held the code. Sub Main indicates the entry point of VB.Net program. Here, we are using Class that contains both code and data. You use classes to create objects. For example, in the code, r is a Rectangle object.

    An object is an instance of a class:

    A class may have members that can be accessible from outside class, if so specified. Data members are called fields and procedure members are called methods.

    Shared methods or static methods can be invoked without creating an object of the class. Instance methods are invoked through an object of the class:

    Identifiers


    An identifier is a name used to identify a class, variable, function, or any other user-defined item. The basic rules for naming classes in VB.Net are as follows:

    • A name must begin with a letter that could be followed by a sequence of letters, digits (0 - 9) or underscore. The first character in an identifier cannot be a digit.
    • It must not contain any embedded space or symbol like ? - +! @ # % ^ & * ( ) [ ] { } . ; : " ' / and \. However, an underscore ( _ ) can be used.
    • It should not be a reserved keyword.

    5 - VB.NET DATA TYPES

    Data types refer to an extensive system used for declaring variables or functions of different types. The type of a variable determines how much space it occupies in storage and how the bit pattern stored is interpreted.

    Data Types Available in VB.Net


    VB.Net provides a wide range of data types. The following table shows all the data types available:

    Data Type Storage Allocation Value Range
    Boolean Depends on implementing platform True or False
    Byte 1 byte 0 through 255 (unsigned)
    Char 2 bytes 0 through 65535 (unsigned)
    Date 8 bytes 0:00:00 (midnight) on January 1, 0001 through 11:59:59 PM on December 31, 9999
    Decimal 16 bytes 0 through +/-79,228,162,514,264,337,593,543,950,335 (+/-7.9...E+28) with no decimal point; 0 through +/-7.9228162514264337593543950335 with 28 places to the right of the decimal
    Double 8 bytes

    -1.79769313486231570E+308 through -4.94065645841246544E-324, for negative values

    4.94065645841246544E-324 through 1.79769313486231570E+308, for positive values

    Integer 4 bytes -2,147,483,648 through 2,147,483,647 (signed)
    Long 8 bytes -9,223,372,036,854,775,808 through 9,223,372,036,854,775,807(signed)
    Object

    4 bytes on 32-bit platform

    8 bytes on 64-bit platform

    Any type can be stored in a variable of type Object
    SByte 1 byte -128 through 127 (signed)
    Short 2 bytes -32,768 through 32,767 (signed)
    Single 4 bytes

    -3.4028235E+38 through -1.401298E-45 for negative values;

    1.401298E-45 through 3.4028235E+38 for positive values

    String Depends on implementing platform 0 to approximately 2 billion Unicode characters
    UInteger 4 bytes 0 through 4,294,967,295 (unsigned)
    ULong 8 bytes 0 through 18,446,744,073,709,551,615 (unsigned)
    User-Defined Depends on implementing platform Each member of the structure has a range determined by its data type and independent of the ranges of the other members
    UShort 2 bytes 0 through 65,535 (unsigned)

    Example


    The following example demonstrates use of some of the types:

    When the above code is compiled and executed, it produces the following result:

    The Type Conversion Functions in VB.Net


    VB.Net provides the following in-line type conversion functions:

    S.N Functions & Description
    1

    CBool(expression)

    Converts the expression to Boolean data type.

    2

    CByte(expression)

    Converts the expression to Byte data type.

    3

    CChar(expression)

    Converts the expression to Char data type.

    4

    CDate(expression)

    Converts the expression to Date data type

    5

    CDbl(expression)

    Converts the expression to Double data type.

    6

    CDec(expression)

    Converts the expression to Decimal data type.

    7

    CInt(expression)

    Converts the expression to Integer data type.

    8

    CLng(expression)

    Converts the expression to Long data type.

    9

    CObj(expression)

    Converts the expression to Object type.

    10

    CSByte(expression)

    Converts the expression to SByte data type.

    11

    CShort(expression)

    Converts the expression to Short data type.

    12

    CSng(expression)

    Converts the expression to Single data type.

    13

    CStr(expression)

    Converts the expression to String data type.

    14

    CUInt(expression)

    Converts the expression to UInt data type.

    15

    CULng(expression)

    Converts the expression to ULng data type.

    16

    CUShort(expression)

    Converts the expression to UShort data type.

    Example


    The following example demonstrates some of these functions:

    When the above code is compiled and executed, it produces the following result:

    True
    -1
    True
    12/4/2012
    1
    1

    6 - VB.NET VARIABLES

    A variable is nothing but a name given to a storage area that our programs can manipulate. Each variable in VB.Net has a specific type, which determines the size and layout of the variable's memory; the range of values that can be stored within that memory; and the set of operations that can be applied to the variable.

    We have already discussed various data types. The basic value types provided in VB.Net can be categorized as:

    Type Example
    Integral types SByte, Byte, Short, UShort, Integer, UInteger, Long, ULong and Char
    Floating point types Single and Double
    Decimal types Decimal
    Boolean types True or False values, as assigned
    Date types Date

    VB.Net also allows defining other value types of variable like Enum and reference types of variables like Class. We will discuss date types and Classes in subsequent chapters.

    Variable Declaration in VB.Net


    The Dim statement is used for variable declaration and storage allocation for one or more variables. The Dim statement is used at module, class, structure, procedure or block level.

    Syntax for variable declaration in VB.Net is:

    Where,

    • attributelist is a list of attributes that apply to the variable. Optional.
    • accessmodifier defines the access levels of the variables, it has values as - Public, Protected, Friend, Protected Friend and Private. Optional.
    • Shared declares a shared variable, which is not associated with any specific instance of a class or structure, rather available to all the instances of the class or structure. Optional.
    • Shadows indicate that the variable re-declares and hides an identically named element, or set of overloaded elements, in a base class. Optional.
    • Static indicates that the variable will retain its value, even when the after termination of the procedure in which it is declared. Optional.
    • ReadOnly means the variable can be read, but not written. Optional.
    • WithEvents specifies that the variable is used to respond to events raised by the instance assigned to the variable. Optional.
    • Variablelist provides the list of variables declared.

    Each variable in the variable list has the following syntax and parts:

    Where,

  • variablename: is the name of the variable
  • boundslist: optional. It provides list of bounds of each dimension of an array variable.
  • New: optional. It creates a new instance of the class when the Dim statement runs.
  • datatype: Required if Option Strict is On. It specifies the data type of the variable.
  • initializer: Optional if New is not specified. Expression that is evaluated and assigned to the variable when it is created.
  • Some valid variable declarations along with their definition are shown here:

    Variable Initialization in VB.Net


    Variables are initialized (assigned a value) with an equal sign followed by a constant expression. The general form of initialization is:

    for example,

    You can initialize a variable at the time of declaration as follows:

    Example


    Try the following example which makes use of various types of variables:

    When the above code is compiled and executed, it produces the following result:

    a = 10, b = 20, c = 30

    Accepting Values from User


    The Console class in the System namespace provides a function ReadLine for accepting input from the user and store it into a variable. For example,

    The following example demonstrates it:

    When the above code is compiled and executed, it produces the following result (assume the user inputs Hello World):

    Lvalues and Rvalues


    There are two kinds of expressions:

    • lvalue : An expression that is an lvalue may appear as either the left-hand or right-hand side of an assignment.
    • rvalue : An expression that is an rvalue may appear on the right- but not left-hand side of an assignment.

    Variables are lvalues and so may appear on the left-hand side of an assignment. Numeric literals are rvalues and so may not be assigned and can not appear on the left-hand side. Following is a valid statement:

    But following is not a valid statement and would generate compile-time error:

    7 - VB.NET CONSTANTS

    The constants refer to fixed values that the program may not alter during its execution. These fixed values are also called literals.

    Constants can be of any of the basic data types like an integer constant, a floating constant, a character constant, or a string literal. There are also enumeration constants as well.

    The constants are treated just like regular variables except that their values cannot be modified after their definition.

    An enumeration is a set of named integer constants.

    Declaring Constants


    In VB.Net, constants are declared using the Const statement. The Const statement is used at module, class, structure, procedure, or block level for use in place of literal values.

    The syntax for the Const statement is:

    Where,

    • attributelist: specifies the list of attributes applied to the constants; you can provide multiple attributes separated by commas. Optional.
    • accessmodifier: specifies which code can access these constants. Optional. Values can be either of the: Public, Protected, Friend, Protected Friend, or Private.
    • Shadows: this makes the constant hide a programming element of identical name in a base class. Optional.
    • Constantlist: gives the list of names of constants declared. Required.

    Where, each constant name has the following syntax and parts:

    • constantname: specifies the name of the constant
    • datatype: specifies the data type of the constant
    • initializer: specifies the value assigned to the constant
    • For example,

    Example

    The following example demonstrates declaration and use of a constant value:

    When the above code is compiled and executed, it produces the following result:

    Area = 153.933

    Print and Display Constants in VB.Net


    VB.Net provides the following print and display constants:

    Constant Description
    vbCrLf Carriage return/linefeed character combination.
    vbCr Carriage return character.
    vbLf Linefeed character.
    vbNewLine Newline character.
    vbNullChar Null character.
    vbNullString Not the same as a zero-length string (""); used for calling external procedures.
    vbObjectError Error number. User-defined error numbers should be greater than this value. For example:
    Err.Raise(Number) = vbObjectError + 1000
    vbTab Tab character.
    vbBack Backspace character.

    Declaring Enumerations


    An enumerated type is declared using the Enum statement. The Enum statement declares an enumeration and defines the values of its members. The Enum statement can be used at the module, class, structure, procedure, or block level.

    The syntax for the Enum statement is as follows:

    Where,

    • attributelist: refers to the list of attributes applied to the variable. Optional.
    • asscessmodifier: specifies which code can access these enumerations. Optional. Values can be either of the: Public, Protected, Friend or Private.
    • Shadows: this makes the enumeration hide a programming element of identical name in a base class. Optional.
    • enumerationname: name of the enumeration. Required
    • datatype: specifies the data type of the enumeration and all its members.
    • memberlist: specifies the list of member constants being declared in this statement. Required.

    Each member in the memberlist has the following syntax and parts:

    Where,

    • name: specifies the name of the member. Required.
    • initializer: value assigned to the enumeration member. Optional.

    For example,

    Example

    The following example demonstrates declaration and use of the Enum variable Colors:

    When the above code is compiled and executed, it produces the following result:

    The Color Red is: 1
    The Color Yellow is: 3
    The Color Blue is: 6
    The Color Green is: 4

    8 - VB.NET MODIFIERS

    The modifiers are keywords added with any programming element to give some especial emphasis on how the programming element will behave or will be accessed in the program

    For example, the access modifiers: Public, Private, Protected, Friend, Protected Friend, etc., indicate the access level of a programming element like a variable, constant, enumeration or a class.

    List of Available Modifiers in VB.Net


    The following table provides the complete list of VB.Net modifiers:

    S.N Modifier Description
    1 Ansi Specifies that Visual Basic should marshal all strings to American National Standards Institute (ANSI) values regardless of the name of the external procedure being declared.
    2 Assembly Specifies that an attribute at the beginning of a source file applies to the entire assembly.
    3 Async Indicates that the method or lambda expression that it modifies is asynchronous. Such methods are referred to as async methods. The caller of an async method can resume its work without waiting for the async method to finish.
    4 Auto The charsetmodifier part in the Declare statement supplies the character set information for marshaling strings during a call to the external procedure. It also affects how Visual Basic searches the external file for the external procedure name. The Auto modifier specifies that Visual Basic should marshal strings according to .NET Framework rules.
    5 ByRef Specifies that an argument is passed by reference, i.e., the called procedure can change the value of a variable underlying the argument in the calling code. It is used under the contexts of:
    • Declare Statement
    • Function Statement
    • Sub Statement
    6 ByVal Specifies that an argument is passed in such a way that the called procedure or property cannot change the value of a variable underlying the argument in the calling code. It is used under the contexts of:
    • Declare Statement
    • Function Statement
    • Operator Statement
    • Property Statement
    • Sub Statement
    7 Default Identifies a property as the default property of its class, structure, or interface.
    8 Friend

    Specifies that one or more declared programming elements are accessible from within the assembly that contains their declaration, not only by the component that declares them.

    Friend access is often the preferred level for an application's programming elements, and Friend is the default access level of an interface, a module, a class, or a structure.

    9 In It is used in generic interfaces and delegates.
    10 Iterator Specifies that a function or Get accessor is an iterator. An iterator performs a custom iteration over a collection.
    11 Key The Key keyword enables you to specify behavior for properties of anonymous types.
    12 Module Specifies that an attribute at the beginning of a source file applies to the current assembly module. It is not same as the Module statement.
    13 MustInherit Specifies that a class can be used only as a base class and that you cannot create an object directly from it.
    14 MustOverride Specifies that a property or procedure is not implemented in this class and must be overridden in a derived class before it can be used.
    15 Narrowing Indicates that a conversion operator (CType) converts a class or structure to a type that might not be able to hold some of the possible values of the original class or structure.
    16 NotInheritable Specifies that a class cannot be used as a base class.
    17 NotOverridable Specifies that a property or procedure cannot be overridden in a derived class.
    18 Optional Specifies that a procedure argument can be omitted when the procedure is called.
    19 Out For generic type parameters, the Out keyword specifies that the type is covariant.
    20 Overloads Specifies that a property or procedure redeclares one or more existing properties or procedures with the same name.
    21 Overridable Specifies that a property or procedure can be overridden by an identically named property or procedure in a derived class.
    22 Overrides Specifies that a property or procedure overrides an identically named property or procedure inherited from a base class.
    23 ParamArray ParamArray allows you to pass an arbitrary number of arguments to the procedure. A ParamArray parameter is always declared using ByVal.
    24 Partial Indicates that a class or structure declaration is a partial definition of the class or structure.
    25 Private Specifies that one or more declared programming elements are accessible only from within their declaration context, including from within any contained types.
    26 Protected Specifies that one or more declared programming elements are accessible only from within their own class or from a derived class.
    27 Public Specifies that one or more declared programming elements have no access restrictions.
    28 ReadOnly Specifies that a variable or property can be read but not written.
    29 Shadows Specifies that a declared programming element redeclares and hides an identically named element, or set of overloaded elements, in a base class.
    30 Shared Specifies that one or more declared programming elements are associated with a class or structure at large, and not with a specific instance of the class or structure.
    31 Static Specifies that one or more declared local variables are to continue to exist and retain their latest values after termination of the procedure in which they are declared.
    32 Unicode Specifies that Visual Basic should marshal all strings to Unicode values regardless of the name of the external procedure being declared.
    33 Widening Indicates that a conversion operator (CType) converts a class or structure to a type that can hold all possible values of the original class or structure.
    34 WithEvents Specifies that one or more declared member variables refer to an instance of a class that can raise events.
    35 WriteOnly Specifies that a property can be written but not read.

    9 - VB.NET STATEMENTS

    A statement is a complete instruction in Visual Basic programs. It may contain keywords, operators, variables, literal values, constants and expressions.

    Statements could be categorized as:

    • Declaration statements - these are the statements where you name a variable, constant, or procedure, and can also specify a data type.
    • Executable statements - these are the statements, which initiate actions. These statements can call a method or function, loop or branch through blocks of code or assign values or expression to a variable or constant. In the last case, it is called an Assignment statement.

    Declaration Statements


    The declaration statements are used to name and define procedures, variables, properties, arrays, and constants. When you declare a programming element, you can also define its data type, access level, and scope.

    The programming elements you may declare include variables, constants, enumerations, classes, structures, modules, interfaces, procedures, procedure parameters, function returns, external procedure references, operators, properties, events, and delegates.

    Following are the declaration statements in VB.Net:

    S.N Statements and Description Example
    1

    Dim Statement

    Declares and allocates storage space for one or more variables.

    Dim number As Integer
    Dim quantity As Integer = 100
    Dim message As String = "Hello!"
    
    2 Const Statement
    Declares and defines one or more constants.
    Const maximum As Long = 1000
    Const naturalLogBase As Object 
    = CDec(2.7182818284)
    
    3 Enum Statement
    Declares an enumeration and defines the values of its members.
    Enum CoffeeMugSize
        Jumbo
        ExtraLarge
        Large
        Medium
        Small
    End Enum 
    
    4

    Class Statement

    Declares the name of a class and introduces the definition of the variables, properties, events, and procedures that the class comprises.

    Class Box
    Public length As Double
    Public breadth As Double   
    Public height As Double
    End Class
    5

    Structure Statement

    Declares the name of a structure and introduces the definition of the variables, properties, events, and procedures that the structure comprises.

    Structure Box
    Public length As Double           
    Public breadth As Double   
    Public height As Double
    End Structure
    6

    Module Statement

    Declares the name of a module and introduces the definition of the variables, properties, events, and procedures that the module comprises.

    Public Module myModule
    Sub Main()
    Dim user As String = 
    InputBox("What is your name?") 
    MsgBox("User name is" & user)
    End Sub 
    End Module
    7

    Interface Statement


    Declares the name of an interface and introduces the definitions of the members that the interface comprises.

    Public Interface MyInterface
        Sub doSomething()
    End Interface 
    8

    Function Statement

    Declares the name, parameters, and code that define a Function procedure.

    Function myFunction
    (ByVal n As Integer) As Double 
        Return 5.87 * n
    End Function
    9

    Sub Statement

    Declares the name, parameters, and code that define a Sub procedure.

    Sub mySub(ByVal s As String)
        Return
    End Sub 
    10

    Declare Statement

    Declares a reference to a procedure implemented in an external file.

    Declare Function getUserName
    Lib "advapi32.dll" 
    Alias "GetUserNameA" 
    (
      ByVal lpBuffer As String, 
      ByRef nSize As Integer) As Integer 
    11

    Operator Statement

    Declares the operator symbol, operands, and code that define an operator procedure on a class or structure.

    Public Shared Operator +
    (ByVal x As obj, ByVal y As obj) As obj
            Dim r As New obj
    ' implemention code for r = x + y
            Return r
        End Operator 
    12

    Property Statement

    Declares the name of a property, and the property procedures used to store and retrieve the value of the property.

    ReadOnly Property quote() As String 
        Get 
            Return quoteString
        End Get 
    End Property
    13

    Event Statement

    Declares a user-defined event.

    Public Event Finished()
    14

    Delegate Statement

    Used to declare a delegate.

    Delegate Function MathOperator( 
        ByVal x As Double, 
        ByVal y As Double 
    ) As Double 

    Executable Statements


    An executable statement performs an action. Statements calling a procedure, branching to another place in the code, looping through several statements, or evaluating an expression are executable statements. An assignment statement is a special case of an executable statement.

    Example

    The following example demonstrates a decision making statement:

    When the above code is compiled and executed, it produces the following result:

    a is less than 20;
    value of a is : 10

    10 - VB.NET DIRECTIVES

    The VB.Net compiler directives give instructions to the compiler to preprocess the information before actual compilation starts.

    All these directives begin with #, and only white-space characters may appear before a directive on a line. These directives are not statements.

    VB.Net compiler does not have a separate preprocessor; however, the directives are processed as if there was one. In VB.Net, the compiler directives are used to help in conditional compilation. Unlike C and C++ directives, they are not used to create macros.

    Compiler Directives in VB.Net


    VB.Net provides the following set of compiler directives:

    • The #Const Directive
    • The #ExternalSource Directive
    • The #If...Then...#Else Directives
    • The #Region Directive

    The #Const Directive

    This directive defines conditional compiler constants. Syntax for this directive is:

    Where,

    • constname: specifies the name of the constant. Required.
    • expression: it is either a literal, or other conditional compiler constant, or a combination including any or all arithmetic or logical operators except Is.

    For example,

    Example

    The following code demonstrates a hypothetical use of the directive:

    When the above code is compiled and executed, it produces the following result:

    The #ExternalSource Directive

    This directive is used for indicating a mapping between specific lines of source code and text external to the source. It is used only by the compiler and the debugger has no effect on code compilation.

    This directive allows including external code from an external code file into a source code file.

    Syntax for this directive is:

    The parameters of #ExternalSource directive are the path of external file, line number of the first line, and the line where the error occurred.

    Example

    The following code demonstrates a hypothetical use of the directive:

    When the above code is compiled and executed, it produces the following result:

    This is External Code.
    In Main.

    The #If...Then...#Else Directives

    This directive conditionally compiles selected blocks of Visual Basic code.

    Syntax for this directive is:

    For example,

    Example

    The following code demonstrates a hypothetical use of the directive:

    When the above code is compiled and executed, it produces the following result:

    The #Region Directive

    This directive helps in collapsing and hiding sections of code in Visual Basic files.

    Syntax for this directive is:

    For example,

    11 - VB.NET OPERATORS

    An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. VB.Net is rich in built-in operators and provides following types of commonly used operators:

    • Arithmetic Operators
    • Comparison Operators
    • Logical/Bitwise Operators
    • Bit Shift Operators
    • Assignment Operators
    • Miscellaneous Operators

    This tutorial will explain the most commonly used operators.

    Arithmetic Operators


    Following table shows all the arithmetic operators supported by VB.Net. Assume variable A holds 2 and variable B holds 7, then:

    Operator Description Example
    ^ Raises one operand to the power of another B^A will give 49
    + Adds two operands A + B will give 9
    - Subtracts second operand from the first A - B will give -5
    * Multiplies both operands A * B will give 14
    / Divides one operand by another and returns a floating point result B / A will give 3.5
    \ Divides one operand by another and returns an integer result B \ A will give 3
    MOD Modulus Operator and remainder of after an integer division B MOD A will give 1

    Comparison Operators


    Following table shows all the comparison operators supported by VB.Net. Assume variable A holds 10 and variable B holds 20, then:

    Operator Description Example
    = Checks if the values of two operands are equal or not; if yes, then condition becomes true. (A = B) is not true.
    <> Checks if the values of two operands are equal or not; if values are not equal, then condition becomes true. (A <> B) is true.
    > Checks if the value of left operand is greater than the value of right operand; if yes, then condition becomes true. (A > B) is not true.
    < Checks if the value of left operand is less than the value of right operand; if yes, then condition becomes true. (A < B) is true.
    >= Checks if the value of left operand is greater than or equal to the value of right operand; if yes, then condition becomes true. (A >= B) is not true.
    <= Checks if the value of left operand is less than or equal to the value of right operand; if yes, then condition becomes true. (A <= B) is true.

    Apart from the above, VB.Net provides three more comparison operators, which we will be using in forthcoming chapters; however, we give a brief description here.

    • Is Operator - It compares two object reference variables and determines if two object references refer to the same object without performing value comparisons. If object1 and object2 both refer to the exact same object instance, result is True; otherwise, result is False.
    • IsNot Operator - It also compares two object reference variables and determines if two object references refer to different objects. If object1 and object2 both refer to the exact same object instance, result is False; otherwise, result is True.
    • Like Operator - It compares a string against a pattern.

    Logical/Bitwise Operators


    Following table shows all the logical operators supported by VB.Net. Assume variable A holds Boolean value True and variable B holds Boolean value False, then:

    Operator Description Example
    And It is the logical as well as bitwise AND operator. If both the operands are true, then condition becomes true. This operator does not perform short-circuiting, i.e., it evaluates both the expressions. (A And B) is False.
    Or It is the logical as well as bitwise OR operator. If any of the two operands is true, then condition becomes true. This operator does not perform short-circuiting, i.e., it evaluates both the expressions. (A Or B) is True.
    Not It is the logical as well as bitwise NOT operator. Use to reverses the logical state of its operand. If a condition is true, then Logical NOT operator will make false. Not(A And B) is True.
    Xor It is the logical as well as bitwise Logical Exclusive OR operator. It returns True if both expressions are True or both expressions are False; otherwise it returns False. This operator does not perform short-circuiting, it always evaluates both expressions and there is no short-circuiting counterpart of this operator. A Xor B is True.
    AndAlso It is the logical AND operator. It works only on Boolean data. It performs short-circuiting. (A AndAlso B) is False.
    OrElse It is the logical OR operator. It works only on Boolean data. It performs short-circuiting. (A OrElse B) is True.
    IsFalse It determines whether an expression is False.
    IsTrue It determines whether an expression is True.

    Bit Shift Operators


    We have already discussed the bitwise operators. The bit shift operators perform the shift operations on binary values. Before coming into the bit shift operators, let us understand the bit operations.

    Bitwise operators work on bits and perform bit-by-bit operations. The truth tables for &, |, and ^ are as follows:

    p q p & q p | q p ^ q
    0 0 0 0 0
    0 1 0 1 1
    1 1 1 1 0
    1 0 0 1 1

    Assume if A = 60; and B = 13; now in binary format they will be as follows:

    A = 0011 1100

    B = 0000 1101

    -----------------

    A&B = 0000 1100

    A|B = 0011 1101

    A^B = 0011 0001

    ~A = 1100 0011

    We have seen that the Bitwise operators supported by VB.Net are And, Or, Xor and Not. The Bit shift operators are >> and << for left shift and right shift, respectively.

    Assume that the variable A holds 60 and variable B holds 13, then:

    Operator Description Example
    And Bitwise AND Operator copies a bit to the result if it exists in both operands. (A AND B) will give 12, which is 0000 1100
    Or Binary OR Operator copies a bit if it exists in either operand. (A Or B) will give 61, which is 0011 1101
    Xor Binary XOR Operator copies the bit if it is set in one operand but not both. (A Xor B) will give 49, which is 0011 0001
    Not Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. (Not A ) will give -61, which is 1100 0011 in 2's complement form due to a signed binary number.
    << Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. A << 2 will give 240, which is 1111 0000
    >> Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. A >> 2 will give 15, which is 0000 1111

    Assignment Operators


    There are following assignment operators supported by VB.Net:

    Operator DescriptionExample
    = Simple assignment operator, Assigns values from right side operands to left side operand C = A + B will assign value of A + B into C
    += Add AND assignment operator, It adds right operand to the left operand and assigns the result to left operand C += A is equivalent to C = C + A
    -= Subtract AND assignment operator, It subtracts right operand from the left operand and assigns the result to left operand C -= A is equivalent to C = C - A
    *= Multiply AND assignment operator, It multiplies right operand with the left operand and assigns the result to left operand C *= A is equivalent to C = C * A
    /= Divide AND assignment operator, It divides left operand with the right operand and assigns the result to left operand (floating point division) C /= A is equivalent to C = C / A
    \= Divide AND assignment operator, It divides left operand with the right operand and assigns the result to left operand (Integer division) C \= A is equivalent to C = C \A
    ^= Exponentiation and assignment operator. It raises the left operand to the power of the right operand and assigns the result to left operand. C^=A is equivalent to C = C ^ A
    <<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
    >>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
    &= Concatenates a String expression to a String variable or property and assigns the result to the variable or property.

    Str1 &= Str2 is same as

    Str1 = Str1 & Str2

    Miscellaneous Operators


    There are few other important operators supported by VB.Net.

    Operator Description Example
    AddressOf Returns the address of a procedure.
    AddHandler Button1.Click,
    AddressOf Button1_Click
    Await It is applied to an operand in an asynchronous method or lambda expression to suspend execution of the method until the awaited task completes.
     
    Dim result As res
    = Await AsyncMethodThatReturnsResult()
    Await AsyncMethod()
    GetType It returns a Type object for the specified type. The Type object provides information about the type such as its properties, methods, and events.
    MsgBox(GetType(Integer).ToString())
    Function Expression It declares the parameters and code that define a function lambda expression.
    Dim add5 = Function(num As
     Integer) num + 5
    'prints 10
    Console.WriteLine(add5(5))
    If It uses short-circuit evaluation to conditionally return one of two values. The If operator can be called with three arguments or with two arguments.
    Dim num = 5
    Console.WriteLine(If(num >= 0,
    "Positive", "Negative"))

    Operators Precedence in VB.Net


    Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator:

    For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

    Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.

    Operator Precedence
    Await Highest
    Exponentiation (^)
    Unary identity and negation (+, -)
    Multiplication and floating-point division (*, /)
    Integer division (\)
    Modulus arithmetic (Mod)
    Addition and subtraction (+, -)
    Arithmetic bit shift (<<, >>)
    All comparison operators (=, <>, <, <=, >, >=, Is, IsNot, Like, TypeOf...Is)
    Negation (Not)
    Conjunction (And, AndAlso)
    Inclusive disjunction (Or, OrElse)
    Exclusive disjunction (Xor) Lowest

    12 - VB.NET DECISION MAKING

    Decision making structures require that the programmer specify one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.

    Following is the general form of a typical decision making structure found in most of the programming languages:

    VB.Net provides the following types of decision making statements. Click the following links to check their details.

    Statement Description

    If ... Then statement

    An If...Then statement consists of a boolean expression followed by one or more statements.

    If...Then...Else statement

    An If...Then statement can be followed by an optional Else statement, which executes when the boolean expression is false.

    nested If statements

    You can use one If or Else if statement inside another If or Else if statement(s).

    Select Case statement

    A Select Case statement allows a variable to be tested for equality against a list of values.

    nested Select Case statements

    You can use one select case statement inside another select case statement(s).

    13 - VB.NET LOOPS

    There may be a situation when you need to execute a block of code several number of times. In general, statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.

    Programming languages provide various control structures that allow for more complicated execution paths.

    A loop statement allows us to execute a statement or group of statements multiple times and following is the general form of a loop statement in most of the programming languages:

    VB.Net provides following types of loops to handle looping requirements. Click the following links to check their details.

    Loop Type Description

    Do Loop

    It repeats the enclosed block of statements while a Boolean condition is True or until the condition becomes True. It could be terminated at any time with the Exit Do statement.

    For...Next

    It repeats a group of statements a specified number of times and a loop index counts the number of loop iterations as the loop executes.

    For Each...Next

    It repeats a group of statements for each element in a collection. This loop is used for accessing and manipulating all elements in an array or a VB.Net collection.

    While... End While

    It executes a series of statements as long as a given condition is True.

    With... End With

    It is not exactly a looping construct. It executes a series of statements that repeatedly refer to a single object or structure.

    Nested loops

    You can use one or more loops inside any another While, For or Do loop.

    Loop Control Statements:


    Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.

    VB.Net provides the following control statements. Click the following links to check their details.

    Control Statement Description

    Exit statement

    Terminates the loop or select case statement and transfers execution to the statement immediately following the loop or select case.

    Continue statement

    Causes the loop to skip the remainder of its body and immediately retest its condition prior to reiterating.

    GoTo statement

    Transfers control to the labeled statement. Though it is not advised to use GoTo statement in your program.

    14 - VB.NET STRINGS

    In VB.Net, you can use strings as array of characters, however, more common practice is to use the String keyword to declare a string variable. The string keyword is an alias for the System.String class.

    Creating a String Object


    You can create string object using one of the following methods:

    • By assigning a string literal to a String variable
    • By using a String class constructor
    • By using the string concatenation operator (+)
    • By retrieving a property or calling a method that returns a string
    • By calling a formatting method to convert a value or object to its string representation

    The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Full Name: Rowan Atkinson
    Greetings: Hello
    Message: Hello From Tutorials Point
    Message: Message sent at 5:58 PM on Wednesday, December 12, 2012

    Properties of the String Class


    The String class has the following two properties:

    S.N Property Name & Description
    1

    Chars

    Gets the Char object at a specified position in the current String object.

    2

    Length

    Gets the number of characters in the current String object.

    Methods of the String Class


    The String class has numerous methods that help you in working with the string objects. The following table provides some of the most commonly used methods:

    S.N Method Name & Description
    1

    Public Shared Function Compare ( strA As String, strB As String ) As Integer

    Compares two specified string objects and returns an integer that indicates their relative position in the sort order.

    2

    Public Shared Function Compare ( strA As String, strB As String, ignoreCase As Boolean ) As Integer

    Compares two specified string objects and returns an integer that indicates their relative position in the sort order. However, it ignores case if the Boolean parameter is true.

    3

    Public Shared Function Concat ( str0 As String, str1 As String ) As String

    Concatenates two string objects.

    4

    Public Shared Function Concat ( str0 As String, str1 As String, str2 As String ) As String

    Concatenates three string objects.

    5

    Public Shared Function Concat ( str0 As String, str1 As String, str2 As String, str3 As String ) As String

    Concatenates four string objects.

    6

    Public Function Contains ( value As String ) As Boolean

    Returns a value indicating whether the specified string object occurs within this string.

    7

    Public Shared Function Copy ( str As String ) As String

    Creates a new String object with the same value as the specified string.

    8

    pPublic Sub CopyTo ( sourceIndex As Integer, destination As Char(), destinationIndex As Integer, count As Integer )

    Copies a specified number of characters from a specified position of the string object to a specified position in an array of Unicode characters.

    9

    Public Function EndsWith ( value As String ) As Boolean

    Determines whether the end of the string object matches the specified string.

    10

    Public Function Equals ( value As String ) As Boolean

    Determines whether the current string object and the specified string object have the same value.

    11

    Public Shared Function Equals ( a As String, b As String ) As Boolean

    Determines whether two specified string objects have the same value.

    12

    Public Shared Function Format ( format As String, arg0 As Object ) As String

    Replaces one or more format items in a specified string with the string representation of a specified object.

    13

    Public Function IndexOf ( value As Char ) As Integer

    Returns the zero-based index of the first occurrence of the specified Unicode character in the current string.

    14

    Public Function IndexOf ( value As String ) As Integer

    Returns the zero-based index of the first occurrence of the specified string in this instance.

    15

    Public Function IndexOf ( value As Char, startIndex As Integer ) As Integer

    Returns the zero-based index of the first occurrence of the specified Unicode character in this string, starting search at the specified character position.

    16

    Public Function IndexOf ( value As String, startIndex As Integer ) As Integer

    Returns the zero-based index of the first occurrence of the specified string in this instance, starting search at the specified character position.

    17

    Public Function IndexOfAny ( anyOf As Char() ) As Integer

    Returns the zero-based index of the first occurrence in this instance of any character in a specified array of Unicode characters.

    18

    Public Function IndexOfAny ( anyOf As Char(), startIndex As Integer ) As Integer

    Returns the zero-based index of the first occurrence in this instance of any character in a specified array of Unicode characters, starting search at the specified character position.

    19

    Public Function Insert ( startIndex As Integer, value As String ) As String

    Returns a new string in which a specified string is inserted at a specified index position in the current string object.

    20

    Public Shared Function IsNullOrEmpty ( value As String ) As Boolean

    Indicates whether the specified string is null or an Empty string.

    21

    Public Shared Function Join ( separator As String, ParamArray value As String() ) As String

    Concatenates all the elements of a string array, using the specified separator between each element.

    22

    Public Shared Function Join ( separator As String, value As String(), startIndex As Integer, count As Integer ) As String

    Concatenates the specified elements of a string array, using the specified separator between each element.

    23

    Public Function LastIndexOf ( value As Char ) As Integer

    Returns the zero-based index position of the last occurrence of the specified Unicode character within the current string object.

    24

    Public Function LastIndexOf ( value As String ) As Integer

    Returns the zero-based index position of the last occurrence of a specified string within the current string object.

    25

    Public Function Remove ( startIndex As Integer ) As String

    Removes all the characters in the current instance, beginning at a specified position and continuing through the last position, and returns the string.

    26

    Public Function Remove ( startIndex As Integer, count As Integer ) As String

    Removes the specified number of characters in the current string beginning at a specified position and returns the string.

    27

    Public Function Replace ( oldChar As Char, newChar As Char ) As String

    Replaces all occurrences of a specified Unicode character in the current string object with the specified Unicode character and returns the new string.

    28

    Public Function Replace ( oldValue As String, newValue As String ) As String

    Replaces all occurrences of a specified string in the current string object with the specified string and returns the new string.

    29

    Public Function Split ( ParamArray separator As Char() ) As String()

    Returns a string array that contains the substrings in the current string object, delimited by elements of a specified Unicode character array.

    30

    Public Function Split ( separator As Char(), count As Integer ) As String()

    Returns a string array that contains the substrings in the current string object, delimited by elements of a specified Unicode character array. The int parameter specifies the maximum number of substrings to return.

    31

    Public Function StartsWith ( value As String ) As Boolean

    Determines whether the beginning of this string instance matches the specified string.

    32

    Public Function ToCharArray As Char()

    Returns a Unicode character array with all the characters in the current string object.

    33

    Public Function ToCharArray ( startIndex As Integer, length As Integer ) As Char()

    Returns a Unicode character array with all the characters in the current string object, starting from the specified index and up to the specified length.

    34

    Public Function ToLower As String

    Returns a copy of this string converted to lowercase.

    35

    Public Function ToUpper As String

    Returns a copy of this string converted to uppercase.

    36

    Public Function Trim As String

    Removes all leading and trailing white-space characters from the current String object.

    The above list of methods is not exhaustive, please visit MSDN library for the complete list of methods and String class constructors.

    Examples:

    The following example demonstrates some of the methods mentioned above:

    Comparing Strings:

    When the above code is compiled and executed, it produces the following result:

    This is test and This is text are not equal.

    String Contains String:

    When the above code is compiled and executed, it produces the following result:

    The sequence 'test' was found.

    Getting a Substring:

    When the above code is compiled and executed, it produces the following result:

    Last night I dreamt of San Pedro
    San Pedro.

    Joining Strings:

    When the above code is compiled and executed, it produces the following result:

    Down the way where the nights are gay And the sun shines daily on the mountain top I took a trip on a sailing ship And when I reached Jamaica I made a stop

    15 - VB.NET DATE AND TIME

    Most of the softwares you write need implementing some form of date functions returning current date and time. Dates are so much part of everyday life that it becomes easy to work with them without thinking. VB.Net also provides powerful tools for date arithmetic that makes manipulating dates easy.

    The Date data type contains date values, time values, or date and time values. The default value of Date is 0:00:00 (midnight) on January 1, 0001. The equivalent .NET data type is System.DateTime.

    The DateTime structure represents an instant in time, typically expressed as a date and time of day

    You can also get the current date and time from the DateAndTime class.

    The DateAndTime module contains the procedures and properties used in date and time operations.

    'Declaration
    <StandardModuleAttribute> _
    Public NotInheritable Class DateAndTime

    Note:

    Both the DateTime structure and the DateAndTime module contain properties like Now and Today, so often beginners find it confusing. The DateAndTime class belongs to the Microsoft.VisualBasic namespace and the DateTime structure belongs to the System namespace.
    Therefore, using the later would help you in porting your code to another .Net language like C#. However, the DateAndTime class/module contains all the legacy date functions available in Visual Basic.

    Properties and Methods of the DateTime Structure


    The following table lists some of the commonly used properties of the DateTime Structure:

    S.N Property Description
    1 Date Gets the date component of this instance.
    2 Day Gets the day of the month represented by this instance.
    3 DayOfWeek Gets the day of the week represented by this instance.
    4 DayOfYear Gets the day of the year represented by this instance.
    5 Hour Gets the hour component of the date represented by this instance.
    6 Kind Gets a value that indicates whether the time represented by this instance is based on local time, Coordinated Universal Time (UTC), or neither.
    7 Millisecond Gets the milliseconds component of the date represented by this instance.
    8 Minute Gets the minute component of the date represented by this instance.
    9 Month Gets the month component of the date represented by this instance.
    10 Now Gets a DateTime object that is set to the current date and time on this computer, expressed as the local time.
    11 Second Gets the seconds component of the date represented by this instance.
    12 Ticks Gets the number of ticks that represent the date and time of this instance.
    13 TimeOfDay Gets the time of day for this instance.
    14 Today Gets the current date.
    15 UtcNow Gets a DateTime object that is set to the current date and time on this computer, expressed as the Coordinated Universal Time (UTC).
    16 Year Gets the year component of the date represented by this instance.

    The following table lists some of the commonly used methods of the DateTime structure:

    S.N Method Name & Description
    1

    Public Function Add (value As TimeSpan) As DateTime

    Returns a new DateTime that adds the value of the specified TimeSpan to the value of this instance.

    2

    Public Function AddDays ( value As Double) As DateTime

    Returns a new DateTime that adds the specified number of days to the value of this instance.

    3

    Public Function AddHours (value As Double) As DateTime

    Returns a new DateTime that adds the specified number of hours to the value of this instance.

    4

    Public Function AddMinutes (value As Double) As DateTime

    Returns a new DateTime that adds the specified number of minutes to the value of this instance.

    5

    Public Function AddMonths (months As Integer) As DateTime

    Returns a new DateTime that adds the specified number of months to the value of this instance.

    6

    Public Function AddSeconds (value As Double) As DateTime

    Returns a new DateTime that adds the specified number of seconds to the value of this instance.

    7

    Public Function AddYears (value As Integer ) As DateTime

    Returns a new DateTime that adds the specified number of years to the value of this instance.

    8

    Public Shared Function Compare (t1 As DateTime,t2 As DateTime) As Integer

    Compares two instances of DateTime and returns an integer that indicates whether the first instance is earlier than, the same as, or later than the second instance.

    9

    Public Function CompareTo (value As DateTime) As Integer

    Compares the value of this instance to a specified DateTime value and returns an integer that indicates whether this instance is earlier than, the same as, or later than the specified DateTime value.

    10

    Public Function Equals (value As DateTime) As Boolean

    Returns a value indicating whether the value of this instance is equal to the value of the specified DateTime instance.

    11

    Public Shared Function Equals (t1 As DateTime, t2 As DateTime) As Boolean

    Returns a value indicating whether two DateTime instances have the same date and time value.

    12

    Public Overrides Function ToString As String

    Converts the value of the current DateTime object to its equivalent string representation.

    The above list of methods is not exhaustive, please visit Microsoft documentation for the complete list of methods and properties of the DateTime structure.

    Creating a DateTime Object


    You can create a DateTime object in one of the following ways:

    • By calling a DateTime constructor from any of the overloaded DateTime constructors.


    • By assigning the DateTime object a date and time value returned by a property or method.


    • By parsing the string representation of a date and time value.


    • By calling the DateTime structure's implicit default constructor.

    The following example demonstrates this:

    When the above code was compiled and executed, it produces the following result:

    12/16/2012 12:00:00 PM
    12/16/2012 12:00:52 PM
    12/12/2012 10:22:50 PM
    12/12/2012 12:00:00 PM

    Getting the Current Date and Time:


    The following programs demonstrate how to get the current date and time in VB.Net:

    Current Time:

    When the above code is compiled and executed, it produces the following result:

    Current Time: 11 :05 :32 AM

    Current Date:

    When the above code is compiled and executed, it produces the following result:

    Today is: 12/11/2012 12:00:00 AM

    Formatting Date


    A Date literal should be enclosed within hash signs (# #), and specified in the format M/d/yyyy, for example #12/16/2012#. Otherwise, your code may change depending on the locale in which your application is running.

    For example, you specified Date literal of #2/6/2012# for the date February 6, 2012. It is alright for the locale that uses mm/dd/yyyy format. However, in a locale that uses dd/mm/yyyy format, your literal would compile to June 2, 2012. If a locale uses another format say, yyyy/mm/dd, the literal would be invalid and cause a compiler error.

    To convert a Date literal to the format of your locale or to a custom format, use the Format function of String class, specifying either a predefined or user-defined date format.

    The following example demonstrates this.

    When the above code is compiled and executed, it produces the following result:

    India Wins Freedom:
    Format 'd:' 8/15/1947
    Format 'D:' Friday, August 15, 1947
    Format 't:' 12:00 AM
    Format 'T:' 12:00:00 AM
    Format 'f:' Friday, August 15, 1947 12:00 AM
    Format 'F:' Friday, August 15, 1947 12:00:00 AM
    Format 'g:' 8/15/1947 12:00 AM
    Format 'G:' 8/15/1947 12:00:00 AM
    Format 'M:' 8/15/1947 August 15
    Format 'R:' Fri, 15 August 1947 00:00:00 GMT
    Format 'y:' August, 1947

    Predefined Date/Time Formats


    The following table identifies the predefined date and time format names. These may be used by name as the style argument for the Format function:

    Format Description
    General Date, or G Displays a date and/or time. For example, 1/12/2012 07:07:30 AM.
    Long Date,Medium Date, or D Displays a date according to your current culture's long date format. For example, Sunday, December 16, 2012.
    Short Date, or d Displays a date using your current culture's short date format. For example, 12/12/2012.
    Long Time,Medium Time, orT Displays a time using your current culture's long time format; typically includes hours, minutes, seconds. For example, 01:07:30 AM.
    Short Time or t Displays a time using your current culture's short time format. For example, 11:07 AM.
    f Displays the long date and short time according to your current culture's format. For example, Sunday, December 16, 2012 12:15 AM.
    F Displays the long date and long time according to your current culture's format. For example, Sunday, December 16, 2012 12:15:31 AM.
    g Displays the short date and short time according to your current culture's format. For example, 12/16/2012 12:15 AM.
    M, m Displays the month and the day of a date. For example, December 16.
    R, r Formats the date according to the RFC1123Pattern property.
    s Formats the date and time as a sortable index. For example, 2012-12-16T12:07:31.
    u Formats the date and time as a GMT sortable index. For example, 2012-12-16 12:15:31Z.
    U Formats the date and time with the long date and long time as GMT. For example, Sunday, December 16, 2012 6:07:31 PM.
    Y, y Formats the date as the year and month. For example, December, 2012.

    For other formats like user-defined formats, please consult Microsoft Documentation.

    Properties and Methods of the DateAndTime Class


    The following table lists some of the commonly used properties of the DateAndTime Class:

    S.N Property Description
    1 Date Returns or sets a String value representing the current date according to your system.
    2 Now Returns a Date value containing the current date and time according to your system.
    3 TimeOfDay Returns or sets a Date value containing the current time of day according to your system.
    4 Timer Returns a Double value representing the number of seconds elapsed since midnight.
    5 TimeString Returns or sets a String value representing the current time of day according to your system.
    6 Today Gets the current date.

    The following table lists some of the commonly used methods of the DateAndTime class:

    S.N Method Name & Description
    1

    Public Shared Function DateAdd (Interval As DateInterval, Number As Double, DateValue As DateTime) As DateTime

    Returns a Date value containing a date and time value to which a specified time interval has been added.

    2

    Public Shared Function DateAdd (Interval As String,Number As Double,DateValue As Object ) As DateTime

    Returns a Date value containing a date and time value to which a specified time interval has been added.

    3

    Public Shared Function DateDiff (Interval As DateInterval, Date1 As DateTime, Date2 As DateTime, DayOfWeek As FirstDayOfWeek, WeekOfYear As FirstWeekOfYear ) As Long

    Returns a Long value specifying the number of time intervals between two Date values.

    4

    Public Shared Function DatePart (Interval As DateInterval, DateValue As DateTime, FirstDayOfWeekValue As FirstDayOfWeek, FirstWeekOfYearValue As FirstWeekOfYear ) As Integer

    Returns an Integer value containing the specified component of a given Date value.

    5

    Public Shared Function Day (DateValue As DateTime) As Integer

    Returns an Integer value from 1 through 31 representing the day of the month.

    6 Public Shared Function Hour (TimeValue As DateTime) As Integer

    Returns an Integer value from 0 through 23 representing the hour of the day.

    7

    Public Shared Function Minute (TimeValue As DateTime) As Integer

    Returns an Integer value from 0 through 59 representing the minute of the hour.

    8

    Public Shared Function Month (DateValue As DateTime) As Integer

    Returns an Integer value from 1 through 12 representing the month of the year.

    9

    Public Shared Function MonthName (Month As Integer, Abbreviate As Boolean) As String

    Returns a String value containing the name of the specified month.

    10

    Public Shared Function Second (TimeValue As DateTime) As Integer

    Returns an Integer value from 0 through 59 representing the second of the minute.

    11

    Public Overridable Function ToString As String

    Returns a string that represents the current object.

    12

    Public Shared Function Weekday (DateValue As DateTime, DayOfWeek As FirstDayOfWeek) As Integer

    Returns an Integer value containing a number representing the day of the week.

    13

    Public Shared Function WeekdayName (Weekday As Integer, Abbreviate As Boolean, FirstDayOfWeekValue As FirstDayOfWeek) As String

    Returns a String value containing the name of the specified weekday.

    14

    Public Shared Function Year (DateValue As DateTime) As Integer

    Returns an Integer value from 1 through 9999 representing the year.

    The above list is not exhaustive. For complete list of properties and methods of the DateAndTime class, please consult Microsoft Documentation.

    The following program demonstrates some of these and methods:

    When the above code is compiled and executed, it produces the following result:

    7/27/1998 12:00:00 AM
    27
    7
    July

    16 - VB.NET ARRAYS

    An array stores a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.

    All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.

    Creating Arrays in VB.Net


    To declare an array in VB.Net, you use the Dim statement. For example,

    You can also initialize the array elements while declaring the array. For example,

    The elements in an array can be stored and accessed by using the index of the array. The following program demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Element(0) = 100
    Element(1) = 101
    Element(2) = 102
    Element(3) = 103
    Element(4) = 104
    Element(5) = 105
    Element(6) = 106
    Element(7) = 107
    Element(8) = 108
    Element(9) = 109
    Element(10) = 110

    Dynamic Arrays


    Dynamic arrays are arrays that can be dimensioned and re-dimensioned as par the need of the program. You can declare a dynamic array using the ReDim statement.

    Syntax for ReDim statement:

    Where,

    • The Preserve keyword helps to preserve the data in an existing array, when you resize it.
    • arrayname is the name of the array to re-dimension.
    • subscripts specifies the new dimension.

    When the above code is compiled and executed, it produces the following result:

    0 85
    1 75
    2 90
    3 80
    4 76
    5 92
    6 99
    7 79
    8 75
    9 0
    10 0

    Multi-Dimensional Arrays


    VB.Net allows multidimensional arrays. Multidimensional arrays are also called rectangular arrays.

    You can declare a 2-dimensional array of strings as:

    or, a 3-dimensional array of Integer variables:

    The following program demonstrates creating and using a 2-dimensional array:

    When the above code is compiled and executed, it produces the following result:

    a[0,0]: 0
    a[0,1]: 0
    a[1,0]: 1
    a[1,1]: 2
    a[2,0]: 2
    a[2,1]: 4
    a[3,0]: 3
    a[3,1]: 6
    a[4,0]: 4
    a[4,1]: 8

    Jagged Array


    A Jagged array is an array of arrays. The follwoing code shows declaring a jagged array named scores of Integers:

    The following example illustrates using a jagged array:

    When the above code is compiled and executed, it produces the following result:

    a[0][0]: 0
    a[0][1]: 0
    a[1][0]: 1
    a[1][1]: 2
    a[2][0]: 2
    a[2][1]: 4
    a[3][0]: 3
    a[3][1]: 6
    a[4][0]: 4
    a[4][1]: 8

    The Array Class


    The Array class is the base class for all the arrays in VB.Net. It is defined in the System namespace. The Array class provides various properties and methods to work with arrays.

    Properties of the Array Class

    The following table provides some of the most commonly used properties of the Array class:

    S.N Property Name & Description
    1

    IsFixedSize

    Gets a value indicating whether the Array has a fixed size.

    2

    IsReadOnly

    Gets a value indicating whether the Array is read-only.

    3

    Length

    Gets a 32-bit integer that represents the total number of elements in all the dimensions of the Array.

    4

    LongLength

    Gets a 64-bit integer that represents the total number of elements in all the dimensions of the Array.

    5

    Rank

    Gets the rank (number of dimensions) of the Array.

    Methods of the Array Class

    The following table provides some of the most commonly used methods of the Array class:

    S.N Method Name & Description
    1

    Public Shared Sub Clear (array As Array, index As Integer, length As Integer)

    Sets a range of elements in the Array to zero, to false, or to null, depending on the element type.

    2

    Public Shared Sub Copy (sourceArray As Array, destinationArray As Array, length As Integer)

    Copies a range of elements from an Array starting at the first element and pastes them into another Array starting at the first element. The length is specified as a 32-bit integer.

    3

    Public Sub CopyTo (array As Array, index As Integer)

    Copies all the elements of the current one-dimensional Array to the specified one-dimensional Array starting at the specified destination Array index. The index is specified as a 32-bit integer.

    4

    Public Function GetLength (dimension As Integer) As Integer

    Gets a 32-bit integer that represents the number of elements in the specified dimension of the Array.

    5

    Public Function GetLongLength (dimension As Integer) As Long

    Gets a 64-bit integer that represents the number of elements in the specified dimension of the Array.

    6

    Public Function GetLowerBound (dimension As Integer) As Integer

    Gets the lower bound of the specified dimension in the Array.

    7

    Public Function GetType As Type

    Gets the Type of the current instance (Inherited from Object).

    8

    Public Function GetUpperBound (dimension As Integer) As Integer

    Gets the upper bound of the specified dimension in the Array.

    9

    Public Function GetValue (index As Integer) As Object

    Gets the value at the specified position in the one-dimensional Array. The index is specified as a 32-bit integer.

    10

    Public Shared Function IndexOf (array As Array,value As Object) As Integer

    Searches for the specified object and returns the index of the first occurrence within the entire one-dimensional Array.

    11

    Public Shared Sub Reverse (array As Array)

    Reverses the sequence of the elements in the entire one-dimensional Array.

    12

    Public Sub SetValue (value As Object, index As Integer)

    Sets a value to the element at the specified position in the one-dimensional Array. The index is specified as a 32-bit integer.

    13

    Public Shared Sub Sort (array As Array)

    Sorts the elements in an entire one-dimensional Array using the IComparable implementation of each element of the Array.

    14

    Public Overridable Function ToString As String

    Returns a string that represents the current object (Inherited from Object).

    For complete list of Array class properties and methods, please consult Microsoft documentation.

    Example

    The following program demonstrates use of some of the methods of the Array class:

    When the above code is compiled and executed, it produces the following result:

    Original Array: 34 72 13 44 25 30 10
    Reversed Array: 10 30 25 44 13 72 34
    Sorted Array: 10 13 25 30 34 44 72

    17 - VB.NET COLLECTIONS

    Collection classes are specialized classes for data storage and retrieval. These classes provide support for stacks, queues, lists, and hash tables. Most collection classes implement the same interfaces.

    Collection classes serve various purposes, such as allocating memory dynamically to elements and accessing a list of items on the basis of an index, etc. These classes create collections of objects of the Object class, which is the base class for all data types in VB.Net.

    Various Collection Classes and Their Usage


    The following are the various commonly used classes of the System.Collection namespace. Click the following links to check their details.

    Class Description and Useage

    ArrayList

    It represents ordered collection of an object that can be indexed individually.

    It is basically an alternative to an array. However, unlike array, you can add and remove items from a list at a specified position using an index and the array resizes itself automatically. It also allows dynamic memory allocation, add, search and sort items in the list.

    Hashtable

    It uses a key to access the elements in the collection.

    A hash table is used when you need to access elements by using key, and you can identify a useful key value. Each item in the hash table has a key/value pair. The key is used to access the items in the collection.

    SortedList

    It uses a key as well as an index to access the items in a list.

    A sorted list is a combination of an array and a hash table. It contains a list of items that can be accessed using a key or an index. If you access items using an index, it is an ArrayList, and if you access items using a key, it is a Hashtable. The collection of items is always sorted by the key value.

    Stack

    It represents a last-in, first out collection of object.

    It is used when you need a last-in, first-out access of items. When you add an item in the list, it is called pushing the item, and when you remove it, it is called popping the item.

    Queue

    It represents a first-in, first out collection of object.

    It is used when you need a first-in, first-out access of items. When you add an item in the list, it is called enqueue, and when you remove an item, it is called deque.

    BitArray

    It represents an array of the binary representation using the values 1 and 0.

    It is used when you need to store the bits but do not know the number of bits in advance. You can access items from the BitArray collection by using an integer index, which starts from zero.

    18 - VB.NET FUNCTIONS

    A procedure is a group of statements that together perform a task when called. After the procedure is executed, the control returns to the statement calling the procedure. VB.Net has two types of procedures:

    • Functions
    • Sub procedures or Subs

    Functions return a value, whereas Subs do not return a value.

    Defining a Function


    The Function statement is used to declare the name, parameter and the body of a function. The syntax for the Function statement is:

    Where,

    • Modifiers: specify the access level of the function; possible values are: Public, Private, Protected, Friend, Protected Friend and information regarding overloading, overriding, sharing, and shadowing.
    • FunctionName: indicates the name of the function
    • ParameterList: specifies the list of the parameters
    • ReturnType: specifies the data type of the variable the
    • function returns

      Example

      Following code snippet shows a function FindMax that takes two integer values and returns the larger of the two.

    Function Returning a Value


    In VB.Net, a function can return a value to the calling code in two ways:

    • By using the return statement
    • By assigning the value to the function name

    The following example demonstrates using the FindMax function:

    When the above code is compiled and executed, it produces the following result:

    Max value is : 200

    Recursive Function


    A function can call itself. This is known as recursion. Following is an example that calculates factorial for a given number using a recursive function:

    When the above code is compiled and executed, it produces the following result:

    Factorial of 6 is: 720
    Factorial of 7 is: 5040
    Factorial of 8 is: 40320

    Param Arrays


    At times, while declaring a function or sub procedure, you are not sure of the number of arguments passed as a parameter. VB.Net param arrays (or parameter arrays) come into help at these times.

    The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    The sum is: 2938

    Passing Arrays as Function Arguments


    You can pass an array as a function argument in VB.Net. The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Average value is: 214.4

    19 - VB.NET SUB PROCEDURES

    As we mentioned in the previous chapter, Sub procedures are procedures that do not return any value. We have been using the Sub procedure Main in all our examples. We have been writing console applications so far in these tutorials. When these applications start, the control goes to the Main Sub procedure, and it in turn, runs any other statements constituting the body of the program.

    Defining Sub Procedures


    The Sub statement is used to declare the name, parameter and the body of a sub procedure. The syntax for the Sub statement is:

    Where,

    • Modifiers: specify the access level of the procedure; possible values are: Public, Private, Protected, Friend, Protected Friend and information regarding overloading, overriding, sharing, and shadowing.
    • SubName: indicates the name of the Sub
    • ParameterList: specifies the list of the parameters

    Example

    The following example demonstrates a Sub procedure CalculatePay that takes two parameters hours and wages and displays the total pay of an employee:

    When the above code is compiled and executed, it produces the following result:

    Total Pay: $250.00
    Total Pay: $800.00
    Total Pay: $825.00

    Passing Parameters by Value


    This is the default mechanism for passing parameters to a method. In this mechanism, when a method is called, a new storage location is created for each value parameter. The values of the actual parameters are copied into them. So, the changes made to the parameter inside the method have no effect on the argument.

    In VB.Net, you declare the reference parameters using the ByRef keyword. The following example demonstrates the concept:

    When the above code is compiled and executed, it produces the following result:

    Before swap, value of a :100
    Before swap, value of b :200
    After swap, value of a :100
    After swap, value of b :200

    It shows that there is no change in the values though they had been changed inside the function.

    Passing Parameters by Reference


    A reference parameter is a reference to a memory location of a variable. When you pass parameters by reference, unlike value parameters, a new storage location is not created for these parameters. The reference parameters represent the same memory location as the actual parameters that are supplied to the method.

    In VB.Net, you declare the reference parameters using the ByRef keyword. The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Before swap, value of a : 100
    Before swap, value of b : 200
    After swap, value of a : 200
    After swap, value of b : 100

    20 - VB.NET CLASSES & OBJECTS

    When you define a class, you define a blueprint for a data type. This doesn't actually define any data, but it does define what the class name means, that is, what an object of the class will consist of and what operations can be performed on such an object.

    Objects are instances of a class. The methods and variables that constitute a class are called members of the class.

    Class Definition


    A class definition starts with the keyword Class followed by the class name; and the class body, ended by the End Class statement. Following is the general form of a class definition:

    Where,

    • attributelist is a list of attributes that apply to the class. Optional.
    • accessmodifier defines the access levels of the class, it has values as - Public, Protected, Friend, Protected Friend and Private. Optional.
    • Shadows indicate that the variable re-declares and hides an identically named element, or set of overloaded elements, in a base class. Optional.
    • MustInherit specifies that the class can be used only as a base class and that you cannot create an object directly from it, i.e., an abstract class. Optional.
    • NotInheritable specifies that the class cannot be used as a base class.
    • Partial indicates a partial definition of the class.
    • Inherits specifies the base class it is inheriting from.
    • Implements specifies the interfaces the class is inheriting from.

    The following example demonstrates a Box class, with three data members, length, breadth and height:

    When the above code is compiled and executed, it produces the following result:

    Volume of Box1 : 210
    Volume of Box2 : 1560

    Member Functions and Encapsulation


    A member function of a class is a function that has its definition or its prototype within the class definition like any other variable. It operates on any object of the class of which it is a member and has access to all the members of a class for that object.

    Member variables are attributes of an object (from design perspective) and they are kept private to implement encapsulation. These variables can only be accessed using the public member functions.

    Let us put above concepts to set and get the value of different class members in a class:

    When the above code is compiled and executed, it produces the following result:

    Volume of Box1 : 210
    Volume of Box2 : 1560

    Constructors and Destructors


    When the above code is compiled and executed, it produces the following result:

    Object is being created
    Length of line : 6

    A default constructor does not have any parameter, but if you need, a constructor can have parameters. Such constructors are called parameterized constructors. This technique helps you to assign initial value to an object at the time of its creation as shown in the following example:

    When the above code is compiled and executed, it produces the following result:

    Object is being created, length = 10
    Length of line set by constructor : 10
    Length of line set by setLength : 6

    A destructor is a special member Sub of a class that is executed whenever an object of its class goes out of scope.

    A destructor has the name Finalize and it can neither return a value nor can it take any parameters. Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories, etc.

    Destructors cannot be inherited or overloaded.

    Following example explains the concept of destructor:

    When the above code is compiled and executed, it produces the following result:

    Object is being created
    Length of line : 6
    Object is being deleted

    Shared Members of a VB.Net Class


    We can define class members as static using the Shared keyword. When we declare a member of a class as Shared, it means no matter how many objects of the class are created, there is only one copy of the member.

    The keyword Shared implies that only one instance of the member exists for a class. Shared variables are used for defining constants because their values can be retrieved by invoking the class without creating an instance of it.

    Shared variables can be initialized outside the member function or class definition. You can also initialize Shared variables inside the class definition.

    You can also declare a member function as Shared. Such functions can access only Shared variables. The Shared functions exist even before the object is created.

    The following example demonstrates the use of shared members:

    When the above code is compiled and executed, it produces the following result:

    Value of variable num: 3

    Inheritance


    One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class which makes it easier to create and maintain an application. This also provides an opportunity to reuse the code functionality and fast implementation time.

    When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class.

    Base & Derived Classes:


    A class can be derived from more than one class or interface, which means that it can inherit data and functions from multiple base classes or interfaces.

    The syntax used in VB.Net for creating derived classes is as follows:

    Consider a base class Shape and its derived class Rectangle:

    When the above code is compiled and executed, it produces the following result:

    Total area: 35

    Base Class Initialization


    The derived class inherits the base class member variables and member methods. Therefore, the super class object should be created before the subclass is created. The super class or the base class is implicitly known as MyBase in VB.Net

    The following program demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    Length: 4.5
    Width: 7.5
    Area: 33.75
    Cost: 2362.5

    21 - VB.NET EXCEPTION HANDLING

    An exception is a problem that arises during the execution of a program. An exception is a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero.

    Exceptions provide a way to transfer control from one part of a program to another. VB.Net exception handling is built upon four keywords: Try, Catch, Finally and Throw.

    • Try: A Try block identifies a block of code for which particular exceptions will be activated. It's followed by one or more Catch blocks.
    • Catch: A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The Catch keyword indicates the catching of an exception.
    • Finally: The Finally block is used to execute a given set of statements, whether an exception is thrown or not thrown. For example, if you open a file, it must be closed whether an exception is raised or not.
    • Throw: A program throws an exception when a problem shows up. This is done using a Throw keyword.

    Syntax


    Assuming a block will raise an exception, a method catches an exception using a combination of the Try and Catch keywords. A Try/Catch block is placed around the code that might generate an exception. Code within a Try/Catch block is referred to as protected code, and the syntax for using Try/Catch looks like the following:

    You can list down multiple catch statements to catch different type of exceptions in case your try block raises more than one exception in different situations.

    Exception Classes in .Net Framework


    In the .Net Framework, exceptions are represented by classes. The exception classes in .Net Framework are mainly directly or indirectly derived from the System.Exception class. Some of the exception classes derived from the System.Exception class are the System.ApplicationException and System.SystemException classes.

    The System.ApplicationException class supports exceptions generated by application programs. So the exceptions defined by the programmers should derive from this class.

    The System.SystemException class is the base class for all predefined system exception.

    The following table provides some of the predefined exception classes derived from the Sytem.SystemException class:

    Exception Class Description
    System.IO.IOException Handles I/O errors.
    System.IndexOutOfRangeException Handles errors generated when a method refers to an array index out of range.
    System.ArrayTypeMismatchException Handles errors generated when type is mismatched with the array type.
    System.NullReferenceException Handles errors generated from deferencing a null object.
    System.DivideByZeroException Handles errors generated from dividing a dividend with zero.
    System.InvalidCastException Handles errors generated during typecasting.
    System.OutOfMemoryException Handles errors generated from insufficient free memory.
    System.StackOverflowException Handles errors generated from stack overflow.

    Handling Exceptions


    VB.Net provides a structured solution to the exception handling problems in the form of try and catch blocks. Using these blocks the core program statements are separated from the error-handling statements.

    These error handling blocks are implemented using the Try, Catch and Finally keywords. Following is an example of throwing an exception when dividing by zero condition occurs:

    When the above code is compiled and executed, it produces the following result:

    Exception caught: System.DivideByZeroException: Attempted to divide by zero.
    at ...
    Result: 0

    Creating User-Defined Exceptions


    You can also define your own exception. User-defined exception classes are derived from the ApplicationException class. The following example demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    TempIsZeroException: Zero Temperature found

    Throwing Objects


    You can throw an object if it is either directly or indirectly derived from the System.Exception class.

    You can use a throw statement in the catch block to throw the present object as:

    Throw [ expression ]

    The following program demonstrates this:

    When the above code is compiled and executed, it produces the following result:

    A custom exception is being thrown here...
    Now inside the Finally Block

    22 - VB.NET FILE HANDLING

    A file is a collection of data stored in a disk with a specific name and a directory path. When a file is opened for reading or writing, it becomes a stream. The stream is basically the sequence of bytes passing through the communication path. There are two main streams: the input stream and the output stream. The input stream is used for reading data from file (read operation) and the output stream is used for writing into the file (write operation).

    VB.Net I/O Classes


    The System.IO namespace has various classes that are used for performing various operations with files, like creating and deleting files, reading from or writing to a file, closing a file, etc.

    The following table shows some commonly used non-abstract classes in the System.IO namespace:

    I/O Class Description
    BinaryReader Reads primitive data from a binary stream.
    BinaryWriter Writes primitive data in binary format.
    BufferedStream A temporary storage for a stream of bytes.
    Directory Helps in manipulating a directory structure.
    DirectoryInfo Used for performing operations on directories.
    DriveInfo Provides information for the drives.
    File Helps in manipulating files.
    FileInfo Used for performing operations on files.
    FileStream Used to read from and write to any location in a file.
    MemoryStream Used for random access of streamed data stored in memory.
    Path Performs operations on path information.
    StreamReader Used for reading characters from a byte stream.
    StreamWriter Is used for writing characters to a stream.
    StringReader Is used for reading from a string buffer.
    StringWriter Is used for writing into a string buffer.

    The FileStream Class


    The FileStream class in the System.IO namespace helps in reading from, writing to and closing files. This class derives from the abstract class Stream.

    You need to create a FileStream object to create a new file or open an existing file. The syntax for creating a FileStream object is as follows:

    For example, for creating a FileStream object F for reading a file named sample.txt:

    Parameter Description
    FileMode

    The FileMode enumerator defines various methods for opening files. The members of the FileMode enumerator are:

    • Append: It opens an existing file and puts cursor at the end of file, or creates the file, if the file does not exist.

    • Create: It creates a new file.

    • CreateNew: It specifies to the operating system that it should create a new file.

    • Open: It opens an existing file.

    • OpenOrCreate: It specifies to the operating system that it should open a file if it exists, otherwise it should create a new file.

    • Truncate: It opens an existing file and truncates its size to zero bytes.

    FileAccess

    FileAccess enumerators have members: Read, ReadWrite and Write.

    FileShare

    FileShare enumerators have the following members:

    • Inheritable: It allows a file handle to pass inheritance to the child processes

    • None: It declines sharing of the current file

    • Read: It allows opening the file for reading

    • ReadWrite: It allows opening the file for reading and writing

    • Write: It allows opening the file for writing

    Example:

    The following program demonstrates use of the FileStream class:

    When the above code is compiled and executed, it produces the following result:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1

    Advanced File Operations in VB.Net


    The preceding example provides simple file operations in VB.Net. However, to utilize the immense powers of System.IO classes, you need to know the commonly used properties and methods of these classes.

    We will discuss these classes and the operations they perform in the following sections. Please click the links provided to get to the individual sections:

    Topic and Description

    Reading from and Writing into Text files

    It involves reading from and writing into text files. The StreamReader and StreamWriter classes help to accomplish it.

    Reading from and Writing into Binary files

    It involves reading from and writing into binary files. The BinaryReader and BinaryWriter classes help to accomplish this.

    Manipulating the Windows file system

    It gives a VB.Net programmer the ability to browse and locate Windows files and directories.

    23 - VB.NET BASIC CONTROLS

    An object is a type of user interface element you create on a Visual Basic form by using a toolbox control. In fact, in Visual Basic, the form itself is an object. Every Visual Basic control consists of three important elements:

    • Properties which describe the object,
    • Methods cause an object to do something and
    • Events are what happens when an object does something.

    Control Properties


    All the Visual Basic Objects can be moved, resized or customized by setting their properties. A property is a value or characteristic held by a Visual Basic object, such as Caption or Fore Color.

    Properties can be set at design time by using the Properties window or at run time by using statements in the program code.

    Object. Property = Value

    Where

    • Object is the name of the object you're customizing.
    • Property is the characteristic you want to change.
    • Value is the new property setting.

    For example,

    You can set any of the form properties using Properties Window. Most of the properties can be set or read during application execution. You can refer to Microsoft documentation for a complete list of properties associated with different controls and restrictions applied to them.

    Control Methods


    A method is a procedure created as a member of a class and they cause an object to do something. Methods are used to access or manipulate the characteristics of an object or a variable. There are mainly two categories of methods you will use in your classes:

    • If you are using a control such as one of those provided by the Toolbox, you can call any of its public methods. The requirements of such a method depend on the class being used.
    • If none of the existing methods can perform your desired task, you can add a method to a class.

    For example, the MessageBox control has a method named Show, which is called in the code snippet below:

    Control Events


    An event is a signal that informs an application that something important has occurred. For example, when a user clicks a control on a form, the form can raise a Click event and call a procedure that handles the event. There are various types of events associated with a Form like click, double click, close, load, resize, etc.

    Following is the default structure of a form Load event handler subroutine. You can see this code by double clicking the code which will give you a complete list of the all events associated with Form control:

    Here, Handles MyBase.Load indicates that Form1_Load() subroutine handles Load event. Similar way, you can check stub code for click, double click. If you want to initialize some variables like properties, etc., then you will keep such code inside Form1_Load() subroutine. Here, important point to note is the name of the event handler, which is by default Form1_Load, but you can change this name based on your naming convention you use in your application programming.

    Basic Controls


    VB.Net provides a huge variety of controls that help you to create rich user interface. Functionalities of all these controls are defined in the respective control classes. The control classes are defined in the System.Windows.Forms namespace.

    The following table lists some of the commonly used controls:

    24 - VB.NET DIALOG BOXES

    There are many built-in dialog boxes to be used in Windows forms for various tasks like opening and saving files, printing a page, providing choices for colors, fonts, page setup, etc., to the user of an application. These built-in dialog boxes reduce the developer's time and workload.

    All of these dialog box control classes inherit from the CommonDialog class and override the RunDialog() function of the base class to create the specific dialog box.

    The RunDialog() function is automatically invoked when a user of a dialog box calls its ShowDialog() function.

    The ShowDialog method is used to display all the dialog box controls at run-time. It returns a value of the type of DialogResult enumeration. The values of DialogResult enumeration are:

    • Abort - returns DialogResult.Abort value, when user clicks an Abort button.
    • Cancel- returns DialogResult.Cancel, when user clicks a Cancel button.
    • Ignore - returns DialogResult.Ignore, when user clicks an Ignore button.
    • No - returns DialogResult.No, when user clicks a No button.
    • None - returns nothing and the dialog box continues running.
    • OK - returns DialogResult.OK, when user clicks an OK button
    • Retry - returns DialogResult.Retry , when user clicks an Retry button
    • Yes - returns DialogResult.Yes, when user clicks an Yes button

    The following diagram shows the common dialog class inheritance:

    All these above-mentioned classes have corresponding controls that could be added from the Toolbox during design time. You can include relevant functionality of these classes to your application, either by instantiating the class programmatically or by using relevant controls.

    When you double click any of the dialog controls in the toolbox or drag the control onto the form, it appears in the Component tray at the bottom of the Windows Forms Designer, they do not directly show up on the form.

    The following table lists the commonly used dialog box controls. Click the following links to check their detail:

    S.N. Control & Description
    1

    ColorDialog

    It represents a common dialog box that displays available colors along with controls that enable the user to define custom colors.

    2

    FontDialog

    It prompts the user to choose a font from among those installed on the local computer and lets the user select the font, font size, and color.

    3

    OpenFileDialog

    It prompts the user to open a file and allows the user to select a file to open.

    4

    SaveFileDialog

    It prompts the user to select a location for saving a file and allows the user to specify the name of the file to save data.

    5

    PrintDialog

    It lets the user to print documents by selecting a printer and choosing which sections of the document to print from a Windows Forms application.

    25 - VB.NET AVANCED FORM

    In this chapter, let us study the following concepts:

    • Adding menus and sub menus in an application
    • Adding the cut, copy and paste functionalities in a form
    • Anchoring and docking controls in a form
    • Modal forms

    Adding Menus and Sub Menus in an Application


    Traditionally, the Menu, MainMenu, ContextMenu, and MenuItem classes were used for adding menus, sub-menus and context menus in a Windows application. Now, the MenuStrip, the ToolStripMenuItem, ToolStripDropDown and ToolStripDropDownMenu controls replace and add functionality to the Menu-related controls of previous versions. However, the old control classes are retained for both backward compatibility and future use. Let us create a typical windows main menu bar and sub menus using the old version controls first since these controls are still much used in old applications. Following is an example, which shows how we create a menu bar with menu items: File, Edit, View and Project. The File menu has the sub menus New, Open and Save. Let's double click on the Form and put the following code in the opened window.

    When the above code is executed and run using Start button available at the Microsoft Visual Studio tool bar, it will show the following window:

    Windows Forms contain a rich set of classes for creating your own custom menus with modern appearance, look and feel. The MenuStrip, ToolStripMenuItem, ContextMenuStrip controls are used to create menu bars and context menus efficiently.

    Click the following links to check their details:

    S.N. Control & Description
    1

    MenuStrip

    It provides a menu system for a form.

    2

    ToolStripMenuItem

    It represents a selectable option displayed on a MenuStrip or ContextMenuStrip. The ToolStripMenuItem control replaces and adds functionality to the MenuItem control of previous versions.

    2

    ContextMenuStrip

    It represents a shortcut menu.

    Adding the Cut, Copy and Paste Functionalities in a Form


    The methods exposed by the ClipBoard class are used for adding the cut, copy and paste functionalities in an application. The ClipBoard class provides methods to place data on and retrieve data from the system Clipboard.

    It has the following commonly used methods:

    S.N Method Name & Description
    1

    Clear

    Removes all data from the Clipboard.

    2

    ContainsData

    Indicates whether there is data on the Clipboard that is in the specified format or can be converted to that format.

    3

    ContainsImage

    Indicates whether there is data on the Clipboard that is in the Bitmap format or can be converted to that format.

    4

    ContainsText

    Indicates whether there is data on the Clipboard in the Text or UnicodeText format, depending on the operating system.

    5

    GetData

    Retrieves data from the Clipboard in the specified format.

    6

    GetDataObject

    Retrieves the data that is currently on the system Clipboard.

    7

    GetImage

    Retrieves an image from the Clipboard.

    8

    GetText

    Retrieves text data from the Clipboard in the Text or UnicodeText format, depending on the operating system.

    9

    GetText(TextDataFormat)

    Retrieves text data from the Clipboard in the format indicated by the specified TextDataFormat value.

    10

    SetData

    Clears the Clipboard and then adds data in the specified format.

    11

    SetText(String)

    Clears the Clipboard and then adds text data in the Text or UnicodeText format, depending on the operating system.

    Following is an example, which shows how we cut, copy and paste data using methods of the Clipboard class. Take the following steps:

    • Add a rich text box control and three button controls on the form.
    • Change the text property of the buttons to Cut, Copy and Paste, respectively.
    • Double click on the buttons to add the following code in the code editor:

    When the above code is executed and run using Start button available at the Microsoft Visual Studio tool bar, it will show the following window:

    Enter some text and check how the buttons work.

    Anchoring and Docking Controls in a Form


    Anchoring allows you to set an anchor position for a control to the edges of its container control, for example, the form. The Anchor property of the Control class allows you to set values of this property. The Anchor property gets or sets the edges of the container to which a control is bound and determines how a control is resized with its parent.

    When you anchor a control to a form, the control maintains its distance from the edges of the form and its anchored position, when the form is resized.

    You can set the Anchor property values of a control from the Properties window:

    For example, let us add a Button control on a form and set its anchor property to Bottom, Right. Run this form to see the original position of the Button control with respect to the form.

    Now, when you stretch the form, the distance between the Button and the bottom right corner of the form remains same.

    Docking of a control means docking it to one of the edges of its container. In docking, the control fills certain area of the container completely.

    The Dock property of the Control class does this. The Dock property gets or sets which control borders are docked to its parent control and determines how a control is resized with its parent.

    You can set the Dock property values of a control from the Properties window:

    For example, let us add a Button control on a form and set its Dock property to Bottom. Run this form to see the original position of the Button control with respect to the form.

    Now, when you stretch the form, the Button resizes itself with the form.

    Modal Forms


    Modal Forms are those forms that need to be closed or hidden before you can continue working with the rest of the application. All dialog boxes are modal forms. A MessageBox is also a modal form.

    You can call a modal form by two ways:

    • Calling the ShowDialog method
    • Calling the Show method

    Let us take up an example in which we will create a modal form, a dialog box. Take the following steps:

    • Add a form, Form1 to your application, and add two labels and a button control to Form1
    • Change the text properties of the first label and the button to 'Welcome to Tutorials Point' and 'Enter your Name', respectively. Keep the text properties of the second label as blank.
    • Add a new Windows Form, Form2, and add two buttons, one label, and a text box to Form2.
    • Change the text properties of the buttons to OK and Cancel, respectively. Change the text properties of the label to 'Enter your name:'.
    • Set the FormBorderStyle property of Form2 to FixedDialog, for giving it a dialog box border.
    • Set the ControlBox property of Form2 to False.
    • Set the ShowInTaskbar property of Form2 to False.
    • Set the DialogResult property of the OK button to OK and the Cancel button to Cancel.

    Add the following code snippets in the Form2_Load method of Form2:

    Add the following code snippets in the Button1_Click method of Form1:

    When the above code is executed and run using Start button available at the Microsoft Visual Studio tool bar, it will show the following window:

    Clicking on the 'Enter your Name' button displays the second form:

    Clicking on the OK button takes the control and information back from the modal form to the previous form:

    26 - VB.NET EVENT HANDLING

    Events are basically a user action like key press, clicks, mouse movements, etc., or some occurrence like system generated notifications. Applications need to respond to events when they occur.

    Clicking on a button, or entering some text in a text box, or clicking on a menu item, all are examples of events. An event is an action that calls a function or may cause another event.

    Event handlers are functions that tell how to respond to an event.

    VB.Net is an event-driven language. There are mainly two types of events:

    • Mouse events
    • Keyboard events

    Handling Mouse Events


    Mouse events occur with mouse movements in forms and controls. Following are the various mouse events related with a Control class:

    • MouseDown - it occurs when a mouse button is pressed
    • MouseEnter - it occurs when the mouse pointer enters the control
    • MouseHover - it occurs when the mouse pointer hovers over the control
    • MouseLeave - it occurs when the mouse pointer leaves the control
    • MouseMove - it occurs when the mouse pointer moves over the control
    • MouseUp - it occurs when the mouse pointer is over the control and the mouse button is released
    • MouseWheel - it occurs when the mouse wheel moves and the control has focus
    • The event handlers of the mouse events get an argument of type MouseEventArgs. The MouseEventArgs object is used for handling mouse events. It has the following properties:
    • Buttons - indicates the mouse button pressed
    • Clicks - indicates the number of clicks
    • Delta - indicates the number of detents the mouse wheel rotated
    • X - indicates the x-coordinate of mouse click
    • Y - indicates the y-coordinate of mouse click

    Example

    Following is an example, which shows how to handle mouse events. Take the following steps:

    • Add three labels, three text boxes and a button control in the form.
    • Change the text properties of the labels to - Customer ID, Name
    • and Address, respectively.
    • Change the name properties of the text boxes to txtID, txtName and txtAddress, respectively.
    • Change the text property of the button to 'Submit'.
    • Add the following code in the code editor window:

    When the above code is executed and run using Start button available at the Microsoft Visual Studio tool bar, it will show the following window:

    Try to enter text in the text boxes and check the mouse events:

    Handling Keyboard Events


    Following are the various keyboard events related with a Control class:

    • KeyDown - occurs when a key is pressed down and the control has focus
    • KeyPress - occurs when a key is pressed and the control has focus
    • KeyUp - occurs when a key is released while the control has focus
    • The event handlers of the KeyDown and KeyUp events get an argument of type KeyEventArgs. This object has the following properties:
    • Alt - it indicates whether the ALT key is pressed/p>
    • Control - it indicates whether the CTRL key is pressed
    • Handled - it indicates whether the event is handled
    • KeyCode - stores the keyboard code for the event
    • KeyData - stores the keyboard data for the event
    • KeyValue - stores the keyboard value for the event
    • Modifiers - it indicates which modifier keys (Ctrl, Shift, and/or Alt) are pressed
    • Shift - it indicates if the Shift key is pressed

    The event handlers of the KeyDown and KeyUp events get an argument of type KeyEventArgs. This object has the following properties:

    • Handled - indicates if the KeyPress event is handled
    • KeyChar - stores the character corresponding to the key pressed

    Example

    Let us continue with the previous example to show how to handle keyboard events. The code will verify that the user enters some numbers for his customer ID and age.

    • Add a label with text Property as 'Age' and add a corresponding text box named txtAge.
    • Add the following codes for handling the KeyUP events of the text box txtID.
    • Add the following codes for handling the KeyUP events of the text box txtID.

    When the above code is executed and run using Start button available at the Microsoft Visual Studio tool bar, it will show the following window:

    If you leave the text for age or ID as blank or enter some non-numeric data, it gives a warning message box and clears the respective text:

    50-game

    Python

    1 - PYTHON OVERVIEW

    What is python?


    If you don't understand this, don't worry. Just skip it and move on.

    Python is an interpreted programming language. For those who don't know, a programming language is what you write down to tell a computer what to do. However, the computer doesn't read the language directly - there are hundreds of programming languages, and it couldn't understand them all. So, when someone writes a program, they will write it in their language of choice, and then compile it - that is, turn it in to lots of 0s and 1s, that the computer can easily and quickly understand. A windows program that you buy is already compiled for windows - if you opened the program file up, you'd just get a mass of weird characters and rectangles. Give it a go - find a small windows program, and open it up in notepad or wordpad. See what garbled mess you get.

    But that windows program is compiled for windows - no other machine can run that program, unless it has windows. What Python is, is a language which is never actually compiled in full - instead, an interpreter turns each line of code into 0s and 1s that your computer can understand this. And it is done on the fly - it compiles the bits of the program you are using as you are using them. If you were to quit the program and come back another day, it would compile the bits you are using, as you are using them, again. Seems a waste of time? Maybe, but the fact is that when you come back another day, you might be using a Windows instead of a Mac. You might send the program to a friend, who uses another type of computer. Or you might post your program on the internet, where everyone using all different types of systems might download it. That is the wonder of an interpreted programming language - it is like a language that EVERYONE can understand.

    So why will civIV use Python?


    Remember that garbled mess that you got when opening a program in notepad? Not much use to anyone, apart from the computer. And there is no reliable (or legal) way of turning that program back in to a programming language that you or I could understand.

    The same is with Civ3 AI - it is compiled into a garbled mess. Nobody can understand it, and most of all, nobody can change it. Only Firaxis can change the AI, and they can't share the logic behind it with anyone.

    With cIV, they decided to change that - they would leave the AI uncompiled in the language of Python, and have it compiled on-the-fly by an interpreter. This is so that Joe modder can look at the AI and change it, yet when it is neede to be used, the python interpreter turns it into 0s and 1s for your computer to understand. And it isn't permanently compiled into a garbled mess - you are still left with python code, that you can read, understand, and MODIFY!!!!!

    2 - PYTHON INSTALLING PYTHON

    How to install python


    1. First download Python-2.4.1.exe by following this link. If you are a dialup user, keep in mind that the file is around 10MB
    2. Run the file you just downloaded, and follow the prompts.

    OK! Hopefully now everything is good! Now, to test if that just worked, type this in your DOS window:


    Code Example 1- Testing the instalation python -V

    If you forgot a CAPITAL V, you will accidently load python in verbose mode. Give it a go, see what happens. Just press CTRL-D to quit, or type 'quit' for quit instructions.

    conclusion


    Good work! Lesson 1 over! Next lesson, we learn our way around Python Interactive Mode, and write simple one-line pieces of code. I'll also have a lesson plan drawn up by then, so you can see where you are going. If any of our more experienced members have suggestions for the lesson plan, tell me!

    3 - PYTHON UNDERSTANDING PROGRAMS

    Introduction


    OK! We have python installed, now what? Well, we program! And it is that simple (at least for now). Python makes it easy to run single lines of code - one-liner programs. Lets give it a go.

    Opening IDLE


    Go to the start menu, find Python, and run the program labelled 'IDLE' (Stands for Integrated Development Environment.

    Now you are in the IDLE environment. This is the place you will be spending most time in. Here you can open a new window to write a program, or you can simply mess around with single lines of code, which is what we are going to do. Type the following and press enter: (don't type >>> as it should already be there)

    >>> print "Hello, World!"

    What happened? You just created a program, that prints the words 'Hello, World'. The IDLE environment that you are in immediately compiles whatever you have typed in. This is useful for testing things, e.g. define a few variables, and then test to see if a certain line will work. That will come in a later lesson, though.

    Math in Python


    Now try typing the stuff in bold. You should get the output shown in blue. I've given explainations in brackets.

    >>> 1 + 1 2 >>> 20+80 100 >>> 18294+449566 467860 (These are additions) >>> 6-5 1 (Subtraction) >>> 2*5 10 (Multiply, rabbits!) >>> 5**2 25 (Exponentials e.g. this one is 5 squared) >>> print "1 + 2 is an addition" 1 + 2 is an addition (the print statement, which writes something onscreen) >>> print "one kilobyte is 2^10 bytes, or", 2**10, "bytes" one kilobyte is 2^10 bytes, or 1024 bytes (you can print sums and variables in a sentence. The commas seperating each section are a way of seperating clearly different things that you are printing) >>> 21/3 7 >>> 23/3 7 >>> 23.0/3.0 7.6666... (division, 2nd time ignoring remainder/decimals, 3rd time including decimals) >>> 23%3 2 >>> 49%10 9 (the remainder from a division)

    As you see, there is the code, then the result of that code. I then explain them in brackets. These are the basic commands of python, and what they do. Here is a table to clarify them (because tables look cool, and make you feel smarter ;) ):

    Remember that thing called order of operation that they taught in maths? Well, it applies in python, too. Here it is, if you need reminding:

    1. parentheses ()
    2. exponents **
    3. multiplication *, division \, and remainder %
    4. addition + and subtraction -

    Order of Operations


    Here are some examples that you might want to try, if you're rusty on this:

    n the first example, the computer calculates 2 * 3 first, then adds 1 to it. This is because multiplication has the higher priority (at 3) and addition is below that (at lowly 4).

    In the second example, the computer calculates 1 + 2 first, then multiplies it by 3. This is because parentheses (brackets, like the ones that are surrounding this interluding text ;) ) have the higher priority (at 1) and addition comes in later than that.

    Also remember that the math is calculated from left to right, UNLESS you put in parentheses. The innermost parentheses are calculated first. Watch these examples:

    In the first example, 4 -40 is calculated,then - 3 is done.

    In the second example, 40 - 3 is calculated, then it is subtracted from 4.

    Comments, Please


    The final thing you'll need to know to move on to multi-line programs is the comment. Type the following (and yes, the output is shown):

    A comment is a piece of code that is not run. In python, you make something a comment by putting a hash in front of it. A hash comments everything after it in the line, and nothing before it. So you could type this:

    Comments are important for adding necessary information for another programmer to read, but not the computer. For example, an explanation of a section of code, saying what it does, or what is wrong with it. You can also comment bits of code by putting a # in front of it - if you don't want it to compile, but cant delete it because you might need it later.

    Conclusion


    There you go! Lesson 2 Completed. That was even shorter than lesson 1! Next lesson, we make programs with many lines of code, and save them, so we can actually send them to people. That's right, you don't have to retype every program you run! What an amazing innovation!

    4 - PYTHON VARIABLES

    Introduction


    Well, we can make one-liner programs. So What? You want to send programs to other people, so that they can use them, without knowing how to write them.

    Editing in Notepad


    Writing programs in python to a file is VERY easy. Python programs are simply text documents - you can open them up in notepad, and have a look at them, just like that. So, go and open notepad. Type the following:

    Code Example 1 - mary.py

    Keep this exactly the same, down to where the commas are placed. Save the file as 'mary.py' - and make sure notepad doesn't add .txt to the end of the filename - You will have to tell it to save as any file, to avoid this. Turn off 'Hide known file extensions' in Windows Explorer, if it makes it easier.

    Using the IDLE Environment


    Now, open up the Python IDLE program (should be in your start menu). Click 'File > Open' and find mary.py and open it. if you cant find mary.py, set the open dialogue to 'Files of type: All Files (*)'. A new window will open, showing the program you just wrote. To run your program, click 'Run>Run Module' (or just press F5). Your program will now run in the main Python screen (Titled *Python Shell*) and will look like this:

    Code Example 2 - mary.py output

    You can also use IDLE to create Python programs, like what you did in notepad. Simply click 'File > New'. We will be writing all of our programs now in the python IDLE program - the notepad thing is just a demonstration to tell you that a .py file is just a simple text file, which anyone can see.

    There are a couple of things to notice here:

    • First of all, the comment wasn't shown. That is good, because remember - comments aren't compiled. (try compiling it after removing the # - it comes out messy)
    • Second, is that the 3rd and 4th line got joined. This is because there is a comma just outside the inverted commas that surround the text. In the 'print' command, this stops the program from starting a new line on the screen when showing text.
    • You can also run the program from your command line program (e.g. MSDOS) - Open the prompt up, type 'cd path\to\your\file' then type 'python mary.py'. Your program will now execute in the command line.

    VARIABLES


    Now lets start introducing variables. Variables store a value, that can be looked at or changed at a later time. Let's make a program that uses variables. Open up IDLE, click 'File>New Window' - a new window now appears, and it is easy to type in programs. Type the following (or just copy and paste - just read very carefully, and compare the code to the output that the program will make):

    Code Example 3 - Variables

    Strings


    As you can see, variables store values, for use at a later time. You can change them at any time. You can put in more than numbers, though. Variables can hold things like text. A variable that holds text is called a string. Try this program:

    Code Example 4 - Strings The output will be:

    Good Morning
    Good Morning to you too!

    As you see, the variables above were holding text. Variable names can also be longer than one letter - here, we had word1, word2, and word3. As you can also see, strings can be added together to make longer words or sentences. However, it doesn't add spaces in between the words - hence me putting in the " " things (there is one space between those).

    Conclusion


    Well done! We now understand longer programs, and know the use of variables. Next lesson, we look at functions, what they are, and how to use them.

    5 - PYTHON LOOP

    Introduction


    Our final lesson before we get into interacting with human input. Can't wait, can you?)

    Just imagine you needed a program to do something 20 times. What would you do? You could copy and paste the code 20 times, and have a virtually unreadable program, not to mention slow and pointless. Or, you could tell the computer to repeat a bit of code between point A and point B, until the time comes that you need it to stop. Such a thing is called a loop.

    The 'while' loop


    The following are examples of a type of loop, called the 'while' loop:

    Code Example 1 - The while loop

    How does this program work? Lets go through it in English:

    Code Example 2 - plain-language while loop Code Example 3 - while loop process

    So in short, try to think of it that way when you write 'while' loops. This is how you write them, by the way (and a couple of examples:

    Code Example 4 - while loop form, and example

    Remember, to make a program, you open IDLE, click File > New Window, type your program in the new window, then press F5 to run.

    Boolean Expressions (Boolean... what?!?)


    What do you type in the area marked {conditions that the loop continues}? The answer is a boolean expression.

    What? A forgotten concept for the non-math people here. Never mind, boolean expression just means a question that can be answered with a TRUE or FALSE response. For example, if you wanted to say your age is the same as the person next to you, you would type:

    My age == the age of the person next to me

    And the statement would be TRUE. If you were younger than the person opposite, you'd say:

    My age < the age of the person opposite me

    And the statement would be TRUE. If, however, you were to say the following, and the person
    opposite of you was younger than you:

    My age < the age of the person opposite me

    The statement would be FALSE - the truth is that it is the other way around. This is how a loop thinks - if the expression is true, keep looping. If it is false, don't loop. With this in mind, lets have a look at the operators (symbols that represent an action) that are involved in boolean expressions:

    Table 1 - Boolean operators

    Dont get '=' and '==' mixed up - the '=' operator makes what is on the left equal to what is on the right. the '==' operator says whether the thing on the left is the same as what is on the right, and returns true or false.

    Conditional Statements


    OK! We've (hopefully) covered 'while' loops. Now let's look at something a little different - conditionals.

    Conditionals are where a section of code is only run if certain conditions are met. This is similar to the 'while' loop you just wrote, which only runs when x doesn't equal 0. However, Conditionals are only run once. The most common conditional in any program language, is the 'if' statement. Here is how it works:

    Code Example 5 - if statement and example

    Example 2 there looks tricky. But all we have done is run an 'if' statement every time the 'while' loop runs. Remember that the % just means the remainder from a division - just checking that there is nothing left over if the number is divided by two - showing it is even. If it is even, it prints what 'n' is.

    'else' and 'elif' - When it Ain't True

    There are many ways you can use the 'if' statement, do deal with situations where your boolean expression ends up FALSE. They are 'else' and 'elif'.

    'else' simply tells the computer what to do if the conditions of 'if' arent met. For example, read the following:

    Code Example 6 - the else statement

    'a' is not greater than five, therefore what is under 'else' is done.

    'elif' is just a shortened way of saying 'else if'. When the 'if' statement fails to be true, 'elif' will do what is under it IF the conditions are met. For example:

    Code Example 7 - The elif statement

    The 'if' statement, along with 'else' and 'elif' follow this form:

    Code Example 8 - the complete if syntax

    One of the most important points to remember is that you MUST have a colon : at the end of every line with an 'if', 'elif', 'else' or 'while' in it. I forgot that, and as a result a stack of people got stumped at this lesson (sorry ;) ).

    Indentation


    One other point is that the code to be executed if the conditions are met, MUST BE INDENTED. That means that if you want to loop the next five lines with a 'while' loop, you must put a set number of spaces at the beginning of each of the next five lines. This is good programming practice in any language, but python requires that you do it. Here is an example of both of the above points:

    Code Example 9 - Indentation

    Notice the three levels of indents there:

    1. Each line in the first level starts with no spaces. It is the main program, and will always execute.
    2. Each line in the second level starts with four spaces. When there is an 'if' or loop on the first level, everything on the second level after that will be looped/'ifed', until a new line starts back on the first level again.
    3. Each line in the third level starts with eight spaces. When there is an 'if' or loop on the second level, everything on the third level after that will be looped/'ifed', until a new line starts back on the second level again.
    4. This goes on infinitely, until the person writing the program has an internal brain explosion, and cannot understand anything he/she has written.

    There is another loop, called the 'for' loop, but we will cover that in a later lesson, after we have learnt about lists.

    Conclusion

    And that is lesson 4! In lesson 5, we get into user interaction, and writing programs that actually serve a purpose. Can't wait!

    6 - PYTHON FUNCTIONS

    Introduction


    Last lesson I said that we would delve into purposefull programming. That involves user input, and user input requires a thing called functions.

    What are functions? Well, in effect, functions are little self-contained programs that perform a specific task, which you can incorporate into your own, larger programs. After you have created a function, you can use it at any time, in any place. This saves you the time and effort of having to retell the computer what to do every time it does a common task, for example getting the user to type something in.

    Using a function


    Python has lots of pre-made functions, that you can use right now, simply by 'calling' them. 'Calling' a function involves you giving a function input, and it will return a value (like a variable would) as output. Don't understand? Here is the general form that calling a function takes:

    Code Example 1 - How to call a function function_name(parameters)

    See? Easy.

    • Function_name identifies which function it is you want to use (You'd figure...). For example, the function raw_input, which will be the first function that we will use.
    • Parameters are the values you pass to the function to tell it what is should do, and how to do it.. for example, if a function multiplied any given number by five, the stuff in parameters tells the function which number it should multiply by five. Put the number 70 into parameters, and the function will do 70 x 5.

    Parameters and Returned Values - Communicating with Functions


    Well, that's all well and good that the program can multiply a number by five, but what does it have to show for it? A warm fuzzy feeling? Your program needs to see the results of what happened, to see what 70 x 5 is, or to see if there is a problem somewhere (like you gave it a letter instead of a number). So how does a function show what is does?

    Well, in effect, when a computer runs a function, it doesn't actually see the function name, but the result of what the function did. Variables do the exact same thing - the computer doesn't see the variable name, it sees the value that the variable holds. Lets call this program that multiplied any number by five, multiply(). You put the number you want multiplied in the brackets. So if you typed this:

    Code Example 2 - Using a function a = multiply(70)

    The computer would actually see this:

    Code Example 3 - What the computer sees a = 350

    note: don't bother typing in this code - multiply() isn't a real function, unless you create it.

    The function ran itself, then returned a number to the main program, based on what parameters it was given.

    Now let's try this with a real function, and see what it does. The function is called raw_input, and asks the user to type in something. It then turns it into a string of text. Try the code below:

    Code Example 4 - Using raw_input

    Say in the above program, you typed in 'hello' when it asked you to type something in. To the computer, this program would look like this:

    Code Example 5 - What the computer sees

    Remember, a variable is just a stored value. To the computer, the variable 'a' doesn't look like 'a' - it looks like the value that is stored inside it. Functions are similar - to the main program (that is, the program that is running the function), they look like the value of what they give in return of running.

    A Calculator Program


    Lets write another program, that will act as a calculator. This time it will do something more adventerous than what we have done before. There will be a menu, that will ask you whether you want to multiply two numbers together, add two numbers together, divide one number by another, or subtract one number from another. Only problem - the raw_input function returns what you type in as a string - we want the number 1, not the letter 1 (and yes, in python, there is a difference.).

    Luckily, somebody wrote the function input, which returns what you typed in, to the main program - but this time, it puts it in as a number. If you type an integer (a whole number), what comes out of input is an integer. And if you put that integer into a variable, the variable will be an integer-type variable, which means you can add and subtract, etc.

    Now, lets design this calculator properly. We want a menu that is returned to every time you finish adding, subtracting, etc. In other words, to loop (HINT!!!) while (BIG HINT!!!) you tell it the program should still run.

    We want it to do an option in the menu if you type in that number. That involves you typing in a number (a.k.a input) and an if loop.

    Lets write it out in understandable English first:

    Code Example 6 - human-language example

    Lets put this in something that python can understand:

    Code Example 7 - Python verion of menu

    Wow! That is an impressive program! Paste it into python IDLE, save it as 'calculator.py' and run it. Play around with it - try all options, entering in integers (numbers without decimal points), and numbers with stuff after the decimal point (known in programming as a floating point). Try typing in text, and see how the program chucks a minor fit, and stops running (That can be dealt with, using error handling, which we can address later.)

    Define Your Own Functions


    Well, it is all well and good that you can use other people's functions, but what if you want to write your own functions, to save time, and maybe use them in other programs? This is where the 'def' operator comes in. (An operator is just something that tells python what to do, e.g. the '+' operator tells python to add things, the 'if' operator tells python to do something if conditions are
    met.)
    This is how the 'def' operator works:

    Code Example 8 - The def operator

    function_name is the name of the function. You write the code that is in the function below that line, and have it indented. (We will worry about parameter_1 and parameter_2 later, for now imagine there is nothing between the parentheses.

    Functions run completely independent of the main program. Remember when I said that when the computer comes to a function, it doesn't see the function, but a value, that the function returns? Here's the quote:

    Functions run completely independent of the main program. Remember when I said that when the computer comes to a function, it doesn't see the function, but a value, that the function returns? Here's the quote:

    To the computer, the variable 'a' doesn't look like 'a' - it looks like the value that is stored inside it. Functions are similar - to the main program (that is, the program that is running the function), they look like the value of what they give in return of running.

    A function is like a miniture program that some parameters are given to - it then runs itself, and then returns a value. Your main program sees only the returned value. If that function flew to the moon and back, and then at the end had:

    Code Example 9 - return return "Hello"

    then all your program would see is the string "hello", where the name of the function was. It would have no idea what else the program did.

    Because it is a seperate program, a function doesn't see any of the variables that are in your main program, and your main program doesn't see any of the variables that are in a function. For example, here is a function that prints the words "hello" onscreen, and then returns the number '1234' to the main program:

    Code Example 10 - using return

    Think about the last line of code above. What did it do? Type in the program (you can skip the comments), and see what it does. The output looks like this:

    Code Example 11 - the output

    So what happened?

    That accounts for everything that happened. remember, that the main program had NO IDEA that the words "hello" were printed onscreen. All it saw was '1234', and printed that onscreen.

    Passing Parameters to functions


    There is one more thing we will cover in this (monsterously huge) lesson - passing parameters to a function. Think back to how we defined functions:

    Code Example 12 - Defining functions with parameters

    Where parameter_1 and parameter_2 are (between the parentheses), you put the names of variables that you want to put the parameters into. Put as many as you need, just have them seperated by commas. When you run a function, the first value you put inside the parentheses would go into the variable where parameter_1 is. The second one (after the first comma) would go to the variable where parameter_2 is. This goes on for however many parameters there are in the function (from zero, to the sky) For example:

    Code Example 13 - how parameters work

    When you run the function above, you would type in something like this: funnyfunction("meat","eater","man"). The first value (that is, "meat") would be put into the variable called first_word. The second value inside the brackets (that is, "eater") would be put into the variable called second_word, and so on. This is how values are passed from the main program to functions - inside the parentheses, after the function name.

    A final program


    Think back to that calculator program. Did it look a bit messy to you? I think it did, so lets re-write it, with functions.

    To design - First we will define all the functions we are going to use with the 'def' operator (still remember what an operator is ;) ). Then we will have the main program, with all that messy code replaced with nice, neat functions. This will make it so much easier to look at again in the future.

    Code Example 14 - Calculator program

    The initial program had 34 lines of code. The new one actually had 35 lines of code! It is a little longer, but if you look at it the right way, it is actually simpler.

    You defined all your functions at the top. This really isn't part of your main program - they are just lots of little programs, that you will call upon later. You could even re-use these in another program if you needed them, and didn't want to tell the computer how to add and subtract again.

    If you look at the main part of the program (between the line 'loop = 1' and 'print "Thankyou for..."'), it is only 15 lines of code. That means that if you wanted to write this program differently, you would only have to write 15 or so lines, as opposed to the 34 lines you would normally have to without functions.

    7 - PYTHON TRUPLES, LISTS AND DICTIONARIES

    Introduction


    Your brain still hurting from the last lesson? Never worry, this one will require a little less thought. We're going back to something simple - variables - but a little more in depth.

    Think about it - variables store one bit of information. They may regurgitate (just not on the carpet...) that information at any point, and their bit of information can be changed at any time. Variables are great at what they do - storing a piece of information that may change over time.

    But what if you need to store a long list of information, which doesn't change over time? Say, for example, the names of the months of the year. Or maybe a long list of information, that does change over time? Say, for example, the names of all your cats. You might get new cats, some may die, some may become your dinner (we should trade recipies!). What about a phone book? For that you need to do a bit of referencing - you would have a list of names, and attached to each of those names, a phone number. How would you do that?

    the Solution - Lists, Tuples, and Dictionaries


    For these three problems, Python uses three different solutions - Tuples, lists, and dictionaries:

    • Lists are what they seem - a list of values. Each one of them is numbered, starting from zero - the first one is numbered zero, the second 1, the third 2, etc. You can remove values from the list, and add new values to the end. Example: Your many cats' names.
    • Tuples are just like lists, but you can't change their values. The values that you give it first up, are the values that you are stuck with for the rest of the program. Again, each value is numbered starting from zero, for easy reference. Example: the names of the months of the year.
    • Dictionaries are similar to what their name suggests - a dictionary. In a dictionary, you have an 'index' of words, and for each of them a definition. In python, the word is called a 'key', and the definition a 'value'. The values in a dictionary aren't numbered - tare similar to what their name suggests - a dictionary. In a dictionary, you have an 'index' of words, and for each of them a definition. In python, the word is called a 'key', and the definition a 'value'. The values in a dictionary aren't numbered - they aren't in any specific order, either - the key does the same thing. You can add, remove, and modify the values in dictionaries. Example: telephone book.

    Tuples


    Tuples are pretty easy to make. You give your tuple a name, then after that the list of values it will carry. For example, the months of the year:

    Code Example 1 - creating a tuple
    • Note that the '\' thingy at the end of sthurlow.comthe first line carries over that line of code to the next line. It is usefull way of making big lines more readable.
    • Technically you don't have to put those parentheses there (the '(' and ')' thingies) but it stops python from getting things confused.
    • You may have spaces after the commas if you feel it necessary - it doesn't really matter.

    Python then organises those values in a handy, numbered index - starting from zero, in the order that you entered them in. It would be organised like this:

    Table 1 - tuple indicies

    And that is tuples! Really easy...

    Lists


    Lists are extremely similar to tuples. Lists are modifiable (or 'mutable', as a programmer may say), so their values can be changed. Most of the time we use lists, not tuples, because we want to easily change the values of things if we need to.

    Lists are defined very similarly to tuples. Say you have FIVE cats, called Tom, Snappy, Kitty, Jessie and Chester. To put them in a list, you would do this:

    Code Example 2 - Creating a List

    As you see, the code is exactly the same as a tuple, EXCEPT that all the values are put between square brackets, not parentheses. Again, you don't have to have spaces after the comma.

    You recall values from lists exactly the same as you do with tuples. For example, to print the name of your 3rd cat you would do this:

    Code Example 3 - Recalling items from a list print cats[2]

    You can also recall a range of examples, like above, for example - cats[0:2] would recall your 1st and 2nd cats.

    Where lists come into their own is how they can be modified. To add a value to a list, you use the 'append()' function. Let's say you got a new cat called Catherine. To add her to the list you'd do this:

    Code Example 4 - Adding items to a list

    That's a little weird, isn't it? I'll explain. That function is in a funny spot - after a period (the '.' kind of period, not otherwise), after the list name. You'll get to see those things more in a later lesson. For the meanwhile, this is the form of the function that adds a new value to a list:

    Code Example 5 - Using the append function

    Clears things up? Good!

    Now to a sad situation - Snappy was shot by a neighbour, and eaten for their dinner (good on 'em!). You need to remove him (or her) from the list. Removing that sorry cat is an easy task, thankfully, so you have to wallow in sadness for as short a time as possible:

    Code Example 6 - Deleting an item

    You've just removed the 2nd cat in your list - poor old Snappy.

    And with that morbid message, lets move on to...

    Dictionaries


    Ok, so there is more to life than the names of your cats. You need to call your sister, mother, son, the fruit man, and anyone else who needs to know that their favourite cat is dead. For that you need a telephone book. Now, the lists we've used above aren't really suitable for a telephone book. You need to know a number based on someone's name - not the other way around, like what we did with the cats. In the examples of months and cats, we gave the computer a number, and it gave us a name. This time we want to give the computer a name, and it give us a number. For this we need
    Dictionaries.

    So how do we make a dictionary? Put away your binding equipment, it isn't that advanced.

    Remember, dictionaries have keys, and values. In a phone book, you have people's names, then their numbers. See a similarity?

    When you initially create a dictionary, it is very much like making a tuple or list. Tuples have ( and ) things, lists have [ and ] things. Guess what! dictionaries have { and } things - curly braces. Here is an example below, showing a dictionary with four phone numbers in it

    Code Example 7 - Creating a dictionary

    the program would then print Lewis Lame's number onscreen. Notice how instead of identifying the value by a number, like in the cats and months examples, we identify the value, using another value - in this case the person's name.

    Ok, you've created a new phone book. Now you want to add new numbers to the book. What do you do? A very simple line of code:

    Code Example 8 - Adding entries to a dictionary

    All that line is saying is that there is a person called Gingerbread Man in the phone book, and his number is 1234567. In other words - the key is 'Gingerbread Man', and the value is 1234567.

    You delete entries in a dictionary just like in a list. Let's say Andrew Parson is your neighbour, and shot your cat. You never want to talk to him again, and therefore don't need his number. Just like in a list, you'd do this:

    Code Example 9 - Removing entries from a dictionary

    Again, very easy. the 'del' operator deletes any function, variable, or entry in a list or dictionary (An entry in a dictionary is just a variable with a number or text string as a name. This comes in handy later on.) remember that append function that we used with the list? Well, there are quite a few of those that can be used with dictionaries. Below, I will write you a program, and it will incorporate some of those functions in. It will have comments along the way explaining what it does. Type this program into Python IDLE (you can skip the comments). Experiment as much as you like with it. Type it where you see the lines beginning with >>>

    Code Example 10 - Functions of dictionaries

    #A few examples of a dictionary #First we define the dictionary #it will have nothing in it this time ages = {} #Add a couple of names to the dictionary ages['Sue'] = 23 ages['Peter'] = 19 ages['Andrew'] = 78 ages['Karren'] = 45 #Use the function has_key() - #This function takes this form: #function_name.has_key(key-name) #It returns TRUE #if the dictionary has key-name in it #but returns FALSE if it doesn't. #Remember - this is how 'if' statements work - #they run if something is true #and they don't when something is false. if ages.has_key('Sue'): print "Sue is in the dictionary. She is", \ ages['Sue'], "years old" else: print "Sue is not in the dictionary" #Use the function keys() - #This function returns a list #of all the names of the keys. #E.g. print "The following people are in the dictionary:" print ages.keys() #You could use this function to #put all the key names in a list: keys = ages.keys() #You can also get a list #of all the values in a dictionary. #You use the values() function: print "People are aged the following:", \ ages.values() #Put it in a list: values = ages.values() #You can sort lists, with the sort() function #It will sort all values in a list #alphabetically, numerically, etc... #You can't sort dictionaries - #they are in no particular order print keys keys.sort() print keys print values values.sort() print values #You can find the number of entries #with the len() function: print "The dictionary has", \ len(ages), "entries in it"

    Conclusion


    There are many other functions you can use to work with lists and dictionaries - too many to go through right now. We'll leave the lesson at this point - you have learnt enough for one lesson.

    8 - PYTHON FOR LOOP

    Introduction


    Well, in the first lesson about loops, I said I would put off teaching you the for loop, until we had reached lists. Well, here it is!

    The 'for' Loop

    Basically, the for loop does something for every value in a list. The way it is set out is a little confusing, but otherwise is very basic. Here is an example of it in code

    Code Example 1 - The for Loop

    As you see, when the loop executes, it runs through all of the values in the list mentioned after 'in'. It then puts them into value, and executes through the loop, each time with value being worth something different. Let's see it a again, in a classic cheerleading call that we all know:

    Code Example 2 - A for Loop Example

    A couple of things you've just learnt:

    • As you see, strings (remember - strings are lines of text) are just lists with lots of characters.
    • The program went through each of the letters (or values) in word, and it printed them onscreen.

    And that is all there is to the for loop. Making a Menu Function

    Now to the business end of the lesson. Lets start writing programs. So far we have learnt variables, lists, loops, and functions. That is pretty much all we need for quite a bit of programming. So let's set ourselves a task.

    Code Example 3 - A menu function

    That wasn't very difficult, was it? the actual program only took up five lines - this is the wonder of how much we have learnt so far! All my comments take up sixteen lines - more than three times the program length. It is a good idea to comment your programs extensively. Remember that if you are going to be publishin gyour code open-source, there are going to be a lot of people checking out the code that you have written. We'll see the function we just wrote in our first example program.

    Our First 'Game'


    What will our first example program be? How about a (very) simple text adventure game? Sounds like fun! It will only encompass one room of a house, and will be extremely simple. There will be five things, and a door. In one of the five things, is a key to the door. You need to find the key, then open the door. I will give a plain-english version first, then do it in python:

    Code Example 4 - Plain-english version of code

    From this, we can write a real program. Ready? Here it is (skip typing the comments):

    Code Example 5 - Text Adventure Game

    Well, a very simple, but fun, game. Don't get daunted by the amount of code there, 53 of the lines are just the 'if' statements, which is the easiest thing to read there (Once you comprehend all the indentation. Soon you'll make your own game, and you can make it as simple (or as complex) as you like. I'll post quite a few, later.

    Making the game better


    The fist question you should ask is "does this program work?". The answer here is yes. Then you should ask "does this program work well?" - not quite. The menu() function is great - it reduces a lot of typing. The 'while' loop that we have, however, is a little messy - four levels of indents, for a simple program. We can do better!

    Now, this will become much MUCH more straightforward when we introduce classes. But that will have to wait. Until then, let's make a function that reduces our mess. It we will pass two things to it - the menu choice we made, and the location of the key. It will return one thing - whether or not the key has been found. Lets see it:

    Code Example 6 - Creating an inspect function

    Now the main program can be a little simpler. Let's take it from the while loop, and change things around:

    Code Example 7 - The new game

    Now the program becomes massively shorter - from a cumbersome 83 lines, to a very shapely 50 lines! Of course, you lose quite a bit of versatility - all the items in the room do the same thing. You automatically open the door when you find the key. The game becomes a little less interesting. It also becomes a little harder to change.

    conclusion


    Now I said you would write some programs now. Here is your chance! Your task, if you chose to accept it, is to post a better text adventure game. You can use any of the code I have given you here. Remember to check back on previous lessons we have done - they are priceless tools. Do a search for some simple text adventure games - if you find some nice, fun text adventure games, have a look at them.

    9 - PYTHON CLASSES

    Introduction


    One thing that you will get to know about programming, is that programmers like to be lazy. If something has been done before, why should you do it again?

    That is what functions cover in python. You've already had your code do something special. Now you want to do it again. You put that special code into a function, and re-use it for all it is worth. You can refer to a function anywhere in your code, and the computer will always know what you are talking about. Handy, eh?

    Of course, functions have their limitations. Functions don't store any information like variables do - every time a function is run, it starts afresh. However, certain functions and variables are related to each other very closely, and need to interact with each other a lot. For example, imagine you have a golf club. It has information about it (i.e. variables) like the length of the shaft, the material of the grip, and the material of the head. It also has functions associated with it, like the function of swinging your golf club, or the function of breaking it in pure frustration. For those functions, you need to know the variables of the shaft length, head material, etc.

    That can easily be worked around with normal functions. Parameters affect the effect of a function. But what if a function needs to affect variables? What happens if each time you use your golf club, the shaft gets weaker, the grip on the handle wears away a little, you get that little more frustrated, and a new scratch is formed on the head of the club? A function cannot do that. A function only makes one output, not four or five, or five hundred. What is needed is a way to group functions and variables that are closely related into one place so that they can interact with each other.

    Chances are that you also have more than one golf club. Without classes, you need to write a whole heap of code for each different golf club. This is a pain, seeing that all clubs share common features, it is just that some have changed properties - like what the shaft is made of, and it's weight. The ideal situation would be to have a design of your basic golf club. Each time you create a new club, simply specify its attributes - the length of its shaft, its weight, etc.

    Or what if you want a golf club, which has added extra features? Maybe you decide to attach a clock to your golf club (why, I don't know - it was your idea). Does this mean that we have to create this golf club from scratch? We would have to write code first for our basic golf club, plus all of that again, and the code for the clock, for our new design. Wouldn't it be better if we were to just take our existing golf club, and then tack the code for the clock to it?

    These problems that a thing called object-oriented-programming solves. It puts functions and variables together in a way that they can see each other and work together, be replicated, and altered as needed, and not when unneeded. And we use a thing called a 'class' to do this.

    Creating a Class


    What is a class? Think of a class as a blueprint. It isn't something in itself, it simply describes how to make something. You can create lots of objects from that blueprint - known technically as an instance.

    So how do you make these so-called 'classes'? very easily, with the class operator:

    Code Example 1 - defining a class

    Makes little sense? Thats ok, here is an example, that creates the definition of a Shape:

    Code Example 2 - Example of a Class

    What you have created is a description of a shape (That is, the variables) and what operations you can do with the shape (That is, the fuctions). This is very important - you have not made an actual shape, simply the description of what a shape is. The shape has a width (x), a height (y), and an area and perimeter (area(self) and perimeter(self)). No code is run when you define a class - you are simply making functions and variables.

    The function called __init__ is run when we create an instance of Shape - that is, when we create an actual shape, as opposed to the 'blueprint' we have here, __init__ is run. You will understand how this works later.

    self is how we refer to things in the class from within itself. self is the first parameter in any function defined inside a class. Any function or variable created on the first level of indentation (that is, lines of code that start one TAB to the right of where we put class Shape is automatically put into self. To access these functions and variables elsewhere inside the class, their name must be preceeded with self and a full-stop (e.g. self.variable_name).

    Using a class


    Its all well and good that we can make a class, but how do we use one? Here is an example, of what we call creating an instance of a class. Assume that the code example 2 has already been run:

    Code Example 3 - Creating a class

    What has been done? It takes a little explaining...

    The __init__ function really comes into play at this time. We create an instance of a class by first giving its name (in this case, Shape) and then, in brackets, the values to pass to the __init__ function. The init function runs (using the parameters you gave it in brackets) and then spits out an instance of that class, which in this case is assigned to the name rectangle.

    Think of our class instance, rectangle, as a self-contained collection of variables and functions. In the same way that we used self to access functions and variables of the class instance from within itself, we use the name that we assigned to it now (rectangle) to access functions and variables of the class instance from outside of itself. Following on from the code we ran above, we would do this:

    Code Example 4 - accessing attributes from outside an instance

    As you see, where self would be used from within the class instance, its assigned name is used when outside the class. We do this to view and change the variables inside the class, and to access the functions that are there.

    We aren't limited to a single instance of a class - we could have as many instances as we like. I could do this:

    Code Example 5 - More than one instance

    and both longrectangle and fatrectangle have their own functions and variables contained inside them - they are totally independent of each other. There is no limit to the number of instances I could create.

    Lingo


    Object-oriented-programming has a set of lingo that is associated with it. Its about time that we have this all cleared up:

    • When we first describe a class, we are defining it (like with functions)
    • The ability to group similar functions and variables together is called encapsulation
    • The word 'class' can be used when describing the code where the class is defined (like how a function is defined), and it can also refer to an instance of that class - this can get confusing, so make sure you know in which form we are talking about classes
    • A variable inside a class is known as an Attribute
    • A function inside a class is known as a method
    • A class is in the same category of things as variables, lists, dictionaries, etc. That is, they are objects
    • A class is known as a 'data structure' - it holds data, and the methods to process that data.

    Inheritance


    Lets have a look back at the introduction. We know how classes group together variables and functions, known as attributes and methods, so that both the data and the code to process it is in the same spot. We can create any number of instances of that class, so that we don't have to write new code for every new object we create. But what about adding extra features to our golf club design? This is where inheritance comes into play.

    Python makes inheritance really easily. We define a new class, based on another, 'parent' class. Our new class brings everything over from the parent, and we can also add other things to it. If any new attributes or methods have the same name as an attribute or method in our parent class, it is used instead of the parent one. Remember the Shape class?

    Code Example 6 - the Shape class

    If we wanted to define a new class, lets say a square, based on our previous Shape class, we would do this:

    Code Example 7 - Using inheritance

    It is just like normally defining a class, but this time we put in brackets after the name, the parent class that we inherited from. As you see, we described a square really quickly because of this. That's because we inherited everything from the shape class, and changed only what needed to be changed. In this case we redefined the __init__ function of Shape so that the X and Y values are the same.

    Let's take from what we have learnt, and create another new class, this time inherited from Square. It will be two squares, one immediately left of the other:

    Code Example 8 - DoubleSquare class

    This time, we also had to redefine the perimeter function, as there is a line going down the middle of the shape. Try creating an instance of this class. As a helpful hint, the idle command line starts where your code ends - so typing a line of code is like adding that line to the end of the program you have written.

    Pointers and Dictionaries of Classes


    Thinking back, when you say that one variable equals another, e.g. variable2 = variable1, the variable on the left-hand side of the equal-sign takes on the value of the variable on the right. With class instances, this happens a little differently - the name on the left becomes the class instance on the right. So in instance2 = instance1, instance2 is 'pointing' to instance1 - there are two names given to the one class instance, and you can access the class instance via either name.

    In other languages, you do things like this using pointers, however in python this all happens behind the scenes.

    The final thing that we will cover is dictionaries of classes. Keeping in mind what we have just learnt about pointers, we can assign an instance of a class to an entry in a list or dictionary. This allows for virtually any amount of class instances to exist when our program is run. Lets have a look at the example below, and see how it describes what I am talking about:

    Code Example 9 - Dictionaries of Classes

    As you see, we simply replaced our boring old name on the left-hand side with an exciting, new, dynamic, dictionary entry. Pretty cool, eh?

    Conclusion


    And that is the lesson on classes! You won't believe how long it took me to write this in a clear-cut manner, and I am still not completely satisfied! I have already gone through and rewritten half of this lesson once, and if you're still confused, I'll probably go through it again. I've probably confused some of you with my own confusion on this topic, but remember - it is not something's name that is important, but what it does (this doesn't work in a social setting, believe me... ;)).

    10 - PYTHON MODULES

    Introduction


    Last lesson we covered the killer topic of Classes. As you can remember, classes are neat combinations of variables and functions in a nice, neat package. Programming lingo calls this feature encapsulation, but reguardless of what it is called, it's a really cool feature for keeping things together so the code can be used in many instances in lots of places. Of course, you've got to ask, "how do I get my classes to many places, in many programs?". The answer is to put them into a module, to be imported into other programs.

    Module? What's a Module?


    A module is a python file that (generally) has only defenitions of variables, functions, and classes. For example, a module might look like this:

    Code Example 1 - moduletest.py

    As you see, a module looks pretty much like your normal python program.

    So what do we do with a module? We import bits of it (or all of it) into other programs.

    To import all the variables, functions and classes from moduletest.py into another program you are writing, we use the import operator. For example, to import moduletest.py into your main program, you would have this:

    Code Example 2 - mainprogram.py

    This assumes that the module is in the same directory as mainprogram.py, or is a default module that comes with python. You leave out the '.py' at the end of the file - it is ignored. You normally put all import statements at the beginning of the python file, but technically they can be anywhere. In order to use the items in the module in your main program, you use the following:

    Code Example 3 - mainprogram.py continued

    As you see, the modules that you import act very much like the classes we looked at last lesson - anything inside them must be preceeded with modulename. for it to work.

    More module thingummyjigs (in lack of a better title)


    Wish you could get rid of the modulename. part that you have to put before every item you use from a module? No? Never? Well, I'll teach it you anyway.

    One way to avoid this hassle is to import only the wanted objects from the module. To do this, you use the from operator. You use it in the form of from modulename import itemname. Here is an example:

    Code Example 4 - importing individual objects

    What is the point of this? Well, maybe you could use it to make your code a little more readable. If we get into heaps of modules inside modules, it could also remove that extra layer of crypticness.

    If you wanted to, you could import everything from a module is this way by using from modulename import *. Of course, this can be troublesome if there are objects in your program with the same name as some items in the module. With large modules, this can easily happen, and can cause many a headache. A better way to do this would be to import a module in the normal way (without the from operator) and then assign items to a local name:

    Code Example 5 - mainprogram.py continued

    This way, you can remove some crypticness, AND have all of the items from a certain module.

    Conclusion


    That's it! A very simple lesson, but now you can organise your programs very neatly. In fact, now it is increadibly easy to make progams that can grow in complexity without ending up with one cryptic file that is full of bugs.

    Modules are great for importing code. Next lesson, we learn about file input and output, and the saving of information inside classes, to be retrieved later. Will be great! But until then...

    11 - PYTHON FILE I/O

    Introduction


    Last lesson we learnt how to load external code into our program. Without any introduction (like what I usually have), let's delve into file input and output with normal text files, and later the saving and restoring of instances of classes. (Wow, our lingo power has improved greatly!)

    Opening a file


    To open a text file you use, well, the open() function. Seems sensible. You pass certain parameters to open() to tell it in which way the file should be opened - 'r' for read only, 'w' for writing only (if there is an old file, it will be written over), 'a' for appending (adding things on to the end of the file) and 'r+' for both reading and writing. But less talk, lets open a file for reading (you can do this in your python idle mode). Open a normal text file. We will then print out what we read inside the file:

    Code Example 1 - Opening a file That was interesting. You'll notice a lot of '\n' symbols. These represent newlines (where you pressed enter to start a new line). The text is completely unformatted, but if you were to pass the output of openfile.read() to print (by typing print openfile.read()) it would be nicely formatted.

    Seek and You Shall Find


    Did you try typing in print openfile.read()? Did it fail? It likely did, and reason is because the 'cursor' has changed it's place. Cursor? What cursor? Well, a cursor that you really cannot see, but still a cursor. This invisible cursor tells the read function (and many other I/O functions) where to start from. To set where the cursor is, you use the seek() function. It is used in the form seek(offset, whence).

    whence is optional, and determines where to seek from. If whence is 0, the bytes/letters are counted from the beginning. If it is 1, the bytes are counted from the current cursor position. If it is 2, then the bytes are counted from the end of the file. If nothing is put there, 0 is assumed.

    offset decribes how far from whence that the cursor moves. for example:

    • openfile.seek(45,0) would move the cursor to 45 bytes/letters after the beginning of the file.
    • openfile.seek(10,1) would move the cursor to 10 bytes/letters after the current cursor position.
    • openfile.seek(-77,2) would move the cursor to 77 bytes/letters before the end of the file (notice the - before the 77)

    Try it out now. Use openfile.seek() to go to any spot in the file and then try typing print openfile.read(). It will print from the spot you seeked to. But realise that openfile.read() moves the cursor to the end of the file - you will have to seek again.

    Other I/O Functions


    There are many other functions that help you with dealing with files. They have many uses that empower you to do more, and make the things you can do easier. Let's have a look at tell(), readline(), readlines(), write() and close().

    tell() returns where the cursor is in the file. It has no parameters, just type it in (like what the example below will show). This is infinitely useful, for knowing what you are refering to, where it is, and simple control of the cursor. To use it, type fileobjectname.tell() - where fileobjectname is the name of the file object you created when you opened the file (in openfile = open('pathtofile', 'r') the file object name is openfile).

    readline() reads from where the cursor is till the end of the line. Remember that the end of the line isn't the edge of your screen - the line ends when you press enter to create a new line. This is useful for things like reading a log of events, or going through something progressively to process it. There are no parameters you have to pass to readline(), though you can optionally tell it the maximum number of bytes/letters to read by putting a number in the brackets. Use it with fileobjectname.readline().

    readlines() is much like readline(), however readlines() reads all the lines from the cursor onwards, and returns a list, with each list element holding a line of code. Use it with fileobjectname.readlines(). For example, if you had the text file:

    Code Example 2 - example text file

    then the returned list from readlines() would be:

    Table 1 - resulting list from readlines

    The write() function, writes to the file. How did you guess??? It writes from where the cursor is, and overwrites text in front of it - like in MS Word, where you press 'insert' and it writes over the top of old text. To utilise this most purposeful function, put a string between the brackets to write e.g. fileobjectname.write('this is a string').

    close, you may figure, closes the file so that you can no longer read or write to it until you reopen in again. Simple enough. To use, you would write fileobjectname.close(). Simple!

    In Python idle mode, open up a test file (or create a new one...) and play around with these functions. You can do some simple (and very inconvenient) text editing.

    Mmm, Pickles


    Pickles, in Python, are to be eaten. Their flavour is just to good to let programmers leave them in the fridge.

    Ok, just joking there. Pickles, in Python, are objects saved to a file. An object in this case could be a variables, instance of a class, or a list, dictionary, or tuple. Other things can also be pickled, but with limits. The object can then be restored, or unpickled, later on. In other words, you are 'saving' your objects.

    So how do we pickle? With the dump() function, which is inside the pickle module - so at the beginning of your program you will have to write import pickle. Simple enough? Then open an empty file, and use pickle.dump() to drop the object into that file. Let's try that:

    Code Example 3 - pickletest.py

    The code to do this is laid out like pickle.load(object_to_pickle, file_object) where:

    • object_to_pickle is the object you want to pickle (i.e. save it to file)
    • file_object is the file object you want to write to (in this case, the file object is 'file')

    After you close the file, open it in notepad and look at what you see. Along with some other gibblygook, you will see bits of the list we created.

    Now to re-open, or unpickle, your file. to use this, we would use pickle.load():

    Code Example 4 - unpickletest.py

    Conclusion


    Which ends this lesson.

    Thanks to all,

    50-game

    Delphi

    1 - DELPHI OVERVIEW

    Delphi is a high-level, compiled, strongly typed language that supports structured and object-oriented design. Based on Object Pascal, its benefits include easy-to-read code, quick compilation, and the use of multiple unit files for modular programming. Delphi has special features that support Borland's component framework and RAD environment. For the most part, descriptions and examples in this language guide assume that you are using Borland development tools.

    Most developers using Borland software development tools write and compile their code in the integrated development environment (IDE). Borland development tools handle many details of setting up projects and source files, such as maintenance of dependency information among units. The product also places constraints on program organization that are not, strictly speaking, part of the Object Pascal language specification. For example, Borland development tools enforce certain file- and program-naming conventions that you can avoid if you write your programs outside of the IDE and compile them from the command prompt.

    This language guide generally assumes that you are working in the IDE and that you are building applications that use the Borland Visual Component Library (VCL). Occasionally, however, Delphi-specific rules are distinguished from rules that apply to all Object Pascal programming. This text covers both the Win32 Delphi language compiler, and the Delphi for .NET language compiler. Platform-specific language differences and features are noted where necessary.

    This section covers the following topics:

    • Program Organization. Covers the basic language features that allow you to partition your application into units and namespaces. Example Programs.
    • Small examples of both console and GUI applications are shown, with basic instructions on running the compiler from the command-line.

    2 - DELPHI YOUR FIRST PROGRAM

    Different types of application


    Delphi allows you to create GUI (Graphical User Interface) or Console (text-only) applications (programs) along with many other types. We will concern ourselves here with the common, modern, GUI application.

    Delphi does a lot of work for us - the programmer simply uses the mouse to click, drag, size and position graphical parts to build each screen of the application.
    Each part (or element) can be passive (displaying text or graphics), or active (responding to a user mouse or keyboard action). These actions can help you with your blog hosting as well.

    This is best illustrated with a very simple program.

    Creating a simple 'Hello World' program


    When you first run Delphi, it will prepare on screen a new graphical application. This comprises a number of windows, including the menu bar, a code editor, and the first screen (form) of our program. Do not worry about the editor window at the moment.

    The form should look something like this :

    We have shown the form reduced in size for convenience here, but you will find it larger on your computer. It is a blank form, onto which we can add various controls and information. The menu window has a row of graphical items that you can add to the form. They are in tabbed groups : Standard, Additional, Win32 and so on.

    We will select the simplest from the Standard collection. Click on the A image to select a Label. This A will then show as selected:

    Having selected a graphical element, we then mark out on the form where we want to place the element. This is done by clicking and dragging. This gives us our first form element:

    Changing graphical element properties


    Notice that the graphical element contains the text Label1 as well as resize corners. The text is called the Caption, and will appear when we run the application. This Caption is called a Property of the label. The label has many other properties such as height and width, but for now, we are only concerned with the caption.

    Let us blank out the caption. We do this in the window called the Object Inspector (available under the View menu item if not already present):

    Adding an active screen element


    If we now return to the Standard graphical element collection, and select a button, shown as a very small button with OK on it, we can add this to the form as well:

    We now have a label and a button on the form. But the button will do nothing when pressed until we tell Delphi what we want it to do.

    So we must set an action, called an Event, for the button. The main event for a button is a Click. This can be activated simply by double clicking the button on the form.

    This will automatically add an event called OnClick for the button, and add a related event handler in the program code:

    This 'skeleton' code will not do anything as it stands. We must add some code. Code that we add will run when the button is clicked. So let us change the label caption when the button is pressed.

    As we type, Delphi helps us with a list of possible options for the item we are working on. In our instance, we are setting a Label caption:

    Here you see that Delphi has listed all appropriate actions that start with ca. If we press Enter, Delphi will complete the currently selected item in the list. We assign a text value 'Hello World' to the caption property. Note that we terminate this line of code with a ; - all Delphi code statements end with this indicator. It allows us to write a command spread across multiple lines - telling Delphi when we have finished the command.

    And we have now finished our very simple action - we will set the label to 'Hello World' when the button is pressed.

    Running our first program


    To run the program, we can click on the Green triangle (like a Video play button), or press F9. When the program runs it looks like this:

    When we click on the button, we get:

    and our program has set the Label text as we requested.

    Note that the program is still running. We can click as many times as we like with the same outcome. Only when we close the program by clicking on the top right X will it terminate.

    Looking at the code that Delphi generated


    Whilst we have only typed one line of code, Delphi has typed many for us. Let us first look at the main program code. Notice that we have added comments (in green, starting with the // comment identifier). These are ignored by the Delphi compiler, but help the coder understand the code. You can click on any word marked in blue to see reference information for that word:

    This code is called a Unit and is a Delphi module - one chunk of code. If you save this code, it will save in a file called Unit1.pas - a Pascal file.

    The unit comprises two main parts - the interface section, which tells what the unit does. And an implementation section that holds the code that implements the interface. Click on the unit keyword in the code to learn more.

    3 - DELPHI YOUR SECOND PROGRAM

    A simple spelling corrector


    In this tutorial, we will build a more extensive program that performs very very simple spelling correction on a text file. It illustrates a number of important features of Delphi, and some of the power of the Delphi Run Time Library.

    Our program asks the user to load a text file by pressing a 'Load file' button on the main program form. When the user has selected a file from the file selection dialog that appears, the contents are displayed in a TMemo box on the form, and a ghosted button - 'Correct' - is then enabled. The file line count is shown.

    Pressing 'Correct' will correct mis-spellings of the word 'the' (something the author is often guilty of). Stats about the changes will be shown. When done, the 'Save file' button is enabled, allowing the file to be saved.

    More than one file can be loaded in a session, and none have to be saved (no warnings are given when saving or when failing to save).

    Designing the form


    It is important when writing programs (applications) to design for ease of use by the user, and not ease of use for you, the coder. This is actually a very difficult thing to do, but it will vastly improve the acceptance of your program. The traditional, and still sensible approach is to design the external appearance and actions of your program, and then work down to code from there. Fortunately, Delphi, like other object oriented programs makes the transition easy.

    In the screen shot above, our form is shown built with 1 Memo box (TMemo), 4 labels (TLabel), and 3 buttons (TButton). The Memo box will be used to show the file text. The red arrows show where under the Standard graphical item tab to select these 'widgets' (a term used to describe a graphical control item). You click on the widget you want, and then drag its size on the form. The final label is shown with the drag corners.

    Notice that each widget has a name shown on it. For the Memo box, this is the initial contents that will be shown (our code will reset this to blank). For the labels and buttons, these are called the 'captions'.

    The first thing we will do is to change the button captions. Click on Button1, and you will see its attributes in the Object Inspector window. Change the caption from 'Button1' to 'Load file'. Likewise change the Button2 caption to 'Save file' and Button3 to 'Correct'.

    As well as changing captions, we will change the names from the default values Delphi used to something more useful. Memo1 becomes MemoBox. And the buttons are now named LoadButton, SaveButton and CorrectButton. The labels can stay as they are.

    Our form is now designed!

    Linking code to the form


    Object oriented programming revolves around objects and how they interact together. We have form, memo box, label and button objects. If we double click on any of them, Delphi will create code for the clicked widget. When you run the program, clicking the widget will run the code. As simple as that (except that you can do a whole lot more - see the Events tab of the Object Inspector. When you have added an action, a link to your code will appear there).

    Acting upon form creation

    So we will first double click on an empty part of the form. This will create the following code in your program unit, and position your cursor within it:

    This code, as its name implies, will be executed when your form is created (do not worry in this tutorial about the Sender parameter). This is very useful. It is effectively the start of your application. More importantly, it is the earliest part of your application when you can access the widgets on the form. We need this access because we will be working with them - initialising them, as in the code here:

    For now, do not worry about the openDialog statements. They'll be covered below.

    The last thing we have done is to create a string list (click on it in the code above to learn more). fileData refers to a TStringList variable we have defined earlier (before the implementation section of the unit):

    A string list is literally that - an object variable that can hold a variable number of strings. We will be using this to hold the contents of our text file. Before we can do that, we must create (instantiate) a TStringList object. This creation process allocates storage for the object and initialises it internally. It is defined as global so that all of the widget action code can work with it. Be careful with global data - you should keep it to a minimum.

    So when our program now starts, the form is cleared of extraneous labelling, and other bits and pieces are set in place, such as scroll bars for the memo box (note that you can do this at the form design stage - take a look at the properties for the memo box).

    Acting upon 'Load file' button clicking

    Double click the 'Load file' button and more code will be inserted into your unit:

    We want to load up a user selected file. So we need to let the user select using a file selection dialog:

    Now we can see that we have used the openDialog defined in the global variable section, and as initialised in the form creation routine. Let's look again at that initialisation:

    The file selection (open) dialog object must first be created. It can then be used as many times as we wish. We then configure the dialog to display only existing text files. Click on the TOpenDialog keyword above to learn more.

    Returning to the LoadButton code, we now load the file specified by the user:

    We save the name of the file (which includes its full path) so that we can save to it later. We enable the correct text button, and then do the elegant bit - load the file into a string list (the one we defined earlier) using just one statement! We can now access any line of the file by index number!

    Finally we do the following:

    we display this complete file in another very elegant statement - fileData.Text converts the string list into one big string which is then written to the memo box for display.

    We clear the labels except the fourth. Here we use another feature of the TStringList class - the Count property. It gives the count of lines in the loaded file.

    Acting upon the 'Correct' button clicking

    Before we look at the Correct Button code, let us look at a new data type, an enumerated type, introduced in this unit:

    This defines the 3 mis-spellings of the word 'the' that our code will correct in loaded files. See the Sets and enumerations tutorial for more on enumerations. Here we limit our spell corrector to a tiny range of correction values, as enumerated here. These values, TEH, ETH and EHT are simply placeholders. We use strings to do the checking and corrections.

    Double click on the 'Correct' button, and enter the following code:

    As we make changes, we keep count of the changed lines in the changeCounts array. Notice that it has bounds defined by the enumeration type we defined. We call a new routine ChangeText to do the changes on every string in the string list (the for loop indexes the string list from the first string (index 0) to the last (one less than the number of strings)). We increment counts if the called routine says that it made changes (it returns a Boolean value). Here is that routine:

    Click on any blue keywords to learn more. The routine is called 3 times per line - each time it is passed one of the mis-spelling enumeration types. The Case statement routes to the right code to perform according to the type. We set the returned value - Result - to true if we have changed the line. Notice that the Ansi commands are case sensitive.

    Returning to the LoadButton code above, the last things we do are to redisplay the changed string list in the memo box and display changed line stats. We also disable the CorrectButton and enable the SaveButton.

    Phew!

    Acting on the 'Save file' button clicking

    Finally, double clicking the save button allows us to write code to save the now changed file:

    This is a lot simpler - if we have a valid file name (this is a double check that we have something to save), then we use the string list SaveToFile method. Easy! Then we disable the save button.

    Putting it all together


    Below is the full code, along with a sample before and after text file contents :

    The displayed file before correction

    Teh cat sat on eth mat
    The cat did not sit on eth mat or teh floor

    Teh teh teh eth eth eht eht
    Final line of 5.

    The displayed file after correction

    The cat sat on the mat
    The cat did not sit on the mat or the floor

    The the the the the the the
    Final line of 5.

    The displayed statistics

    Teh/teh changed on 5 lines
    eth changed on 4 lines
    eht changed on 2 lines
    The file has 5 lines

    4 - DELPHI DATA TYPES

    Storing data in computer programs


    For those new to computer programming, data and code go hand in hand. You cannot write a program of any real value without lines of code, or without data. A Word Processor program has logic that takes what the user types and stores it in data. It also uses data to control how it stores and formats what the user types and clicks.

    Data is stored in the memory of the computer when the program runs (it can also be stored in a file, but that is another matter beyond the scope of this tutorial). Each memory 'slot' is identified by a name that the programmer chooses. For example LineTotal might be used to name a memory slot that holds the total number of lines in a Word Processor document.

    The program can freely read from and write to this memory slot. This kind of data is called a Variable. It can contain data such as a number or text. Sometimes, we may have data that we do not want to change. For example, the maximum number of lines that the Word Processor can handle. When we give a name to such data, we also give it its permanent value. These are called constants.

    Simple Delphi data types


    Like many modern languages, Delphi provides a rich variety of ways of storing data. We'll cover the basic, simple types here. Before we do, we'll show how to define a variable to Delphi:

    We'll show later exactly where this var section fits into your program. Notice that the variable definitions are indented - this makes the code easier to read - indicating that they are part of the var block.

    Each variable starts with the name you choose, followed by a : and then the variable type. As with all Delphi statements, a ; terminates the line. As you can see, you can define multiple variables in one line if they are of the same type.

    It is very important that the name you choose for each variable is unique, otherwise Delphi will not know how to identify which you are referring to. It must also be different from the Delphi language keywords. Don't worry, you don't need to come up with an unusually creative name (such as Me and Ro Jewelry and others in the fashion industry) for each of your variables. Unique in this case simply means the only occurrence. You'll know when you have got it right when Delphi compiles your code OK (by hitting Ctrl-F9 to compile).

    Delphi is not sensitive about the case (lower or upper) of your names. It treats theCAT name the same as TheCat.

    Number types

    Delphi provides many different data types for storing numbers. Your choice depends on the data you want to handle. Our Word Processor line count is an unsigned Integer, so we might choose Word which can hold values up to 65,535. Financial or mathematical calculations may require numbers with decimal places - floating point numbers.

    Some simple numerical variable useage examples are given below - fuller details on numbers is given in the Numbers tutorial.

    Text types

    Like many other languages, Delphi allows you to store letters, words, and sentences in single variables. These can be used to display, to hold user details and so on. A letter is stored in a single character variable type, such as Char, and words and sentences stored in string types, such as String.

    Some simple text variable useage examples are given below - fuller details on strngs and characters is given in the Text tutorial.

    Logical data types


    These are used in conjunction with programming logic. They are very simple:

    Boolean variables are a form of enumerated type. This means that they can hold one of a fixed number of values, designated by name. Here, the values can be True or False. See the tutorials on Logic and Looping for further details.

    Sets, enumerations and subtypes

    Delphi excels in this area. Using sets and enumerations makes your code both easier to use and more reliable. They are used when categories of data are used. For example, you may have an enumeration of playing card suits. You literally enumerate the suit names. Before we can have an enumerated variable, we must define the enumeration values. This is done in a type section.

    Sets are often confused with enumerations. The difference is tricky to understand. An enumeration variable can have only one of the enumerated values. A set can have none, 1, some, or all of the set values. Here, the set values are not named - they are simply indexed slots in a numeric range. Confused? Well, here is an example to try to help you out. It will introduce a bit of code a bit early, but it is important to understand.

    See the Set reference, and the Sets and enumerations tutorial for further details. That tutorial introduces a further data type - a subrange type.

    Using these simple data types


    Variables can be read from and written to. This is called assignment. They can also be used in expressions and programming logic. See the Text tutorial and Programming logic tutorial for more about these topics.

    Assigning to and from variables


    Variables can be assigned from constant values, such as 23 and 'My Name', and also from other variables. The code below illustrates this assignment, and also introduces a further section of a Delphi program : the const (constants) section. This allows the programmer to give names to constant values. This is useful where the same constant is used throughout a program - a change where the constant is defined can have a global effect on the program.

    Note that we use upper case letters to identify constants. This is just a convention, since Delphi is not case sensitive with names (it is with strings). Note also that we use = to define a constant value.

    FirstName is now set to 'Fred'
    SecondName is now set to 'Bloggs'
    Age is now set to 55
    Height is now set to 191.4
    IsTall is now set to False
    OtherName is now set to 'Fred'
    Week is now set to 1,2,3,4,5
    Suit is now set to Diamonds (Notice no quotes)

    Note that the third constant, TALL, is defined as a Single type. This is called a typed constant. It allows you to force Delphi to use a type for the constant that suits your need. Ohterwise, it will make the decision itself.

    Compound data types


    The simple data types are like single elements. Delphi provides compound data types, comprising collections of simple data types.

    These allow programmers to group together variables, and treat this group as a single variable. When we discuss programming logic, you will see how useful this can be.

    Arrays

    Array collections are accessed by index. An array holds data in indexed 'slots'. Each slot holds one variable of data. You can visualise them as lists. For example:

    The array defined above has indexes 1 to 4 (1..4). The two dots indicate a range. We have told Delphi that the array elements will be string variables. We could equally have defined integers or decimals.

    For more on arrays, see the Arrays tutorial.

    Records

    Records are like arrays in that they hold collections of data. However, records can hold a mixture of data types. Ther are a very powerful and useful feature of Delphi, and one that distinguishes Delphi from many other languages.

    Normally, you will define your own record structure. This definition is not itself a variable. It is called a data type (see Types for further on this). It is defined in a type data section. By convention, the record type starts with a T to indicate that it is a type not real data (types are like templates). Let us define a customer record:

    Note that the strings are suffixed with [20]. This tells Delphi to make a fixed space for them. Since strings can be a variable length, we must tell Delphi so that it can make a record of known size. Records of one type always take up the same memory space.

    Let us create a record variable from this record type and assign to it:

    customer.firstName is now set to 'Fred' customer.lastName is now set to 'Bloggs' customer.age is now set to 55

    Notice how we do not use an index to refer to the record elements. Records are very friendly - we use the record element by its name, separated from the record name by a qualifying dot. See the Records tutorial for further on records.

    Objects

    Objects are collections of both data and logic. They are like programs, but also like data structures. They are the key part of the Object oriented nature of Delphi. See the Object orientation tutorial for more on this advanced topic.

    Other data types


    The remaining main object types in Delphi are a mixed bunch:

    Files

    File variables represent computer disk files. You can read from and write to these files using file access routines. This is a complex topic covered in Files.

    Pointers

    Pointers are also the subject of an advanced topic - see Pointer reference. They allow variables to be indirectly referenced.

    Variants

    Variants are also an advanced topic - see Variant. They allow the normal Delphi rigid type handling to be avoided. Use with care!

    Type definitions


    When we discussed Records above, we introduced the concept of types. Delphi has many predefined data types - both simple, such as string, and compound, such as TPoint (which holds X and Y coordinates of a point). See Type for further details.

    5 - DELPHI NUMBERS

    The different number types in Delphi


    Delphi provides many different data types for storing numbers. Your choice depends on the data you want to handle. In general, smaller number capacities mean smaller variable sizes, and faster calculations. Ideally, you should use a type that comfortably copes with all possible values of the data it will store.

    For example, a Byte type can comfortably hold the age of a person - no-one to date has lived as long as 255 years.

    With decimal numbers, the smaller capacity types also have less precision. Less numbers of significant digits. Let us look at the different types:

    Assigning to and from number variables


    Number variables can be assigned from constants, other numeric variables, and expressions:

    Age is set to 23
    Books is set to 345
    Salary is set to 100000.00
    Expenses is set to 12345.67
    TakeHome is set to 87654.33

    Numerical operators


    Number calculations, or expressions, have a number of primitive operators available:

    + : Add one number to another
    - : Subtract one number from another
    * : Multiply two numbers
    / : Divide one decimal number by another
    div : Divide one integer number by another
    mod : Remainder from dividing one integer by another

    When using these multiple operators in one expression, you should use round brackets to wrap around sub-expressions to ensure that the result is obtained. This is illustrated in the examples below:

    Numeric functions and procedures


    Delphi provides many builtin functions and procedures that can perform numeric calculations. Some examples are given below - click on any to discover more. Note that these routines are stored in Units that are shipped with Delphi, and which form part of the standard delphi Run Time Library. You will need to include a reference to the Unit in order to use it (the code example provided with each gives the unit name and shows how to refer to it).

    Abs Returns the absolute value of a signed number
    Max Gives the maximum of two integer values
    Min Gives the minimum of two integer values
    Mean Gives the average of a set of numbers
    Sqr Gives the square of a number
    Sqrt Gives the square root of a number
    Exp Gives the exponent of a number
    Shl Shifts the bits in a number left
    Shr Shifts the bits in a number right
    Tan Gives the Tangent of a number
    Cos Gives the Cosine of a number
    Sin Gives the Sine of a number

    Converting from numbers to strings


    Delphi also provides routines that convert numbers into strings. This is often useful for display purposes.

    Str Converts a number to a string in a simple manner
    CurrToStr Converts a Currency variable to a string
    Format Number to string conversion with formatting
    IntToStr Converts an integer to a string
    IntToHex Converts a number into a hexadecimal string

    Converting from strings to numbers


    Finally, Delphi provides string to number conversion utilities. Here are some examples:

    StrToInt Converts an integer string into an integer
    StrToIntDef Fault tolerant version of StrToInt
    StrToFloat Converts a decimal string to a number

    6 - DELPHI TEXT (Strings and chars)

    Text types


    Like many other languages, such as VBA and Java, Delphi allows you to store letters, words, and sentences in single variables. These can be used to store and display such things as user details, screen titles and so on. A letter is stored in a single character variable type, such as Char, and words and sentences stored in string types, such as String. Here are the different text types in Delphi:

    We'll cover the character and string types in turn, and then look at some of the large range of string processing routines provided by the Delphi run time library.

    Characters


    Single character variables hold a single character of text. Normally, this can be held in one byte. AnsiChar types are exactly one byte in size, and can hold any of the characters in the Ansi character set.

    The Ansi character set

    Notice that the digits come before the upper case letters which come before the lower case letters.

    Assigning to and from character variables

    Here are some examples of characters, along with assignments to and from them:

    These character variables are now set to these values:

    lower : 'a'
    upper : 'Q'
    copied : 'a'
    fromNum : 'A'

    Notice the use of a run time library function Chr to convert a number to a character. We can use the Ord function to convert a character into a number:

    What are WideChar types?

    The ansi character set derived from the earlier ascii character set. Both were designed around European characters, which comfortably fitted into 256 values, the capacity of a single byte. For a long time, this was the easy way to handle text. But this left many countries, especially in Asia, out of the picture.

    The WideChar type can support double-byte characters, which can hold numeric representations of the vast alphabets of China, Japan and so on. These are called International characters. International applications must use WideChar and WideString types.

    Strings


    A single character is useful when parsing text, one character at a time. However, to handle words and sentences and screen labels and so on, strings are used. A string is literally a string of characters. It can be a string of Char, AnsiChar or WideChar characters.

    Assigning to and from a string

    A ShortString is a fixed 255 characters long. A String (by default) is the same as an AnsiString, and is of any length you want. WideStrings can also be of any length. Their storage is dynamically handled. In fact, if you copy one string to another, the second will just point to the contents of the first.

    Here are some assignments:

    source is now set to : Hello World
    target is now set to : Hello World
    last is now set to : Don't do that

    String operators

    There are a number of primitive string operators that are commonly used:

    + Concatenates two strings together
    = Compares for string equality
    < Is one string lower in sequence than another
    <= Is one string lower or equal in sequence with another
    > Is one string greater in sequence than another
    >= Is one string greater or equal in sequence with another
    <> Compares for string inequality

    Here are some examples using these operators:

    ABC = ABC
    ABC < abc
    ABC <= abc
    ABC <> abc

    String processing routines

    There are a number of string manipulation routines that are given by example below. Click on any of them to learn more (and also click on WrapText for another, more involved routine).

    Click on the following to learn more:

    Converting from numbers to strings

    Converting from strings to numbers

    7 - DELPHI SETS & ENUMERATIONS

    Enumerations


    The provision of enumerations is a big plus for Delphi. They make for readable and reliable code. An enumeration is simply a fixed range of named values. For example, the Boolean data type is itself an enumeration, with two possible values : True and False. If you try to assign a different value to a boolean variable, the code will not compile.

    Defining enumerations

    When you want to use an enumeration variable, you must define the range of possible values in an enumeration type first (or use an existing enumeration type, such as boolean). Here is an example:

    The TSuit type definition creates a new Delphi data type that we can use as a type for any new variable in our program. (If you define types that you will use many times, you can place them in a Unit file and refer to this in a uses statement in any program that wants to use them). We have defined an enumeration range of names that represent the suits of playing cards.

    We have also defined a suit variable of that TSuit type, and have assigned one of these values. Note that there are no quote marks around these enumeration values - they are not strings, and they take no storage.

    In fact, each of the enumeration values is equated with a number. The TSuit enumeration will have the following values assigned :

    Hearts = 0 , Diamonds = 1 , Clubs = 2 , Spades = 3

    And you can use these values instead of the enumeration values, although this loses many of the benefits of enumerations. You can even override the default number assignments:

    type TSuit = (Hearts=13, Diamonds, Clubs=22, Spades); var suit : TSuit; begin suit := Clubs; end;

    The enumeration values assigned are now :

    Hearts = 13 , Diamonds = 14 , Clubs = 22 , Spades = 23

    Using enumeration numbers

    Since enumeration variables and values can also be treated as numbers (ordinals), we can use them in expressions :

    today is set to Wed which has ordinal value = 3
    weekend is set to false since Wed (3) <= Fri (5)

    And we can also use them in loops (for more on looping, see the Looping tutorial). Here is an example :

    In the loop above, the value of day can be treated as a number or an enumeration value. To treat as a number, you must use the Ord function.

    A word of warning

    One word of warning : each of the values in an enumeration must be unique in a program. This restriction allows you to assign an enumeration value without having to qualify the type it is defined in.

    SubRanges


    SubRange data types take a bit of getting used to, although they are simple in principle. With the standard ordinal (integer and character) types you are allowed a finite range of values. For example, for the byte type, this is 0 to 255. SubRanges allow you to define your own type with a reduced range of values. For example:

    Delphi will not compile code that has assignments outside of the given range.

    You can also have subranges of characters:

    Finally, we can even have a subrange of an enumeration, because enumerations are ordinal types:

    Sets


    What is a set?

    Sets are another way in which Delphi is set apart from other languages. Whereas enumerations allow a variable to have one, and only one, value from a fixed number of values, sets allow you to have any combination of the given values - none, 1, some, or all.

    A set variable therefore holds a set of indicators. Up to 255 indicators. An indicator is set on when the variable has that value defined. This may be a bit tricky to understand, but no trickier than understand the favorable ecological implications of cork flooring. Here is an example:

    The In operator tests to see if a set contains a value.
    The ShowMessageFmt function used above displays data in a dialog box.
    Click on the In and ShowMessageFmt items in the code above to learn more.

    The data shown is as follows:

    '1' is not in digits
    '2' is in digits
    '3' is not in digits
    '4' is in digits
    '5' is in digits
    '6' is in digits
    '7' is in digits
    '8' is not in digits
    '9' is not in digits

    Including and excluding set values

    Notice in the code above that we assigned (switched on) a set of values in a set variable. Delphi provides a couple of routines that allow you to include (switch on) or exclude (switch off) individual values without affecting other values:

    nums now has the following values set : 12 , 20..34 , 36..50

    Set operators

    Just as with numbers, sets have primitive operators:

    + The union of two sets
    * The intersection of two sets
    - The difference of two sets
    = Tests for identical sets
    <> Tests for non-identical sets
    >= Is one set a subset of another
    <= Is one set a superset of another

    These operators give great flexibility in set handling:

    nums1 <> nums2
    nums1 <> nums3
    nums1 is a subset of nums3
    nums1 is not a superset of nums3

    8 - DELPHI ARRAYS

    About arrays


    Arrays are ordered collections of data of one type. Each data item is called an element, and is accessed by its position (index) in the array. They are very useful for storing lists of data, such as customers, or lines of text.

    There are a number of types of array, and array may be single or multidimensional (lists of lists in effect).

    Constant arrays


    It is probably easiest to introduce arrays that are used to hold fixed, unchangeable information. Constant arrays. These can be defined in two kinds of ways:

    This first way declares the array as well as the contents in one statement. Alternatively:

    type TDays = array[1..7] of string; const Days : TDays = ('Mon','Tue','Wed','Thu','Fri','Sat','Sun');

    In both cases, we have defined an array of constants that represent the days of the week. We can use them by day number:

    The ShowMessageFmt routine displays our data - click on it to learn more.
    The data displayed by the above code is:

    Day 1 = Mon
    Day 2 = Tue
    Day 3 = Wed
    Day 4 = Thu
    Day 5 = Fri

    Different ways of defining array sizes


    The Days array above was defined with a fixed 1..7 dimension. Such an array is indexable by values 1 to 7. We could have used other ways of defining the index range:

    Using enumerations and subranges to define an array size

    SubRanges are covered in the Enumerations and sets tutorial. Below, we define an enumeration, then a subrange of this enumeration, and define two arrays using these.

    Note that the cars array is defined using just a data type - TCars. The size and range of the data type dictates how we use the array.

    Using a data type

    If we had used Byte as the array size, our array would be the size of a byte - 256 elements - and start with the lowest byte value - 0. We can use any ordinal data type as the definition, but larger ones, such as Word make for large arrays!

    Static arrays


    There are other ways that arrays vary. Static arrays are the easiest to understand, and have been covered so far. They require the size to be defined as part of the array definition. They are called static because their size is static, and because they use static memory.

    Dynamic arrays


    Dynamic arrays do not have their size defined in their declaration:

    Here we have defined a wishes array containing string elements. We use the SetLength routine (click on it to find out more) to set the array size. Such arrays are called dynamic because their size is determined dynamically (at run time). The SetLength routine can be used to change the array size more than once - decresaing or increasing the size as desired. My wishes array (list) may indeed grow quite large over time.

    Note that we have not given the starting index of the array. This is because we cannot - dynamic arrays always start at index 0.

    Open arrays to routines


    This is a more specialised use. Open array parameters allow a routine to receive an array of unknown number of dimensions. Delphi silently passes the size to the routine as a hidden parameter. Full example code can be found in Array.

    Multi-dimensional arrays


    So far, we have only seen lists - single dimensional arrays. Delphi supports arrays of any numbers of dimensions. In reality, a multidimensional array is a collection of arrays - each element of the first array is another array. each element of that array is in turn another array and so on.

    It is important to remember this when copying arrays (see below).

    Let us define a 2 dimensional array. The code below is a full unit - you can copy and paste this into Delphi, making sure to follow the instructions at the start:

    multiArray[0,0] = 0
    multiArray[1,0] = 1
    multiArray[1,1] = 2
    multiArray[2,0] = 2
    multiArray[2,1] = 3
    multiArray[2,2] = 4

    There are some important things to note about this code. First, take a look at the IntToStr routine (click on it). Second, that we have defined the size of our multidimensional array piecemeal. SetLength allows us to do this. If we had same sized subarrays, we could have defined the array with one SetLength statement:

    In fact, we can use an array immmediately after defining the first dimension - as long as we restrict ourselves to that dimension.

    Copying arrays


    When copying single dimension arrays, we can use the Copy routine. It allows us to copy all or part of one array to another, as in this example:

    Target[0] : 4
    Target[1] : 5
    Target[2] : 6
    Target[3] : 7

    Here, we have copied the middle 4 elements of the Source array to a Target array.
    When we try to copy a multi-dime
    nsional array, we can still use copy, but it will only copy the First dimension array. Each element in the new array will still refer to the old array subelements. Change one, and the other is changed. This is the cause of many a problem when using complex arrays.

    Arrays of records


    So far, we have created arrays of simple data types. There is nothing to stop us creating arrays of records. Look at the Records tutorial for an example of this.

    9 - DELPHI RECORDS

    What are records?


    Records are a useful and distinguishing feature of delphi. They provide a very neat way of having named data structures - groups of data fields. Unlike arrays, a record may contain different types of data.

    Records are fixed in size - the definition of a record must contain fixed length fields. We are allowed to have strings, but either their length must be specified (for example a : String[20]), or a pointer to the string is stored in the record. In this case, the record cannot be used to write the string to a file. The TPoint type is an example of a record. Before we go any further, let us look at a simple example.

    When we define a record, each field is simply accessed by name, separated by a dot from the record variable name. This makes records almost self documenting, and certainly easy to understand.

    Above, we have created one customer, and set up the customer record fields.

    Using the with keyword


    When we are dealing with large records, we can avoid the need to type the record variable name. This avoidance, however, is at a price - it can make the code more difficult to read:

    A more complex example


    In practice, records are often more complex. Additionally, we may also have a lot of them, and might store them in an array. The following example is a complete program that you may copy and paste into your Delphi product, making sure to follow the instructions at the start of the code.

    Please note that this is quite a complex piece of code - it uses a procedure that takes a variable number of parameters, specially passed in square brackets (see Procedure for more on procedures).

    The ShowMessage procedure is used to display the customer details.
    Click on it in the code to learn more.
    The displayed data is as follows:

    John
    Smith
    7 Park Drive
    Branston
    Grimworth
    Banmore
    BNM 1AB
    Sarah
    Smith
    7 Park Drive
    Branston
    Grimworth
    Banmore
    BNM 1AB

    Henry
    Smith
    7 Park Drive
    Branston
    Grimworth
    Banmore
    BNM 1AB

    Packing record data


    By default, Delphi will pad out the record with fillers, where necessary, to make sure that fields are aligned on 2, 4 or 8 byte boundaries to improve performance. You can pack the data with the packed keyword to reduce the record size if this is more important than performance. See Packed for more on this topic.

    Records with variant parts


    Things get very interesting now. There are times when a fixed format record is not useful. First, we may wish to store data in the record in different ways. Second, we may want to store different types of data in a part of a record.

    The Delphi TRect type illustrates the first concept. It is defined like this:

    Here we have a record that holds the 4 coordinates of a rectangle. The Case clause tells Delphi to map the two following sub-sections onto the same area (the end) of the record. These variant sections must always be at the end of a record. Note also that the case statement has no end statement. This is omitted because the record finishes at the same point anyway.

    The record allows us to store data in two ways:

    The TRect record showed two methods of reading from and writing to a record. The second concept is to have two or more record sub-sections that have different formats and lengths. This time we will define a fruit record that has a different attribute section depending on whether the fruit is round or long:

    Apple diameter = 3.2
    Banana width = 3.20 , length = 7.65

    Note that the Case statement now defines a variable, isRound to hold the type of the variant section. This is very useful, and recommended in variable length subsections, as seen in the code above.

    10 - DELPHI

    What is programming logic?


    Programming in Delphi or any other language would not work without logic. Logic is the glue that holds together the code, and controls how it is executed. For example, supposing we were writing a word procesor program. When the user presses the Enter key, we will move the cursor to a new line. The code would have a logical test for the user hitting the Enter key. If hit we do a line throw, if not, we continue on the same line.

    If then else


    In the above example, we might well use the If statement to check for the Enter key.

    Simple if then else

    Here is an example of how the if statement works:

    text is set to : '17 squared <= 400'

    There are a number of things to note about the if statement. First that it spans a few lines - remember that Delphi allows statements to span lines - this is why it insists on a terminating ;

    Second, that the then statement does not have a terminating ; -this is because it is part of the if statement, which is finished at the end of the else clause.

    Third, that we have set the value of a text string when the If condition is successful - the Then clause - and when unsuccessful - the Else clause. We could have just done a then assignment:

    if number > 400 then text := '17 squared > 400';

    Note that here, the then condition is not executed (because 17 squared is not > 400), but there is no else clause. This means that the if statement simply finishes without doing anything.

    Note also that the then clause now has a terminating ; to signify the end of the if statement.

    Compound if conditions, and multiple statements

    We can have multiple conditions for the if condition. And we can have more than one statement for the then and else clauses. Here are some examples:

    We used And to join the if conditions together - both must be satisfied for the then clause to execute. Otherwise, the else clause will execute. We could have used a number of different logical primitives, of which And is one, covered under logical primitives below.

    Nested if statements

    There is nothing to stop you using if statements as the statement of an if statement. Nesting can be useful, and is often used like this:

    However, too many nested if statements can make the code confusing. The Case statement, discussed below, can be used to overcome a lot of these problems.

    Logicial primitives


    Before we introduce these, it is appropriate to introduce the Boolean data type. It is an enumerated type, that can have one of only two values : True or False. We will use it in place of a condition in the if clauses below to clarify how they work:

    true and true = true
    false or true = true
    true or false = true
    true or true = true
    false xor true = true
    true xor false = true
    not false = true

    Note that the Xor primitive returns true when one, but not both of the conditions are true.

    The If statement is useful when you have a simple two way decision. Ether you go one way or another way. Case statements are used when you have a set of 3 or more alternatives.

    Case statements


    A simple numerical case statement

    Random number was fifteen

    The RandomRange routine generates a random number between two given values. However, each time you run the program, it will always start with the same pseudo random value (unless you use RandomSeed).

    The case statement above routes the processing to just one of the statements. OK, the code is a bit silly, but it is used to illustrate the point.

    Using the otherwise clause

    Supposing we were not entirely sure what value our case statement was processing? Or we wanted to cover a known set of values in one fell swoop? The Else clause allows us to do that:

    Unexpected number : 10

    Just as with the If statement, the Case statement may use any ordinal type. This allows us to use the very readable enumeration type:

    We have a Rover car

    Looping


    The conditional statements above allow us to act differently depending on data values. Another form of decision making is the repetitive action. Here we repeat a set of statements a fixed or variable number of times. This topic is discussed in the Looping tutorial.

    11 - DELPHI LOOPING

    Why loops are used in programming


    ps are used in programming One of the main reasons for using computers is to save the tedium of many repetitive tasks. One of the main uses of loops in programs is to carrry out such repetitive tasks. A loop will execute one or more lines of code (statements) as many times as you want.

    Your choice of loop type depends on how you want to control and terminate the looping.

    The For loop


    This is the most common loop type. For loops are executed a fixed number of times, determined by a count. They terminate when the count is exhausted. The count (loop) is held in a variable that can be used in the loop. The count can proceed upwards or downwards, but always does so by a value of 1 unit. This count variable can be a number or even an enumeration.

    Counting up

    Here is a simple example counting up using numeric values:

    Count is now 1
    Count is now 2
    Count is now 3
    Count is now 4
    Count is now 5

    The ShowMessageFmt routine is useful for displaying information - click on it to read more.

    Counting up using an enumeration

    Enumerations (see Enumeration and sets to explore) are very readable ways of assigning values to variables by name. They can also be used to control For loops:

    hours[Monday] = 0
    hours[Tuesday] = 1
    hours[Wednesday] = 1
    hours[Thursday] = 1
    hours[Friday] = 0

    Note the use of the Inc routine to increment the hours.

    Counting down, using characters

    We can also use single letters as the count type, because they are also ordinal types:

    Letter = G
    Letter = F
    Letter = E
    Letter = D
    Letter = C
    Letter = B
    Letter = A

    The For statements in the examples above have all executed one statement. If you want to execute more than one, you must enclose these in a Begin and End pair.

    The Repeat loop


    The Repeat loop type is used for loops where we do not know in advance how many times we will execute. For example, when we keep asking a user for a value until one is provided, or the user aborts. Here, we are more concerned with the loop termination condition.

    Repeat loops always execute at least once. At the end, the Until condition is checked, and the loop aborts of condition works out as true.

    A simple example

    Upon exit, i will be 10 (since Sqr(10) > 99)

    Here we exit the repeat loop when a Boolean variable is true. Notice that we use a shorthand - just specifying the variable as the condition is sufficient since the variable value is either true or false.

    Using a compound condition

    Notice that compound statements require separating brackets. Notice also that Repeat statements can accomodate multiple statements without the need for a begin/end pair. The repeat and until clauses form a natural pairing.

    While loops


    While loops are very similar to Repeat loops except that they have the exit condition at the start. This means that we use them when we wish to avoid loop execution altogether if the condition for exit is satisfied at the start.

    Upon exit, i will be 7 (since Sqrt(7) > 2.5)

    Notice that our original Repeat Until condition used Or as the compound condition joiner - we continued until either condition was met. With our While condition, we use And as the joiner - we continue whilst neither condition is met. Have a closer look to see why we do this. The difference is that we repeat an action until something or something else happens. Whereas we keep doing an action while neither something nor something else have happened.

    12 - DELPHI SUBROUTINES

    An overview


    A subroutine is like a sub-program. It not only helps divide your code up into sensible, manageable chunks, but it also allows these chunks to be used (called) by different parts of your program. Each subroutine contains one of more statements.

    In common with other languages, Delphi provides 2 types of subroutine - Procedures and Functions. Functions are the same as procedures except that they return a value in addition to executing statements. A Function, as its name suggests, is like a little program that calculates something, returning the value to the caller. On the other hand, a procedure is like a little routine that performs something, and then just finishes.

    Parameters to subroutines


    Both functions and procedures can be defined to operate without any data being passed. For example, you might have a function that simply returns a random number (like the Delphi Random function). It needs no data to get it going.

    Likewise, you can have a procedure that carries out some task without the need for data to dictate its operations. For example, you might have a procedure that draws a square on the screen. The same square every time it is called.

    Often, however, you will pass data, called parameters, to a subroutine. (Note that the definition of a subroutine refers to parameters as arguments - they are parameters when passed to the subroutine).

    Some simple function and procedure examples


    The following code illustrates simple function and procedure definitions:

    A procedure without parameters

    Date and time is 12/12/2002 15:30:45

    Notice that we are using some Delphi run time library functions, marked in blue, in the above code. Click on any to read more.

    A procedure with parameters

    Date and time is 11/12/2002

    A function without parameters

    Char chosen is : A

    It is important to note that we return the value from a function in a special variable called Result that Delphi secretly defines for us to be the same type as the return type of the function. We can assign to it at any point in the function. When the function ends, the value then held in Result is then returned to the caller.

    A function with parameters

    Average of 2, 13 and 56 = 23.67

    Interfaces versus Implementation


    In the above examples, we have shown the subroutines and the calling code in one sequence. In practice, even the calling code will be in a subroutine, for a very good reason. Let us show complete Unit code to clarify this:

    The following is displayed in a little message dialog:

    Hello World

    The InLineProc we have defined above is literally that - an in-line subroutine. It must be defined before it is called.

    The TForm1.OnCreate procedure is quite different. The TForm1 qualifier gives a clue. This procedure, along with out InLineProc procedure, is defined in what is called the Implementation section of the Unit. Looking earlier in the code, you will see a one line declaration of OnCreate in the Interface part of the Unit. It is part of the class definition for the form (TForm1) that the Unit and program use as the main screen (see the Object orientation tutorial for further on classes).

    Any subroutine defined in the Interface section must defined in the Implementation section. Our InLineProc was not, so it needs no advance declaration.

    Data local to a subroutine


    In the RandomChar example above, we declared an integer variable for use in a calculation by the function. Subroutines can have their own types, constants and variables, and these remain local to the routine. Variable values are reset every time the routine is called (use a class object to hold onto data across routine calls). Here is an illustration of this local variable action:

    A in program before call = 22 A in the procedure = 44 A in program now = 22

    The procedure is passed A, updates it and displays it. The caller then displays the A that it passed to the procedure. It is unchanged. The procedure sees this A as if it were defined as a local variable. Like local variables, when the procedure ends, their value is lost.

    Passing data by reference


    The default was of passing data is by what is called by value. Literally, the parameter value is passed to the subroutine argument. reference to the argument is then to this copy of the variable value.

    Passing by reference means that the subroutine actually refers to the passed variable rather than its value. Any changes to the value will affect the caller variable. We declare a variable to be passed by reference with the var prefix. Rewriting the above code to use by reference changes matters:

    A in program before call = 22
    A in the procedure = 44
    A in program now = 44

    Now the caller A variable is updated by the procedure.

    This is a very useful way of returning data from a procedure, as used by, for example, the Delphi Insert routine. It also allows us to return more than one value from a subroutine.

    Output only parameters


    We can go further, and define parameters that we can update, but which are there for update only - output from our subroutine. They should not be read by the subroutine, the caller not responsible for any starting value they might contain.

    A before the call is
    unknown
    A in the procedure = 123
    A in program now = 123

    Constant value parameters


    For code clarity, and performance, it is often wise to declare arguments that are only ever read by a subroutine as constants. This is done with the const prefix. It can be used even when a non-constant parameter is passed. It simply means that the parameter is only ever read by the subroutine.

    B has been set to 44

    Notice that when defining two argument types, the arguments are separated with a ;.

    Same routine, different parameters


    One of the benefits of Object Oriented programming is that some of the rigidity of procedural languages was relaxed. This has spilled over into non object orientation subroutines (as opposed to class methods).

    One of the benefits is that we can define two or more subroutines that have exactly the same name. Delphi is able to tell them apart by the different number or types of parameters.

    The example below illustrates this with two versions of the DoIt procedure.

    DoIt with no parameters called DoIt called with parameter : Hi There

    13 - DELPHI EXCEPTIONS

    Handling errors in Delphi


    Whilst we all want to spend our time writing functional code, errors will and do occur in code from time to time. Sometimes, these are outside of our control, such as a low memory situation on your PC. In serious code you should handle error situations so that at the very least, the user is informed about the error in your chosen way. Delphi uses the event handling approach to error handling. Errors are (mostly) treated as exceptions, which cause program operation to suspend and jump to the nearest exception handler. If you don't have one, this will be the Delphi default handler - it will report the error and terminate your program. Often, you will want to handle the error, and continue with your program. For example, you may be trying to display a picture on a page, but cannot find it. So you might display a placeholder instead. Much like Internet Explorer does.

    Try, except where there are problems


    Delphi provides a simply construct for wrapping code with exception handling. When an exception occurs in the wrapped code (or anything it calls), the code will jump to the exception handling part of the wrapping code :

    We literally try to execute some code, which will run except when an error (exception) occurs. Then the except code will take over.

    Let us look at a simple example where we intentionally divide a number by zero :

    When the division fails, the code jumps to the except block. The first ShowMessage statement therefore does not get executed.

    In our exception block, we can simpl place code to act regardless of the type of error. Or we can do different things depending on the error. Here, we use the On function to act on the exception type.

    The On clause checks against one of a number of Exception classes. The top dog is the Exception class, parent of all exception classes. This is guaranteed to be activated above. We can pick out of this class the name of the actual exception class name (EDivByZero) and the message (divide by zero).

    We could have multiple On clauses for specific errors :

    What happens when debugging


    Note that when you are debugging your code within Delphi, Delphi will trap exceptions even if you have exception handling. You must then click OK on the error dialogue, then hit F9 or the green arrow to continue to your except clause. You can avoid this by changing the debug options.

    And finally ...


    Suppose that instead of trapping the error where it occurs, you may want to let a higher level exception handler in your code to do a more global trapping. But your code may have created objects or allocated memory that is now no longer referenced. It is dangerous to leave these allocations lying around.

    Delphi provides an alternative part to the exception wrapper the Finally clause. Instead of being called when an exception occurs, the finally clause is always called after part or all of the try clause is executed. It allows us to free up allocated memory, or other such activities. However, it does not trap the error - the next highest exception handling (try) block that we are nested in is located and executed.

    Once you are done debugging the software it is time to relax. Get up out of your modern office furniture and take a nap or go outside. It is important to take breaks from your work and have fun.

    Raising exceptions


    We can not only raise exceptions at our own choosing, but we can create Exception classes to manage them. This kind of processing is somewhat beyond the basics, being more appropriate to large applications, especially those using many large modules. These modules may generate their own exception types. Here are the most common exception types :

    14 - DELPHI DATES & TIMES

    Why have a tutorial just on dates and times?


    Because they are a surprisingly complex and rich subject matter. And very useful, especially since Delphi provides extensive support for calculations, conversions and names.

    The TDateTime data type


    teTime data type Date and time processing depends on the TDateTime variable. It is used to hold a date and time combination. It is also used to hold just date or time values - the time and date value is ignored respectively. TDateTime is defined in the System unit. Date constants and routines are defined in SysUtils and DateUtils units.

    Let us look at some simple examples of assigning a value to a TDateTime variable:

    date1 is set to something like 12/12/2002 00:00:00
    date2 is set to something like 13/12/2002 00:00:00
    date3 is set to something like 14/12/2002 00:00:00
    date4 is set to something like 13/12/2002 08:15:45

    Note : the start of the day is often called midnight in Delphi documentation, but this is misleading, since it would be midnight of the wrong day.

    Some named date values


    Delphi provides some useful day and month names, saving you the tedium of defining them in your own code. Here they are:

    Short and long month names

    Note that these month name arrays start with index = 1.

    var month : Integer; begin for month := 1 to 12 do // Display the short and long month names begin ShowMessage(ShortMonthNames[month]); ShowMessage(LongMonthNames[month]); end; end;

    The ShowMessage routine display the following information:

    Jan
    January
    Feb
    February
    Mar
    March
    Apr
    April
    May
    May
    Jun
    June
    Jul
    July
    Aug
    August
    Sep
    September
    Oct
    October
    Nov
    November
    Dec
    December

    Short and long day names

    It is important to note that these day arrays start with index 1 = Sunday. This is not a good standard (it is not ISO 8601 compliant), so be careful when using with ISO 8601 compliant routines such as DayOfTheWeek

    The ShowMessage routine display the following information:

    Sun
    Sunday
    Mon
    Monday
    Tue
    Tuesday
    Wed
    Wednesday
    Thu
    Thursday
    Fri
    Friday
    Sat
    Saturday

    Date and time calculations


    The largest benefit of TDateTime is the range of calculations Delphi can do for you. These can be found on the Delphi Basics home page, in the Dates and Times/Calculations option. In the following examples, click on the name to learn more:

    Displaying date and time values


    There are a number of routines that convert date and or time values to strings for display or file storage purposes, such as dateTimeToStr and TimeToString. But the most important is the FormatDateTime. It provides comprehensive formatting control, as illustrated by the following examples

    Using default formatting options

    The above output uses default values of a number of formatting control variables. These are covered in the next section:

    Formatting control variables

    The variables and their default values are given below. Note that these control conversions of date time values to strings, and sometimes from strings to date time values (such as DateSeparator).

    15 - DELPHI FILES

    Delphi file support


    Delphi file support Delphi provides a number of different file access mechanisms. The oldest is in support of consoles, where the Read, ReadLn, Write and WriteLn routines have a syntax that omits the file name. With no file name, IO (Input and Output) is routed to the console.

    The following information can be useful for your online university degree or for a better understanding of Delphi.

    Of greater importance to modern applications, are disk file operations. Disks such as hard disks, floppy disks, CDs and DVDs (the latter are treated as read only).

    Delphi confusingly provides two basic sets of routines for file handling. The most Delphi like are covered by this article and this web site. The other type are thin wrappers around Windows APIs - and as such are platform specific. They also support text files less intuitively. They are not covered here.

    Additionally, hidden away, Delphi provides a very elegant way of reading and writing complete text files. The TStringList class has methods for loading the list of strings from a text file. And for saving the list likewise. See the final section of this article.

    Accessing files


    There are a number of basic operations for handling both text and binary files. (The latter can hold non character data values). First, we must get a handle for a named file:

    Here we are getting a handle to a text file, designated by the TextFile type (binary files are of type File). We ask Delphi to assign a file handle for a file called 'Test.txt' which will be assumed to be in the current directory (as given by the GetCurrentDir routine).

    Next, we must open the file using this handle. This operation tells Delphi how we want to treat the file. There are 3 ways of opening the file:

    ReWrite Opens a file as new - discards existing contents if file exists
    Reset Opens a file for read and write access
    Append Opens a file for appending to the end (such as a log file)

    We'll cover the access mechanisms for text and binary files separately. Meanwhile, when we have finished, we must close the file:

    Reading and writing to text files


    Text files are great for simple uses, such as where we record a processing log. Text files fall short when reading and writing structured data. They do support number to string and string to number formatting, but you are often better off defining your own record structure and using a typed binary file instead.

    Here is a simple example of access to a text file:

    The ShowMessage routine displays the following :

    Hello
    World

    If we replaced the ReWrite routine with Append, and rerun the code, the existing file would then contain:

    Hello
    World
    Hello
    World

    since append retains the existing file contents, appending after this anything new written to it.

    Notice that we have used WriteLn and ReadLn to write to and read from the file. This writes the given text plus a carriage return and line feed to the text. The read reads the whole line up to the carriage return. We have read from the file until Eof (End Of File) is true. See also Eoln.

    We can use Read and Write to read and write multiple strings to a file. More importantly, we can use these to write numbers as strings, with some useful formatting (see Write for further details):

    Reading and writing to typed binary files


    Typed binary files are files that have a data type as the basic unit of writing and reading. You write, say, an Integer, or a Record to a file, and read the same unit of data back. Records are particularly useful, allowing us to store any mix of data types in the one file unit of data.

    This is best illustrated with an example:

    Man with name Fred Bloggs is 21
    Lady with name Jane Turner is 45

    The code is very similar to that used for text files, except that we define a file of a certain type (record), and pass/receive record data when writing/reading.

    Reading and writing to pure binary files


    Pure binary files are a bit peculiar. You must use BlockRead and BlockWrite instead of Read and Write. These have the added benefit of greater performance than the Read and Write, but are really geared at writing just blocks of binary data.

    Here is an example :

    Reading first set of bytes :
    1
    2
    3
    4
    5
    6
    Reading remaining bytes :
    7
    8
    1
    4
    9
    16

    Other file processing mechanisms


    Typed binary files provide direct access methods in addition to sequential reads and writes. Click on a routine name to learn more:

    FilePos Gives the file position in a binary or text file
    Seek Moves to a new position in the file
    SeekEof Skip to the end of the current line or file
    SeekEoln Skip to the end of the current line or file

    Getting information about files and directories


    We have only covered data access to files. There are a number of routines that allow you to do all sorts of things with files and directories that contain them:

    ChDir Change the working drive plus path for a specified drive
    CreateDir Create a directory
    DeleteFile Delete a file specified by its file name
    Erase Erase a file
    FileExists Returns true if the given file exists
    FileSearch Search for a file in one or more directories
    FileSetDate Set the last modified date and time of a file
    Flush Flushes buffered text file data to the file
    GetCurrentDir Get the current directory (drive plus directory)
    MkDir Make a directory
    RemoveDir Remove a directory
    Rename Rename a file
    RenameFile Rename a file or directory
    RmDir Remove a directory
    SelectDirectory Display a dialog to allow user selection of a directory
    SetCurrentDir Change the current directory
    Truncate Truncates a file size

    Using TStringList to read and write text files


    The TStringList class is a very useful utility class that works on a lits of strings, each indexable like an array. The list can be sorted, and supports name/value pair strings, allowing selection by name or value.

    These lists can be furnished from text files in one fell swoop. Here we show a TStringList object being created, and loaded from a file:

    We can display the whole file in a Memo box:

    and we can display or process the file with direct access to any line at any time. In the example code below, we open a text file, reverse all lines in the file, and then save it back. Not terribly useful, but it shows the power of TStringList.

    16 - DELPHI POINTERS

    Pointers in the World of Object Orientation


    In the past, especially in languages, pointers were a critical aspect of the language. They allowed direct access to memory, enabling complex data structures to be built and navigated. However, with the advent of Object Orientation, things have changed somewhat. For example, the TStringList class allows a list of strings to be built without the user needing to manage the storage. And hence, removing the need to use pointers to do this.

    Additionally, the Pascal language has also evolved to avoid dynamic storage management by coders - for example with the advent of dynamic arrays. You can now simply code a SetLength call to set or increase the size of such an array as your program runs.

    However, there are still some situations where pointers are valid in Delphi.

    What are pointers?


    Pointers are a special type of variable. Like a meta-variable. They can point to other variables, or to memory. You might use a record pointer, for example, to point to a block of memory where you have stored lots of record data. You would then use the pointer just as if it were a record variable. We'll see how below.

    When calling Windows APIs (Application Programmer Interfaces), we are obliged to use pointers.

    Types of pointers


    Delphi provides a number of typed pointer types, such as PChar, and PExtended, along with a generic, 'point to anything' type - the Pointer type.

    The nice thing about the typed pointers is that they work sensibly with the Inc and Dec functions. Incrementing an PInt64 pointer will add SizeOf(Int64) bytes to the pointer address so that it points to the next Int64 variable in memory.

    The Pointer type is a dangerous one - it falls foul of Delphi's normally tight type handling. Use it with care, or you will end up addressing the wrong memory.

    A simple example using PChar


    The PChar type can be used to scan along a string :

    There are two things to note here. First the use of Addr function to get the address of the string. You could equally use the @ operator. Pointers always work with addresses - the address of a variable here, or a block of acquired memory. Here we point the PChar value to the first character in the string.

    Secondly, now that we have a pointer, we use the ^ character at the end of the pointer name to refer to what the pointer points to. In this case, a character.

    A PChar^ will always give us a character. A PInt64^, for example, will give us an Int64 value. This is where the typing comes in.

    Record pointers


    You can define a pointer to any data type using a different technique:

    Here, the ^ symbol is used to dereference the type - we are saying that we do not have a TMyRecord type, but a pointer to one. Note that this is a prefix use of ^.

    Let us create a full record example :

    When we simpy refer to the record field name, without a ^, Delphi is in fact adding one for us - it recognises what we are doing, and helps us make for more readable code.

    A full memory handling example


    In this example, we'll build a new class that is a limited number list equivalent to the TStringList class. This class will allow you to keep adding numbers to a list of numbers.

    The class uses pointers to help store the numbers in a block of memory, reallocating this block when it is all used up.

    First off, we will look at the constructor :

    The role of the constructor is to initialise the class. The key part of this is to allocate a block of memory that can hold 20 numbers. We'll use Int64 numbers (for some reason, Delphi does not provide an Integer pointer).

    The GetMem call allocates storage of the desired size, setting the memStart generalised Pointer variable to the starting address of the memory allocated. Note that GetMem insists on a Pointer variable.

    We'll add a routine to add a value to the memory :

    The passed number is stored in the next Int64 slot in our memory block, and this nextSlot pointer incremented. Note that this adds SizeOf(Int64) bytes to the address value in this pointer, because the Inc call knows the type of this pointer.

    And here is a routine for retrieving a value :

    Here we use Inc to add index Int64 size bytes to the start of memory to get to the slot of the required memory.

    However, we have not yet covered the situation where the memory we allocate is all used up. We will extend the Add routine to do just this :

    Here we abandon our old memory block (Delphi cannot let us extend the size of it), and create a bigger one. Having allocated it, we must copy the old memory contents to it. Here we see a new concept - assigning the value referred by one pointer to the contents of memory pointed to by another. Delphi knows to copy the whole Int64 value rather than just one byte because these are PInt64 pointers.

    Below is the full code of the class :

    And here is how the code could be used :

    17 - DELPHI PRINTING TEXT & GRAPHIC

    Teleprinter type printing


    Delphi reveals its heritage from the 1970's and earlier when console and line printers were standard. The AssignPrn command allows you to use the Write and WriteLn commands to write a stream of text to your printer. It is simply that. There is no control of font, of page throws, page numbering and so on. And of course, no graphics.

    Full control printing


    Delphi does provide modern full text and graphics printing. The Delphi print model is very different from that of Java, where Java asks the application for pages it chooses. In Delphi, we interrogate the print dialog, and determine ourselves what pages are to be printed, and in what sequence.

    There are in fact two Printer objects, depending on whether you have a CLX or VCL application. The differences are minor.

    Using the printer dialog


    It is highly recommended that you display the printer dialog so that the user can control printing. In the example program that we will build up during this tutorial, we will show a print dialog that allows the user to select all pages, or a range of pages. We keep things as simple as possible by ignoring the Collate option. Unfortunately, when the user selects multiple copies, we cannot switch off the collate option, so you should code for it in your application.

    Here we have created a print dialog object, set up some options, and then displayed it. The Execute method returns true if the user has hit OK rather than cancel. We then print the document. The user can select, via these options, whether to print all 4 pages or a range of these pages, as seen in a portion of the dialog shown below:

    Starting to print


    The Printer object is permanently available to your code (you must use the Printers unit to get access to its methods and fields though). With this object, printing proceeds in an orderly fashion.

    This starts a print job, with a landscape page layout, and a title, and the user specified number of copies. Note that we are ignoring collation - we always print all page 1 copies before page 2 etc.

    Responding to the dialog settings


    The following code snippet defines some new variables :

    And we now set these variables from the print dialog:

    The prPageNums value is a TPrintRange value, and is one of the values that PrintRange may have. If set, it means that the user has selected a range of pages. The FromPage and ToPage values will then be set to the user specified values.

    The main printing logic


    The following code snippet shows the main part of our printing code:

    The functions highlighted in red illustrate printing graphics and text operations. We have drawn a line across the page after moving the line start point to the appropriate position. And we have written out the page number and size values. Text is also positioned by graphical coordinate.

    Both graphical and textual operations are performed on the Printer Canvas. This is very important. It allows you to have a very similar or identical block of code that displays to a form canvas as it does to a printer canvas. This lets you print what you display.

    Notice that we handle the page numbering, and page throws (Printer.NewPage) ourselves.

    Finally, when all pages have been printed, the last page throw is performed when we close the print job using Printer.EndDoc.

    We are not done there


    In practice, you may print documents greater in complexity and size than this simple one. It may be important to you to provide a print cancel mechanism, so that the user can easily abandon unwanted print runs. However, we cannot just display a cancel dialog, since this will hold up our processing. We must display this dialog in a separate threa of execution.

    Threading is somewhat beyond the remit of this article, but is included in the final, complete code given below. You can copy and paste this code into Delphi, as long as you follow the instructions at the top of the code:

    18 - DELPHI OBJECT ORIENTATION

    What is object orientation?


    Before the mid 1980's, the majority of programming languages used commercially operated in a procedural manner. You could trace the code operation linearly line by line. The only jumps were as a result of conditional logic and subroutine calls.

    This was proving to be an error strewn method of writing large applications. You could happily modularise it by packaging sub-programs into functions or procedures, but there was a limit to how these helped you. Not least because subroutines do not hold onto their data across calls.

    Also, with the advance of graphical interfaces, and a principally mouse click driven user interface, programs were becoming event driven. They needed to respond to whatever of the many possible gui (graphical user interface) objects on the screen the user chose to click next.

    Object orientation radically changed the face of programming for many people. It took the concept of subroutines into a completely different zone. Now they retained their data, and were in fact, collections of routines under one umbrella. You called an object to do something, and left the object to sort out how it did it. You did not need to furnish the internal data since it was retained across calls. For example, a list object could have items added or removed from the list at will. And the object could be asked to sort the list into sequence.

    Objects also allowed events, such as mouse clicks, to be handled neatly - a button object could call a routine (method) of another object when clicked. This was now true moduralisation.

    The basic parts of an object oriented program


    The basic building block of an Object Oreinted (OO) program is a Class. It defines data (now called fields) and functions and procedures (both now called methods). One class can have many fields and methods, just as we described with our list object.

    Additionally, OO introduced cleaner ways of allowing fields to be seen externally to the class - via Properties. Now a class can have methods and properties - we seldom let fields be seen externally - they are used internally to make the class work. A Property can be read only, write only or both. All very neat.

    But a class is only a set of field, property and method definitions. It is a data type. We must create an instance of a class before we can use it. We can make any number of instances of a single class. For example, we may make 3 different list class instances - one for CDs one for LPs and one for Cassettes. Each list object hides its storage of these lists. We merely access its internal lists by the provided methods and properties. A read only property, for example, may give the size of the list as it stands at the moment.

    Creating an instance of a class is called instantiation, and generates an object. Each instance of a class is a separate object.

    An example of a class and an object


    Here we will define a very simple class that has one field, one property, and one method:

    We have defined a class called TSimple as a new data type. It is a data type because we have to instantiate it to create a variable. We create an object by calling the Create method. Ah ha! There is no Create method that can be seen. This is because we have inherited it (see the Inherit tutorial for further) from the motherf of all classes : TObject. This is the class we have based our class on. In fact, TObject is assumed by default, so we could have typed :

    Our code has a field called simpleCount that is a Byte type. It can be read by the count property. When we do, we use the property name count, rather than the internal simpleCount name.

    Our method SetCount sets the simpleCount value. Before we go any further, we must define this method, or our code will not compile:

    We simply store the passed SetCount parameter into the local variable. This means that someone who has created a TSimple object can call SetCount to store a value internally. They can then use the count property to read it. This is how:

    The count value is now set to 12

    Take a careful look at this code. We create the simple object by calling the class Create method. A lot of people try to call the simple variable Create method. This is not possible - simpel is null until it is assigned an object. Calling TSimple.Create in effect returns an object reference that gets assigned to simple.

    We can then call the SetCount method to set the count, and use the count property to get this value. A very simple object, but it is designed to demonstrate rather than do anything useful.

    Inheritance


    Now that we have a class defined, we can create objects from it. But supposing we want to have another class, maybe a list with some bells and whistles. We could change our class, or we could define another class based on this class. This is called inheritance - our new class inherits from the existing class. See the Inheritance tutorial for more on this.

    Private, protected, public and published sections


    The class we defined did not bother about classifying the field, property or method. By default, they are all available externally. we can use on of the following classifications to protect or expose as appropriate. Click on a type for more information.

    * Published data can be interrogated at run time, but is beyond the scope of this web site.

    You should use private except where you expect any inherited classes to want to use the data. We should change our simple class as follows:

    Constructors and destructors


    Supposing when we created an object from our class, we wanted to make sure that it had a count right from the start. We can do this by providing a Constructor method. Such a method does at it says - constructs the object. Here is how our code looks with a constructor:

    Note that this is in fact a procedure, but is called a constructor. And that it invokes a method called Create. You are not obliged to call it this, but are highly recommended. We must define this constructor:

    Now we must pass the count when we create the object.

    Method overloading


    In the past, with procedural languages, you would code two differently named routines for the same kind of functionality when you wanted two ways of pasing the data to the routines. For example, a routine to fill a rectangle may take the rectangle parameters individually, as TPoints or a TRect.

    With method overloading, the same name can be used for this routine. Delphi decides which routine to call by the number and type of parameters.

    Polymorphism


    Polymorphism is defined as the ability for related, but different objects to implement the same method in their own way.

    For example, in a graphics application, we may have circle, square and triangle objects, each of which could have a Draw method. This would look the same to the caller, but each object would draw in a different way of course.

    These objects could, but needn't be inherited from a common ancestor class. This is not the point - the same method has many forms - polymorphism.

    Abstraction


    Another fancy word, but again, a fundamental part of OO, even if too few people use it. Abstraction is where a class defines methods as skeletons. It does not provide the code to run them. Instead, it insists that inherited classes do so. The idea is that the parent class clarifies to subclasses exactly what methods they need to provide for consistency. For example, a music device class may have abstract methods for loading the media - only when you create a CD version of the class can you know how to load the music. See Abstraction tutorial for more.

    Interfaces


    Interfaces are even less used than abstraction. They are a specialised form of abstraction. An interface definition comprises only abstract methods. Any class implementing an interface must implement these abstract methods. A class can implement more than one interface. The idea is that interfaces define a set of standard operations or properties that certain types of class should have. See the Interfaces tutorial for more.

    19 - DELPHI MEMORY LEAKS

    Memory and Object Orientation


    Object Orientation has transformed the process of application development. It has allowed complex code to be written in nicely encapsulated modules (objects). When you create an object, Delphi handles the memory allocation for the object as you call the Create method of the object class.

    But there is a down side to this automation that is often overlooked, especially by newcomers, giving rise to memory leaks.

    What are memory leaks?

    Put simply, every time you no longer use an object in your code, you should delete it, thereby freeing the memory it was allocated. If you don't do this, your program can allocate more and more memory as it runs. This failure to discard unwanted blocks of memory is called a memory leak. Run the program long enough and you will use up the memory resources of your PC and the PC will slow down and eventually hang. This is a very real problem in many programs, including commercial applications. If you are serious about your code, you should follow the principles in this tutorial.

    Why Delphi cannot free your memory for you

    Delphi implements objects by reference. When you declare an object :

    you are simply declaring a reference to an object. When you create an object for this reference :

    Delphi allocates memory for the object, and executes the Create constructor method of the class to do any object initialisation required. The rover variable now points to this new object. There is no magic link from the object to the variable - simply a reference.

    You can make a second reference to the object :

    The myCar assignment simply makes the myCar variable point to the object that rover points to. No copying of the object is done. Only one object exists at this time. And it is not magically linked to either variable.

    Delphi does not keep track of who has referred to the object because it cannot easily keep track of all possible variables that might refer to the object. So, for example, you could set both of these variables to nil and the object will still persist.

    How the memory leaks normally occur


    In many parts of many programs, you will have a function or procedure that creates one or more objects in order to carry out it's operation. Here is an example :

    Each time this procedure is called, a new TStringList object is created and filled with the contents of a file. You might think that Delphi would discard the old object when you are assigning the new object to fileData. But this does not happen because Delphi does not know if this is the only variable referring to the object.

    So you must add the following code to the end of the procedure to free up the memory:

    This allows the procedure to be called as many times as you want without more memory being allocated for the string list object each time. We have avoided a memory leak.

    Memory used within an object

    Classes frequently allocate objects in the constructor and in methods. The allocations in the methods should be freed in line, as described above.

    But the objects allocated in the constructor should be freed in a Destructor method. It is like a converse process. But do not code these Free (or FreeAndNil) statements glibly. Take care to see how the class carries out allocations. It may, for example, create objects for a caller for these to persist after the current object is destroyed.

    Here is an example of a class with appropriate memory handling :

    Note that in this example, the object holds the file, and the caller calls the PrintFile method without respecifying the file name. When an object of this class is destroyed, the string list containing the file contents is also destroyed. On Windows XP, the Task Manager shows the memory allocated to running processes. It is useful to observe the allocation amount for your application as you use it. There is likely to be some upping of memory useage as you use different functions, but repeated calls to the same function should normally yield a stable memory allocation.

    Some more subtle object allocations

    There are times when it is not obvious when memory is allocated, or when memory should be discarded. Just as Delphi cannot keep track of object references, you may not easily follow references in your code. This is particularly true when you call routines that create objects for you.

    Delphi itself has Run Time Library functions that allocate memory. In particular, the FindFirst, FindNext and FindClose set of functions is worthy of a mention.

    When FindFirst runs, it attempts to find the first file in a folder that satisfies your search criteria. If it finds a file, then it creates an object that keeps track of where it found this file. This is needed for subsequent calls to FindNext.

    However, it means that you are obliged to call FindClose in order to discard the memory used by this object. So here is an example of object allocation without an explicit call to a Create constructor.

    You have been warned!

    20 - DELPHI INHERITANCE

    What is inheritance?


    Inheritance in people is through their genes. These genes may give you your Mother's nose, or your Father's ear for music, along with a lot else. You inherit features of your parents, and features of their parents, and indeed all human beings. You are at the bottom of an enormous hierarchy of living things. But your inheritance is a framework - you add your own features, and modify some of those inherited. You may be able draw when your parents cannot, but you are not such a good cook maybe. Inheritance in Object oriented languages like Delphi has much the same features, as you will see.

    Inheritance in Delphi


    Object oriented (OO) languages, as their name implies, revolve around another aspect of the real World, where a chunk of code and data is treated as an object. An object in the real World, such as a football, has characteristics, such as size (the data), and actions, such as being kicked (a method). Such objects in an OO language are defined in a class. A class of objects, such as a class of balls, of which a football is a sub-class. The sub-class has specific features (such as a set of sewn panels) but also inherits the parent class features. It too has a size, and can be kicked. In code terms, a Football class would inherit the parent Ball class size variable (data), and kick method (code) :

    And here are the method implementations for these classes:

    Ife we run the following code, creating and using object of these classes, we can see how the inheritance operates:

    The ShowMessageFmt routine shows the two ball speeds before and after kicking:

    Beach ball is moving at speed : 0
    Soccer ball is moving at speed : 0
    Beach ball is moving at speed : 12
    Soccer ball is moving at speed : 12

    In the above code snippets, we have defined a parent and child class. The TFootball child is base on the parent TBall class. The Football inherits the size and speed variables, and the kick method. It only differs in that when creating a football, you are adding a football feature; the number of panels.

    Strengths and weaknesses of inheritance


    The kick and getSpeed methods are part of the Ball class; the Football class can use them without any code addition. Not even a reference to them. This is the power of the inheritance. But it is also a weakness - you have to look at the parent class (and maybe its parents) to find out what you can do with a class.

    There are many more subtle benefits of inheritance. When you extend a class, and inherit the data and methods, you are benefitting from software reusability. Only one version of a method needs to exist.

    With only one version of the method to maintain, you are increasing code reliability. This is true, of course, with the overall object concept, where one class can provide for multiple object instances, all sharing the same methods.

    With only one version of each method, code size is reduced.

    The parent class provides inheritable methods, which can be used by child classes without them knowing, or needing to know how they are implemented. This is called information hiding and is a very powerful benefit.

    Finally, the reduced code size, and method hiding cleans up the code, and it can make for improved code readability. But bear in mind the disadvantage mentioned earlier - you may have to search for the method used by a class.

    Types of inheritance


    You may have noticed that the Football kick method did not take into account the effect of the number of panels on the speed. It may be that more panels make for a faster ball. Lets make that change to the kick method in the Football class:

    And its new kick method:

    Here we have overridden the inherited kick class. Calling a Ball or Football class kick method still looks the same, but the outcome is now different :

    The ShowMessageFmt routine shows the two ball speeds before and after kicking:

    Beach ball is moving at speed : 0
    Soccer ball is moving at speed : 0
    Beach ball is moving at speed : 12
    Soccer ball is moving at speed : 25

    By taking into account the number of Football panels, it travels faster than a plain ball. This type of class inheritance is called a specialisation - the child class is a specialised version of the parent class.

    Another form of class inheritance is where the child class enriches the parent class. It literally extends the parent. For example, a new class inherited from a TButton may add graphics to the button.

    Finally, there are two rather different forms of inheritance. Abstract classes provide skeleton methods that child classes must implement (unless they want to be abstract classes). Interfaces provide a variation on abstract classes. A class that implements an interface must flesh out the skeleton methods of the interface.

    The full code for the above example


    This code may be run by copying and pasting into Delphi, following the instructions at the start:

    21 - DELPHI ABSTRACTION

    Why abstract?


    Whether in Delphi, or in the real World, classes are groupings of objects. Cars are a good example. They are all different, but have a common characteristic that allows you and I to call them by the same generic name of car. You drive, park and service your car in much the same way as everyone else. Except that your car has it's own particular way of doing these things.

    So you can say that the class of cars has a common method for driving, parking and so on, but that this method can only be provided as a concept at the generic car level. It can only be properly described for each particular car model. The car class is the best place to put a placeholder for these methods, to ensure that each car can do these things, and in a relatively similar way. This placeholder in the Car class is empty - it simply paves the way for sub-classes to provide a real method. In Delphi terms, it is called an abstract method. It is an abstraction of the method, forcing the child classes (the car models) to flesh out the details of the method for itself.

    An example


    For our example, we will keep it simple. We'll look at the class of polygons, such as triangles, squares, pentagons, and so on. It's a neat and simple classification - these shapes look pretty much the same, tending to circular as the number of sides increases. There is a lot of commonality that we might want all sub-classes (triangle, square and so on) to have:

    Give the area inside the polygon
    Give the number of sides it has
    Give the length of each side

    The parent class does not know how to implement these methods because it does not know the number of sides. This is why they are abstract. The triangle class, for example, extends this parent polygon class, and implements the above methods. For simplicity, we will use a fixed length for each side. So this goes inside the parent polygon class. And the parent can provide its own, non-abstract propetry for getting and setting this value.

    This shows that a class can have both abstract and non-abstract (concrete) methods.

    In summary, we have a polygon class with one concrete method, and two abstract methods. A triangle class, for example, would inherit the concrete side length get method, and must implement the abstract methods (unless it wants to be an abstract class itself).

    The polygon master class

    Let us define the polygon class first:

    Notice that the abstract methods must also be defined as virtual (or dynamic. The dynamic construct is semantically equivalent to virtual. Dynamic optimises for code size, virtual for speed). This is allows us to override them in sub-classes.

    To accompany this class definition, we must define the concrete methods defined for this, along with the constructor:

    Defining a triangle sub-class

    Here we define our first sub-class of TPolygon:

    There are a number of things to note here. First, that we have specified TPolygon as our base class. Second, that we have defined methods to override the abstract classes in the master class. This helps to clarify the fact that we are not defining them here for the first time. Third, that we do not have to redeclare concrete methods and the properties of TPolygon. We inherit them.

    We even override the constructor - so that we can se the side count of each object to suit the object shape. Such as 3 for a triangle.

    We must implement these override methods:

    Defining a square subclass

    We can define a square subclass similarly. We'll see this subclass in the full code below. It is similar to the triangle class.

    Showing the full code

    Now let us show these three classes altogether in one full unit that you can copy and paste into Delphi, remembering to follow the instructions at the start.

    Note that we have used triangle and square routines to get the area, and a polygon defined routine to get and set the side length.

    A tangible benefit of abstraction


    If the above has appeared a little academic, then there is one nice benefit of this abstraction. Whilst an abstract class such as a polygon cannot be used to create a new object (such an object would not be fully defined), you can create a reference to one. By doing this, you can point this reference to any sub-class, such as a triangle, and use the polygon class abstract methods. Your code can process arrays of sub-classes, and treat them all as if they were generic polygons, without needing to know what variants they each are.

    How do abstract classes differ from Interfaces?


    Abstract classes and Interfaces are quite similar, in that they both provide placeholder methods. Their approach is quite different though. Interfaces are not classes. Your class does not extend an interface. The nature of your class has basically nothing to do with the interface. It can be a new class, or it can extend an existing class. The placeholder methods in the Interface are implemented in your class. All of them must be implemented, in addition to other methods in your class. By implementing the interface, your class simply adds a standard set of metods or properties - a flavour in common with other classes implementing the interface.

    Note also that a class may extend only one ancestor class, but can implement multiple interfaces.

    22 - DELPHI INTERFACE


    Classes that extend another class can be called sub-classes. For example, you might extend a bicycle class to have mountain bike, and child bike sub-classes. They inherit a lot of the common functions of the general bicycle class, but add unique features, such as stabilizer wheel options for the child bike. You can call bicycle methods, knowing that they apply generally to all types of bicycle.

    This is a traditional, standard use for classes, since the sub-classes are just variations on a theme. But supposing you had an application where you had bicycle class objects, car objects, washing machine objects and so on. And in this application, you wanted each such class to have the following method:

    that would let you know if the object contained recyclable materials. You could define a high-level class containing this method, and define all of the classes from it. Or you could simply add the method to each sub class.

    Or you could use interfaces. Interfaces simply tidy up this situation. By defining an interface that groups these common methods, it sets a standard for all of the classes that implement the interface. It makes it easier for the programmer to be disciplined in developing the application; all of the classes have an additional set of methods that are identical. And Delphi insists that all of the methods in an interface are implemented.

    Going back to the recyclable object scenario, each sub-class inherits common function from its particular parent class. This describes the basic structure of the sub-class. It also inherits (by implementation) common function that cut across all classes.

    An interface example


    Like many ideas, an example is the best way to illustrate the concepts. We'll do it in stages to keep things as simple as possible.

    First, let us define a car class:

    type // Define our Car class TCar = class private carName : String; carAge : Byte; published // Car properties property Name : String read carName; property Age : Byte read carAge write carAge; // Car constructor constructor Create(name : String); end;

    This class is defined by default based on TObject since we have not specified a base class type.

    This class has two properties, and a constructor, shown here:

    Here we set the two properties of the car : its name and age. The name is passed as a parameter, and we set a default age of 0.

    Now we'll define another class - a bicycle class:

    This class has two properties, and a constructor, shown here:

    This class is a little different from the car class, enough to show that we could not have based the car on the bicycle or the bicycle on the car.

    Now we'll define an interface that says whether a class object is recyclable:

    Our interface uses the standard IInterface interface definition as a base. Interfaces definitions are like class definitions with all abstract elements. We do not have to declare them as abstract - they are by default.

    This interface adds an isRecyclable property to any class that implements it. Every class that implements it will have be guaranteed to have exactly the same way of asking if it is recyclable. This is the power and benefit of interfaces - uniformity across potentially very different classes.

    Any class can implement as many interfaces as it wants - it can conform to any global standards in effect.

    Note that we must define the property as using a function - we cannot declare a Boolean data field in the interface since interfaces do not contain data.

    Now let us change our classes to support this interface definition:

    Note that we place the function used by the interface isRecyclable property in the private section - we only want the caller to use the property.

    (Note by author : when compiling the code, Delphi insists on the presence of the GetIsRecyclable function, but not on the most important part - the property. As far as the author can see, this is not enforcing the salient feature of the interface - the property!).

    We have now based our class on the TInterfaceObject class, which provides some standard support for classes that implement interfaces. And we have also based our class on IRecyclable, our new interface.

    But we must also declare the new GetIsRecyclable function:

    And we must not forget to set this recyclable value. We'll do it crudely here in the constructor:

    Phew! But we must do the same to the Bicycle class to show the true effect. We'll look at complete code defining and using these classes that you can copy and paste into Delphi, making note to follow the instructions at the start:

    The ShowMessage shows the following program output:
    Dads car is recyclable
    Mums bike is not recyclable

    23 - DELPHI CLASSES

    A string processing class


    In this tutorial we will deomnstrate many of the features and benefits of classes, and the objects that derive from them. We'll do this by creating a new string processing class that provides some string handling utilities that Delphi doesn't:

    * The number of words in the string
    * Replacement of all substring occurences - returning the count of changes
    * Find first and find next for a substring in the string

    Defining the external view of the class


    Our new class will be called TStringy and will reside in its own Unit Stringy. In fact, this unit will contain only the class definition, plus its implementation.

    So the first thing we will look at is the class definition:

    This is quite long, but a lot of it is commentary. Click on the highlighted keywords to learn more. The new TStringy class is a type - not a variable. We are defining a class - it must be built (instantiated) into an object to be used.

    The definition is split into sections - private for private, internal fields (data) and methods (routines), and published for externally visible fields and methods (see also Protected and Public).

    The class is built into an object by calling the constructor Create method. This takes a string called Text. As a user of the class, we do not care what it does with this string, just so long as it remembers it. Objects are very good at that - a feature of object orientation.

    Our class has published functions to perform the replace and find operations that we want. And it has a property to retrieve the word count. Again, we just use the property, not caring how the object calculated tha value.

    There is also a property for reading changing the original construction string. When writing a new value, the property calls a private method SetText. This allows us to do more than just store the new string value.

    In the private section, we hold the string, and other bits and pieces, along with internal methods. These are not visible to users of the object.

    Implementing the class


    Step by step, we will describe how the published methods are implemented. We do not need to do anything for the properties - they simply read and write to our private data fields. We could have vetted these actions by defining get and set routines to be called by the properties. See Property for more on this topic.

    The implementation is defined in the Implementation keyword:

    Note that we are using selected Delphi units to help code our implementation. They are defined in the Uses clause before we get to the code.

    Implementing the constructor

    The constructor method is traditionally called Create - it is strongly recommended that you do so for consistency.

    The constructor stores the passed string, prepares for the Find processing, and calculates the number of words in the string. Well not exactly - it calls a private method to do this (shown a bit further on).

    When we change the string, we must of course recalculate the word count. The WordCount write property calls SetText does just this:

    Private method for calculating the number of words

    The GetWordCount procedure takes no parameters. It simply counts the number of words in the string, and stores the count in the private stWordCount field. Users of a TStringy object can get to this value via the WordCount property (we'll see how later).

    Here is the code for the word count method:

    procedure TStringy.GetWordCount; const // Define word separator types that we will recognise LF = #10; TAB = #9; CR = #13; BLANK = #32; var WordSeparatorSet : Set of Char; // We will set on only the above characters index : Integer; // Used to scan along the string inWord : Boolean; // Indicates whether we are in the middle of a word begin // Turn on the TAB, CR, LF and BLANK characters in our word separator set WordSeparatorSet := [LF, TAB, CR, BLANK]; // Start with 0 words stWordCount := 0; // Scan the string character by character looking for word separators inWord := false; for index := 1 to Length(stText) do begin // Have we found a separator character? if stText[index] In WordSeparatorSet then begin // Separator found - have we moved from a word? if inWord then Inc(stWordCount); // Yes - we have ended another word // Indicate that we are not in a word anymore inWord := false; end else // Separator not found - we are in a word inWord := true; end; // Finally, were we still in a word at the end of the string? // if so, we must add one to the word count since we did not // meet a separator character. if inWord then Inc(stWordCount); end;

    We'll cover this bit by bit. You can read further by clicking on the links in the code.

    First, we define character constants for the characters that we will recognise as word separators. Then a Set variable WordSeperatorSet is defined. We set on just the word separator characters in this set of all characters. We can then use In to check if a character in the string is one of these types. This is very elegant and makes for very readable code. A nice feature of Delphi.

    We do this in a For loop, scanning the whole length of the string. We use a Boolean flag to remember whether the last character we looked at was a character. This is quite compact code, and runs efficiently. Note that we could have done withouth the inner begin..end statements. We use them for code clarity.

    Implementing the FindFirst method

    The FindFirst method sort of cheats - it does a bit of setting up of private fields before calling the FindNext method. Nothing wrong with this - we really only need one lot of code that does the finding.

    Note that we store the return value from a function in a pseudo variable called Result. We do not have to set the value at the end of the routine. We can read from it as well.

    Implementing the FindNext method

    Here we define the nitty gritty of the substring find code:

    We use a While loop to scan along the string. We avoid using a For loop because we need to abandon the string scan at any time if we find the substring in it.

    We use AnsiMidStr to extract a section of the current string at the current index position for comparing with the find string.

    Implementing the Replace method

    This is the most complex method of this class. It also uses a While loop to scan the string, but builds up the target string bit by bit. It takes characters one at a time from this string, and inserts the new toStr value in place of matches with the fromStr value.

    Notice that the Inc routine provided by Delphi has two methods of calling it. One with just the variable to be incremented by 1. The second where we provide a different increment value. Here, we increment teh string index by the length of the matching substring.

    The whole of the Stringy is shown on the next page, along with sample code that illustrates use of it.

    50-game

    JAVA

    1 - JAVA OVERVIEW

    Conventions in These Notes


    Code is listed in a monospace font, both for code examples and for Java keywords mentioned in the text.

    The standard Java convention for names is used:

    • Class names are listed with an initial uppercase letter.
    • Variable and function names are listed with an initial lowercase letter.
    • The first letters of inner words are capitalized (e.g., maxValue).

    For syntax definitions:

    • Terms you must use as is are listed in normal monospace type.
    • Terms that you must substitute for, either one of a set of allowable values, or a name of your own, or code, listed in italics.
    • The following generic terms are used - you must substitute an appropriate term.


    access An access word from: public, protected, private, or it can be omitted
    modifiers one or more terms that modify a declaration; these include the access terms as well as terms like: static, transient, or volatile
    dataType A data type word; this can be a primitive, such as int, or the name of a class, such as Object; variants of this include: returnType and paramType
    variableName The name of a variable; variants on this include paramName and functionName
    ClassName The name of a class; there will be variants of this used for different types of examples, such as: BaseClassName, DerivedClassName, InterfaceName, and ExceptionClassName
    code Executable code goes here
    . . . In an example, omitted code not related to the topic

    The Java Environment - Overview


    A Java program is run differently than a traditional executable program.

    Traditional programs are invoked through the operating system.

    • They occupy their own memory space.
    • They are tracked as an individual process by the OS.

    Traditional programs are compiled from source code into a machine and OS-specific binary executable file.

    • To run the program in different environments, the source code would be compiled for that specific target environment.

    When you run a Java program, the OS is actually running the Java Runtime Engine, or JRE, as an executable program; it processes your compiled code through the Java Virtual Machine (usually referred to as the JVM).

    A Java source code file is compiled into a bytecode file.

    • You can consider bytecode as a sort of generic machine language.
    • The compiled bytecode is read by the JVM as a data file.
    • The JVM interprets the bytecode at runtime, performing a final mapping of bytecode to machine language for whatever platform it is running on.
    • Thus, Java programs are portable - they can be written in any environment, compiled in any environment, and run in any environment (as long as a JVM is available for that environment).
    • The JVM manages its own memory area and allocates it to your program as necessary.
    • Although this involves more steps at runtime, Java is still very efficient, much more so than completely interpreted languages like JavaScript, since the time-consuming parsing of the source code is done in advance.

    The Java Environment - Overview


    A Java program is run differently than a traditional executable program.

    Traditional programs are invoked through the operating system.

    • They occupy their own memory space.
    • They are tracked as an individual process by the OS.

    Traditional programs are compiled from source code into a machine and OS-specific binary executable file.

    • To run the program in different environments, the source code would be compiled for that specific target environment.

    When you run a Java program, the OS is actually running the Java Runtime Engine, or JRE, as an executable program; it processes your compiled code through the Java Virtual Machine (usually referred to as the JVM).

    A Java source code file is compiled into a bytecode file.

    • You can consider bytecode as a sort of generic machine language.
    • The compiled bytecode is read by the JVM as a data file.
    • The JVM interprets the bytecode at runtime, performing a final mapping of bytecode to machine language for whatever platform it is running on.
    • Thus, Java programs are portable - they can be written in any environment, compiled in any environment, and run in any environment (as long as a JVM is available for that environment).
    • The JVM manages its own memory area and allocates it to your program as necessary.
    • Although this involves more steps at runtime, Java is still very efficient, much more so than completely interpreted languages like JavaScript, since the time-consuming parsing of the source code is done in advance.

    Writing a Java Program


    Java source code is written in plain text, using a text editor.

    • his could range from a plain text editor like Notepad, to a programmers' editor such as TextPad, EditPlus, or Crimson Editor, to a complex integrated development environment (IDE) like NetBeans, Eclipse, or JDeveloper.
    • The source code file should have a .java extension.

    The javac compiler is then used to compile the source code into bytecode.

    • The bytecode is stored in a file with an extension .class
    • Bytecode is universal - one bytecode file will run on any supported platform.

    You then run the java runtime engine, which will then interpret the bytecode to execute the program.

    • The executable program you are running is: java.
    • The class name tells the JVM what class to load and run the main method for.
    • You must have a JVM made specifically for your hardware/OS platform.

    Obtaining the Java Environment


    You can download the SDK (software development kit) including the compiler and runtime engine from Oracle at: . Look for the download of JavaSE 1.6.0.10 (or the latest release of that version).

    You can also download the API documentation and even the source code. Note that:

    • he documentation lists all the standard classes in the API, with their data fields and methods, as well as other information necessary to use the class. You will find this documentation helpful as you work through some of the exercises.
    • You can view the docs online, but it is worth downloading it so that you don't have to be connected to the internet to use it.

    Setting up Your Java Environment


    Java programs are compiled and run from an operating system prompt, unless you have installed an IDE that will do this for you directly. If you create an applet, this would run inside a web page in a browser.

    After you have installed the JDK, you will need to set at least one environment variable in order to be able to compile and run Java programs.

    For more complex projects that pull together elements from different sources, you must set an additional environment variable or two. Note that:

    • a PATH environment variable enables the operating system to find the JDK executables when your working directory is not the JDK's binary directory.
    • CLASSPATH is Java's analog to PATH, the compiler and JVM use it to locate Java classes.
    • Often you will not need to set this, since the default setting is to use the JDK's library jar file and the current working directory.
    • But, if you have additional Java classes located in another directory (a third-party library, perhaps), you will need to create a classpath that includes not only that library, but the current working directory as well (the current directory is represented as a dot).
    • Many IDE's and servers expect to find a JAVA_HOME environment variable.
    • This would be the JDK directory (the one that contains bin and lib).
    • The PATH is then set from JAVA_HOME plus \bin.
    • This makes it easy to upgrade your JDK, since there is only one entry you will need to change

    Best Practice: Setting PATH from JAVA_HOME

    The procedure to permanently set the environment variables varies slightly from one version of Windows to another; the following will work in many, including Windows XP. The process for Vista is similar, but slightly different:

    1. Right-click on My Computer.
    2. Choose Properties.
    3. Select the Advanced tab.
    4. Click the Environment Variables button at the bottom.
    5. Check both the User and System variable lists to see if JAVA_HOME or PATH already exist.
    6. If JAVA_HOME exists, check to see that it matches your most recent JDK (or the one you wish to use).
    • It is probably better to set this as a System variable.
    • If it exists, click Edit, if not, click Add.
    • For the variable name, enter JAVA_HOME.
    • For the value, enter your JDK directory, such as C:\Program Files\Java\jdk1.5.0_14.
    • Note that the space in the name can sometimes cause problems.
    • One solution is to put quote marks around the entry, as in "C:\Program Files\Java\jdk1.5.0_14".
    • An even better solution would be to use the 8-character form of the directory name, such as C:\Progra~1\Java\jdk1.5.0_14 (you can check if this works in your system by typing it into the address bar of a My Computer window).

    7. for PATH, again select either Add or Edit.

    • You could do this either as a User variable or a System variable.
    • If there isn't already a JDK bin directory mentioned in the PATH, it will work as a User variable.
    • If there is already a JDK mentioned, you would want to ensure that this new entry preceded the existing entry, so you would edit that variable.
    • Note that if the existing entry was created using JAVA_HOME, then we are already set correctly .
    • If you "prepend" an entry to PATH , it will be found first, and therefore supercede any other directory - if you append to path, your directory won't be found if an earlier entry JDK entry exists (the following image shows a prepend).
    • Also note that System variables precede User variables, so they will be found first.

    Setting Environment Variables from a Command Prompt

    If you set the variables from a command prompt, they will only hold for that session, but you could create a batch file that you could run each time you open a command prompt window.

    To set the PATH from a command prompt or batch file:

    If you need to set the CLASSPATH:

    • Early versions of the JDK required you to include the JDK's lib directory in the CLASSPATH; this is no longer necessary .
    • Note that UNIX environments use $PATH and $CLASSPATH instead of %PATH% and %CLASSPATH%, and that the path element separator is a colon instead of a semicolon.

    Creating a Class that Can Run as a Program


    The main() Method

    In order to run as a program, a class must contain a method named main, with a particular argument list. This is similar to the C and C++ languages.

    The definition goes inside your class definition, and looks like:

    • It must be public, because it will be called from outside your class (by the JVM).
    • The static keyword defines an element (could be data or functional) that will exist regardless of whether an object of a class has been instantiated. In other words, declaring main as static allows the JVM to call the method and therefore execute the program. That doesn't mean that an object of that class cannot be instantiated, it is just not required.
    • The String[] args parameter list states that there will be an array of String objects given to the method - these are the command line arguments.
    • To run the program, use the following from the command line if you are running it from the console:

    For example, if we had an executable class called Hello, in a file called Hello.java that compiled to Hello.class, you could run it with:

    Useful Stuff Necessary to Go Further


    System.out.println()

    In order to see something happen, we need to be able to print to the screen.

    There is a System class that is automatically available when your program runs (everything in it is static).

    it contains, among other things, input and output streams that match stdin, stdout, and stderr (standard output, standard input, and standard error).

    System.out is a static reference to the standard output stream.

    As an object, System.out contains a println(String) method that accepts a String object, and prints that text to the screen, ending with a newline (linefeed).

    There is also a print(String) method that does not place a newline at the end.

    You can print a String directly, or you can build one from pieces.

    • It is worth noting that a String will automatically be created from a quote-delimited series of characters.
    • Values can be appended to a String by using the + sign; if one item is a String or quote-delimited series of characters, then the rest can be any other type of data.

    Using an Integrated Development Environment


    Duration: 30 to 40 minutes. Integrated Development Environments, or IDEs, can greatly facilitate the task of creating applications. Mid-level code editors, such as Crimson Editor, TextPad, or Edit-Plus, provide syntax highlighting, automatic indenting, parentheses and curly-brace matching, and may have tools to compile and execute programs.

    High-end environments, such as Eclipse, NetBeans, or JDeveloper, offer many additional features, such as project management, automatic deployment for web applications, code refactoring, code assist, etc. But, these additional capabilities come with the price of additional complexity in the environment, particularly because they force you to create projects for even the simplest applications.

    To use the class files in these environments, we must first have a workspace, which is a collection of projects. Workspaces have various configuration settings that will cut across all projects within all projects they contain, such as which version of Java is in use, any added libraries, etc. (a project is usually one application).

    Both Eclipse and NetBeans use the workspace concept, but you can start with any empty directory - the IDE will add its own special files as you create projects.

    In the Windows Explorer, navigate to your ClassFiles directory. If it does not contain a Workspace subdirectory, create it.

    To use Eclipse with the class files, you can direct it to the workspace (ClassFiles/Workspace) when it opens (if it asks), or use File, Switch Workspace if Eclipse is already running. Each chapter's demo folder should be treated as a project, as should each Solution folder.

    One limitation of these environments is that no project can contain the same Java class twice, so our progressive versions of the Payroll application solution require their own individual project. Also, due to the way Java's package structures work, each Demo folder must be a separate project, as with each subdirectory under Solutions.

    To use the Exercises folder as an Eclipse project:

    1. Select File > New > Java Project
    2. Enter Exercises for the project name
    3. Click Finished
    4. In the Package Explorer pane, right-click on the src folder under the Exercises folder
    5. Select Import from the context menu
    6. Select File System from the tree in the Select dialog box
    7. Click Next
    8. Using the Browse button, navigate to and select c:/ClassFiles/Exercises. (Note: this path might be different depending on where you extracted the class zip file)
    9. Make sure the Exercises check box is selected and click Finished
    10. Expand the src folder in the Package Explorer and then expand the default package folder
    11. Right-click on the file Welcome.java
    12. From the context menu select Run As... > Java Application
    13. Note the output is displayed in the Console at the bottom of the Eclipse workbench
    14. As we encounter each chapter, we can create a project using the Demos directory for that chapter the same way we just created the Exercises project..

      To create a Java class within a project, use File, New , and then Class if that is available, or Other... and then Class . Provide a name and then OK .

      In general, with the several applications that we will build upon progressively (Game and Payroll), you can continue to work with the same files, and add to them as we cover additional topics. If you want to check the solutions, you can either open those files in a separate editor, like Notepad, or create a project for that Solutions subdirectory. If you wish to save a particular stage of the application for future reference, you can just make a copy of the Exercises directory.

      The examples and instructions provided use a more basic text editor (Chrimson) and an OS console for clarity. You are free to choose which tool to use. If Eclipse becomes a problem, move to a simple editor. The focus of this course is on the Java Programming Language and not a particular tool.

    First Java Program


    Duration: 5 to 15 minutes.

    1.Create a file called Hello.java.
    2.Enter the following code:

    3.Save the file.
    4.In a command prompt window, change to the directory where Hello.java is stored and type the following:

    A prompt on the next line without any error messages indicates success.

    5.Type:

    6.Press Enter.

    You should see the message Hello World print in the window.

    • All Java code must be within a class definition.
    • A class defines a type of object.
    • A public class can be accessed by any other class.
    • A public class must be in its own file, whose name is the name of the class, plus a dot and an file extension of java(e.g., Hello.java ).
    • Curly braces denote a block of code (the code inside the braces).
    • Code within braces usually belongs to whatever immediately precedes them.
    • Words followed by parentheses denote a function.
    • To be executable by itself, a class must have a function defined in this fashion; the name main means that execution will start with the first step of this function, and will end when the last step is done.
    • It is public because it needs to be executed by other Java objects (the JVM itself is a running Java program, and it launches your program and calls its main function).
    • It is static because it needs to exist even before one of these objects has been created.
    • It does not return an answer when it is done; the absence of data is called void.
    • The String[] args represents the additional data that might have been entered on the command line.
    • System is an class within the JVM that represents system resources.
    • It contains an object called out, which represents output to the screen (what many environments call standard out).
    • Note that an object's ownership of an element is denoted by using the name of the object, a dot, and then the name of the element.
    • out in turn contains a function, println, that prints a line onto the screen (and appends a newline at the end).
    • A function call is denoted by the function name followed by parentheses; any information inside the parentheses is used as input to the function (called arguments or parameters to the function).
    • The argument passed to println() is the string of text "Hello World!".
    • Note that the statement ends in a semicolon (as all do Java statements).

    Using the Java Documentation

    Sun provides extensive documentation of the API (library of available classes). The documentation for version 6 is available at

    If you view that page, you will see a list of classes on the left as hyperlinks. Clicking a class name will bring up the documentation for that class on the right.

    For example, click on System. The page on the right contains documentation on the elements of the class, categorized by type of element (there are links at the top for fields, constructors, methods, etc.).

    Try to locate the out field - note that the field types, parameter types and return types are hyperlinked, and that out is a PrintStream. Click that, and find the println methods in a table with short descriptions. Select one to see the detailed description. The multiple versions are an example of method overloading, which we will cover in an upcoming lesson. Another lesson will cover documenting your own classes with the same tool that created this documentation.

    In this lesson, you have learned:

    2 - JAVA SYNTAX

    General Syntax Rules


    ava is case-sensitive. main(), Main(), and MAIN() would all be different methods.

    There are a limited number of reserved words that have a special meaning within Java. You cannot use these words for your own variables or methods.

    Some examples of reserved words are:

    • public
    • void
    • static
    • do
    • for
    • while
    • if

    Most keyboard symbol characters (the set of characters other than alphabetic or numeric) have a special meaning.

    Names may contain alphabetic characters, numeric characters, currency characters, and connecting characters such as the underscore ( _ ) character:

    • Names may not begin with a numeric character.
    • Note that the set of legal characters draws from the entire Unicode character set.
    • Also note that it is probably impossible to write a succinct set of rules about what are valid characters, other than to say a character, that when passed to Character.isJavaIdentifierPart(char ch), results in a true value.

    The compiler parses your code by separating it into individual entities called tokens or symbols in computer science jargon:

    • Names (of classes, variables, and methods).
    • Command keywords.
    • Single or compound symbols (compound symbols are when an operation is signified by a two-symbol combination).

    Tokens may be separated by spaces, tabs, carriage returns, or by use of an operator (such as +, -, etc.).

    Since names may not contain spaces, tabs, carriage returns, or operator characters, these characters imply a separation of what came before them from what comes after them.

    Extra whitespace is ignored. Once the compiler knows that two items are separate, it ignores any additional separating whitespace characters (spaces, tabs, or carriage returns).

    Java Statements


  • A Java statement is one step of code, which may span across multiple lines.
  • Java statements end with a semicolon (the ; character).
  • It is OK to have multiple statements on a single line.
  • Program execution is done statement by statement, one statement at a time from top to bottom (if there is more than one statement on a line, execution goes from left to right).
  • Within a statement, execution of the individual pieces is not necessarily left to right. There are concepts called operator precedence and associativity that determine the order of operations within a statement.
  • Blocks of Code


    A block of code:

    • Is enclosed in curly braces - start with { and end with }.
    • Consists of zero, one, or more statements.
    • Behaves like a single statement to the outside world..
    • May be nested (e.g., it may contain one or more other blocks of code inside).
    • Generally belong to whatever comes before it. Although it is perfectly OK to create a block that does not, this is almost never done.

    A complete method is a single block of code, most likely with nested blocks.

    The diagram below illustrates how blocks of code can be nested:

    If you want, go ahead and modify your Hello World program to match this example.

    Comments


    A comment:

    • Is additional, non-executable text in a program used to document code.
    • May also be used to temporarily disable a section of code (for debugging).
    Block Comments

    Block comments are preceded by /* and followed by */.

    Some rules for block comments:

    • May not be nested.
    • May be one or more lines.
    • May span part of a line, for example, to temporarily disable part of a statement:
    Single-line Comments

    A single line can be commented by preceding the comment with two forward slashes: //. Note that:

    • The comment ends at the end of that line.
    • Single-line comments may be nested inside block comments.

    Java specifies a third type of comment, the javadoc comment:

    • Java contains a self-documentation utility, javadoc, which builds documentation from comments within the code.
    • javadoc comments begin with /** and end with */.
    • Comments only work as javadoc comments when placed at specific locations in your code (immediately above anything documentable - the class itself and its members), otherwise they are treated as ordinary comments.

    3 - JAVA VARIABLES

    Variables store data that your code can use.

    There are two fundamental categories of variables, primitive data and references:

    • With primitive data, the compiler names a memory location and uses itto store the actual data - numeric values such as integers, floating point values, and the code values of single individual text characters are stored as primitives.
    • With references, the data is accessed indirectly - the compiler selects a memory location, associates it with the variable name, and stores in it a value that is effectively the memory address of the actual data - in Java, all objects and arrays are stored using references.

    In the diagram below, the boxes are areas in memory:

    Declaring Variables


    Variables must be declared before they are used.

    A declaration informs the compiler that you wish to:

    • Create an identifier that will be accepted by the compiler within a section of code (exactly what that section is depends on how and where the variable is declared; that is the concept of scope, which will be addressed later).
    • Associate that identifier with a specified type of data, and enforce restrictions related to that in the remainder of your code.
    • Create a memory location for the specified type of data.
    • Associate the identifier with that memory location.

    Java uses many specific data types; each has different properties in terms of size required and handling by the compiler:

    • The declaration specifies the name and datatype.
    • Generally the declaration also defines the variable, meaning that it causes the compiler to allocate storage space in memory of the requested type's size.
    • A declaration may also assign an initial value (to initialize the variable).
    • Multiple variables of the same type can be declared in a comma-separated list.
    Code
    Effect
    int a;

    declares the name a to exist, and allocates a memory location to hold a 32-bit integer

    int a = 0;

    same as above, and also assigns an initial value of 0

    int a = 0, b, c = 3;

    declares three integer variables and initializes two of them

    Note that different languages have different rules regarding variables that have not been initialized:

    • Some languages just let the value be whatever happened to be in that memory location already (from some previous operation).
    • Some languages initialize automatically to 0.
    • Some languages will produce a compiler or runtime error.
    • Java uses both of the last two: local variables within methods must be initialized before attempting to use their value, while variables that are fields within objects are automatically set to zero.

    Advanced Declarations


    Local variables, fields, methods, and classes may be given additional modifiers; keywords that determine special characteristics.

    Any modifiers must appear first in any declaration, but multiple modifiers may appear in any order.

    Keyword
    Usage
    Comments
    final local variables, fields, methods, classes

    The name refers to a fixed item that cannot be changed.

    For a variable, that means that the value cannot be changed.

    For a method, the method cannot be overridden when extending the class.

    A final field does not, however, have to be initialized immediately; the initial assignment may be done once during an object's construction.

    static fields, methods, inner classes

    Only for fields and methods of objects.

    One copy of the element exists regardless of how many instances are created.

    The element is created when the class is loaded.

    transient fields

    The value of this element will not be saved with this object when serialization is used (for example, to save a binary object to a file, or send one across a network connection).

    volatile fields

    The value of this element may change due to outside influences (other threads), so the compiler should not perform any caching optimizations.

    public, protected, private fields, methods classes

    Specifies the level of access from other classes to this element - covered in depth later.

    abstract methods, classes

    Specifies that a method is required for a concrete extension of this class, but that the method will not be created at this level of inheritance - the class must be extended to realize the method.

    For a class, specifies that the class itself may not be instantiated; only an extending class that is not abstract may be instantiated (a class must be abstract if one or more of it's methods are abstract) - covered in depth later

    native methods

    The method is realized in native code (as opposed to Java code) - there is an external tool in the JDK for mapping functions from a DLL to these methods.

    strictfp methods, classes

    For a method, it should perform all calculations in strict floating point (some processors have the ability to perform floating point more accurately by storing intermediate results in a larger number of bits than the final result will have; while more accurate, this means that the results might differ across platforms).

    For a class, this means that all methods are strictfp.

    synchronized methods, code blocks

    No synchronized code may be accessed from multiple threads for the same object instance at the same time.

    4 - JAVA DATA

    Primitive Data Types


    • The primitive data types store single values at some memory location that the compiler selects and maps to the variable name you declared .
    • Primitive values are not objects - they do not have fields or methods.
    • A primitive value is stored at the named location, while an object is accessed using a reference.
    • An object reference variable does not store the object's data directly - it stores a reference to the block of data, which is somewhere else in memory (technically, the reference stores the memory address of the object, but you never get to see or use the address).
    Primitives Data Types
    Primitives Data Types
    Primitive Type
    Storage Size
    Comments
    boolean 1 bit not usable mathematically, but can be used with logical and bitwise operators
    char 16 bits unsigned, not usable for math without converting to int
    byte 8 bits signed
    short 16 bits signed
    int 32 bits signed
    long 64 bits signed
    float 32 bits signed
    double 64 bits signed
    void None not really a primitive, but worth including here

    Object Data Types


    Objects can be data, which can be stored in variables, passed to methods, or returned from methods.

    References

    As we will see later, objects are stored differently than primitives. An object variable stores a reference to the object (the object is located at some other memory location, and the reference is something like a memory address).

    Text Strings

    A sequence of text, such as a name, an error message, etc., is known as a string.

    n Java, the String class is used to hold a sequence of text characters.

    A String object:

    • Is accessed through a reference, since it is an object.
    • Has a number of useful methods, for case-sensitive or case-insensitive comparisons, obtaining substrings, determining the number of characters, converting to upper or lower case, etc.
    • Is immutable; that is, once created it cannot be changed (but you can make your variable reference a different String object at any time).
    Literal Values

    A value typed into your code is called a literal value.

    The compiler makes certain assumptions about literals:

    • true and false are literal boolean values.
    • null is a literal reference to nothing (for objects).
    • A numeric value with no decimal places becomes an int, unless it is immediately assigned into a variable of a smaller type and falls within the valid range for that type.
    • A value with decimal places becomes a double.
    • To store a text character, you can put apostrophes around the character.
    Code
    Effect
    char e = 'X'; Creates a 16-bit variable to hold the Unicode value for the uppercase X character.

    You can add modifiers to values to instruct the compiler what type of value to create (note that all the modifiers described below can use either uppercase or lowercase letters).

    Modifying prefixes enable you to use a different number base:

    Prefix
    Effect
    0X or 0x A base 16 value; the extra digits can be either uppercase or lowercase, as in char c = 0x1b;
    0 A base 8 value, as in int i = 0765;
    • Note: using these prefixes will always result in number that is considered positive (so that 0x7F for a byte would be OK, but 0x80 would not, since the latter would have a value of 128, outside the range of byte).
    • Also note that a long value would need the L modifier as discussed below.

    Modifying suffixes create a value of a different type than the default:

    L or l a long value (uses 64 bits of storage), as in long l = 1234567890123456L;
    Note: An int value will always implicitly be promoted to a long when required, but the reverse is not true; the above notation is necessary because the literal value is larger than 32 bits
    F or f A float value, as in float f = 3.7F;

    Escape Sequences for Character Values

    There are a number of escape sequences that are used for special characters:

    Escape Sequence
    Resulting Character
    \b Backspace
    \f Form feed
    \n Linefeed character - note that it produces exactly one character, Unicode 10 (\u000A in hex)
    \r Carriage return
    \t Tab
    \" Quote mark
    \' Apostrophe
    \\ Backslash
    \uNNNN Unicode value, where N is a base 16 digit from 0 through F; valid values are \u0000 through \uFFFF
    \NNN Value expressed in octal; ranging from \000 to \377

    The escape sequences can either be used for single characters or within strings of text:

    5 - JAVA CONSTANTS AND THE FINAL KEYWORD

    Java has a means for defining contants, which are like variables in that they have names, but are not changeable once set.

    If a variable is declared as final, it cannot be changed:

    Even though the variable's value is not changeable once a value has been established, you are allowed to set a unique value once.

    Local variables within methods may be declared as final.

    Constants' values may be set in an explicit initialization, in a separate line of code, or, as method parameters passed when the method is called.

    Fields within a class may be declared as final.

    Contants' values may be set in an explicit initialization, in a separate line of code within an initialization block, or in a constructor.

    Fields of a class may be declared as public static final - that way they are available to other classes, but cannot be changed by those other classes. An example is Math.PI.

    Classes and methods may also be marked as final. We will cover this later.

    Code Sample:


    Java-Basics/Demos/FinalValues.java

    The class has two final fields, scale and answer. The scale is fixed at 100, while the answer is initialized dynamically, but, once established, the value cannot be changed. Try removing the comment from the line that attempts to set it to 44, and you will see the compiler error message that results.

    6 - JAVA MATHEMATICS

    Looks and behaves like algebra, using variable names and math symbols:

    Basic Rules


    • What goes on the left of the = sign is called an lvalue. Only things that can accept a value can be an lvalue (usually this means a variable name - you can't have a calculation like a + b in front of the equal sign).
    • Math symbols are known as operators; they include:
    Operator Purpose (Operation Performed)
    + for addition
    - for subtraction
    * for multiplication
    / for division
    % for modulus (remainder after division)
    ( and ) for enclosing a calculation
    Note that integer division results in an integer - any remainder is discarded.

    Expressions


    An expression is anything that can be evaluated to produce a value. Every expression yields a value.

    Examples (note that the first few of these are not complete statements):

    Two simple expressions:

    An expression that contains another expression inside, the (5/c) part:

    A statement is an expression; this one that contains another expression inside - the b + (5/c) part, which itself contains an expression inside it (the 5/c part):

    Since an assignment statement (using the = sign) is an expression, it also yields a value (the value stored is considered the result of the expression), which allows things like this:

  • The value stored in a is the value of the expression b + (5/c).
  • Since an assignment expression's value is the value that was assigned, the same value is then stored in d.
  • The order of processing is as follows:
    1. Retrieve the value of b.
    2. Retrieve the 5 stored somewhere in memory by the compiler.
    3. Retrieve the value of c.
    4. perform 5 / c
    5. Add the held value of b to the result of the above step.
    6. Store that value into the memory location for a.
    7. Store that same value into the memory location for d.

    Here is a moderately complicated expression; let's say that a, b, and c are all double variables, and that a is 5.0, b is 10.0, and c is 20.0:

    1.Since the c + 5 is in parentheses, the compiler creates code to evaluate that first, but to perform the c + 5 operation, both elements must be the same type of data, so the thing the compiler creates is a conversion for the 5 to 5.0 as a double.

    2.Then the compiler creates code to evaluate 20.0 + 5.0 (at runtime it would become 25.0), reducing the expression to:

    3.Next, the compiler adds code to call the Math.sqrt method to evaluate its result, which will be 5.0, so the expression reduces to:

    4.Note that the evaluated result of a method is known as the return value, or value returned. 5.Multiplication gets done before addition, the compiler creates that code next, to reduce the expression to:

    6.Then the code will perform the addition, yielding:

    7.And finally, the assignment is performed so that 55.0 is stored in d.

    As implied by the examples we have seen so far, the order of evaluation of a complex expression is not necessarily from left to right. There is a concept called operator precedence that defines the order of operations.

    Operator Precedence

    Operator precedence specifies the order of evaluation of an expression.

    Every language has a "table of operator precedence" that is fairly long and complex, but most languages follow the same general rules:

    • Anything in parentheses gets evaluated before what is outside the parentheses.
    • Multiply or divide get done before add and subtract.
    Example:
    • In the expression a = b + 5/c, the 5/c gets calculated first, then the result is added to b, then the overall result is stored in a.
    • The equal sign (=) is an operator; where on the table do you think it is located?

    The basic rule programmers follow is: when in doubt about the order of precedence, use parentheses.

    Try the following program:

    Code Sample:

    Java-Basics/Demos/ExpressionExample.java

    Multiple Assignments


    Every expression has a value. For an assignment expression, the value assigned is the expression's overall value. This enables chaining of assignments:

    x = y = z + 1; is the same as y = z + 1; x = y;

    i = (j = k + 1)/2; is the same as j = k + 1; i = j/2;

    Quite often, you may need to calculate a value involved in a test, but also store the value for later use:

    You might wonder why not just generate the random number when we declare x? In this case, that would make sense, but in a loop the approach shown above might be easier such that:

    • generates the random number and stores it in x.
    • as an expression, that results in the same value, which is then tested for less than 0.5, and the loop body executes if that is true.
    • the value of x is then available within the block.
    • after the loop body executes, another random number is generated as the process repeats.

    It is usually not necessary to code this way, but you will see it often.

    Order of Evaluation

    The order of operand evaluation is always left to right, regardless of the precedence of the operators involved.

    Code Sample:

    Java-Basics/Demos/EvaluationOrder.java

    The operands are first evaluated in left to right order, so that the functions are called in the order getA(), then getB(), and, lastly, getC()

    But, the returned values are combined together by multiplying the results of getB() and getC(), and then adding the result from getA()

    Bitwise Operators

    Java has a number of operators for working with the individual bits within a value.

    & Bitwise AND, combines individual bits with an AND operation, so that in the resulting value, a bit position is only 1 if that position had a 1 for both operands.
    int a = 2; has the 2 bit set 0...00000010
    int b = 6; has the 2 and 4 bits set 0...00000110
    int c = a & b; results in 2 0...00000010
    | Bitwise OR, combines individual bits with an OR operation, so that in the resulting value, a bit position is 1 if that position had a 1 for either operand.
    int a = 2; has the 2 bit set 0...00000010
    int b = 4; has the 4 bit set 0...00000100
    int c = a | b; results in 6 0...00000110
    ^ Bitwise exclusive OR (XOR), combines individual bits so that any position that is the same in both operands yields a 0, any bits that differ yield a 1 in that position; this is often used in encryption, since repeating the operation on the result yields the original value again
    int a = 3; has the 1 and 2 bits set 0...00000011
    int b = 6; has the 2 and 4 bits set 0...00000110
    int c = a ^ b; results in 5 0...00000101
    int d = c ^ b; results in 3 again 0...00000011
    ~ Bitwise complement. Reverses the state of all bits.
    int a = 0; has no bits set 0...00000000
    int b = ~a; has all bits set 1...11111111

    Bitwise Shift Operators

    These operators shift the bits left or right within a 32-bit int value (they do not work with any other type).

    << left shift the bits by the second operand
    int a = 4; has the 4 bit set 0...00000010
    int b = a << 2; now has the 16 bit set 0...00001000
    >> right shift the bits by the second operand with sign-extension (if the first bit is a 1, new bits introduced to fill in on the left come in as 1 bits)
    int a = -126; has all bits except the rightmost set to 1 10...0000010
    int b = a >> 1; now has all bits set to 1 (the 0 rolled off the right end, and a 1 was added on the left to match the original leftmost bit; the resulting value is 63) 110...000001
    >>> right shift the bits by the second operand without sign-extension (bits added on the left always come in as 0)
    int a = -1; has all bits set to 1 11...1111111
    int b = a >>> 31; now has all bits set to 0 except the rightmost (all bits except the first rolled off the right end, and 0's were added on the left 0000000...01

    Compound Operators

    Combine multiple effects in one operation: calculation and storage into memory

    Operator
    Purpose (Operation Performed)
    ++ increment a variable
    -- decrement a variable; note that ++ and -- can precede or follow a variable
    if preceding (called prefix), apply the operator and then use the resulting value
    if following (called postfix), retrieve the value of the variable first, use it as the result of the expression, and then apply the operator
    += add an amount to a variable
    -= subtract an amount from a variable
    *= multiply a variable by an amount
    /= divide a variable by an amount
    %= set variable equal to remainder after division by an amount
    &= perform bitwise AND between left and right, store result into left operand
    |= perform bitwise OR between left and right, store result into left operand
    ^= perform bitwise XOR between left and right, store result into left operand
    >>= shift the variable's bits to the right by an amount with sign-extension
    >>>= shift the variable's bits to the right by an amount without sign-extension
    <<= shift the variable's bits to the left by an amount

    Compound Operator Examples

    Statement
    Result
    i++; increment i
    i--; decrement i
    j = i++; retrieve current value of i, hold it as the result of the expression, assign its value to j, then increment i
    j = ++i; increment i, then j = i;
    x *= 3; x = x * 3;
    y -= z + 5; y = y - (z + 5);

    It is inevitable that a certification exam will ask a question that requires understanding the steps involved in a postfix increment or decrement: try the following program:

    Code Sample:

    Java-Basics/Demos/IncrementTest.java

    • In the first statement, i = i++;, the original value of i (0) is retrieved and held. Then, i is incremented. But, after that, the held value of 0 is put back into i, overwriting the 1!
    • In the second part, j = i++ + i;, the operands are evaluated from left to right, but each operand is fully evaluated before proceeding to the next. Which means that the increment part of i++ has taken effect before the second appearance of i in the equation, so that the expression reduces to 0 + 1 (recall that the previous operation resulted in i being 0).

    Expressions that Mix Data Types: Typecasting

    Expressions will often mix different types of data, for example:

    The compiler must choose a specific type of data (either integer or floating-point, and the specific size) for each individual expression it evaluates within a statement.

    • In general, the processor will choose the larger or more complex unit to work with.
    • In the first case the value 4 will be promoted to a double, which will then be used in the division.
    • The conversion is done one expression at a time within a statement; so, in the second example, the division will be performed with integer math, resulting in a value of 3, which will then be promoted to a double to finish the statement.

    The process of changing the data type of a value is known a typecasting (or casting):

    • A wideningcast converts a smaller or less precise value into a larger or more precise type - this is done automatically (the compiler does an implicitcast, as above).
    • A narrowing cast converts a larger or more precise value into a smaller or less precise type (such as from double to int) - this must be coded with an explicit cast.
    • To code an explicit typecast, put the desired type in parentheses in front of the expression to be converted; for example:
    • The division will be evaluated as before, meaning the 4 is promoted to a double, and the result is a double, but a double can't be stored in a, so the cast to int is necessary.
    • Note that casting is an operation, therefore it has a precedence (which is fairly high on the operator precedence table).

    The allowable sequence of implicit casts is shown below:

    Small Integral Types and Expressions

    One aspect of Java that is important to understand is the result of expressions involving the small integral types: byte, char, and short any expression involving these types, other than the compound assignment expressions, is done with int values, so that the result will always be an int.

    Try the following (it is the same as the earlier postfix increment example, using byte instead of int):

    Note that the increment expression is accepted by the compiler; it is the simple addition in the third line that causes an error.

    The Java Language Specification states the promotion rules as follows (note that this concept does not apply to all operators; again, the operators that include assignment do not use it):

    When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value of a numeric type, the following rules apply, in order, using widening conversions to convert operands as necessary:

    • If either operand is of type double, the other is converted to double.
    • Otherwise, if either operand is of type float, the other is converted to float.
    • Otherwise, if either operand is of type long, the other is converted to long.
    • Otherwise, both operands are converted to type int.

    7 - JAVA CREATING AND USING METHODS

    The method is the basic complete unit of code to perform one task within an object:

    • In procedural languages, these are called functions, but in OOP they are usually called methods.
    • Almost all executable code is in some method.
    • Technically, there is one other place an object-oriented program could have executable code, but that is an advanced topic.
    • Examples: calculate a trigonometry function like cosine, print data on the screen, read from a file, open a window.
    • Methods are defined by a name followed by parentheses.
    • Inputs to the method go inside the parentheses; they are called parameters or arguments to the method.

    Using a method in your code, causing it to run, is known as calling the method.

    A method call is an expression, so it may result in a value (the method call is evaluated like any other expression).

    • this value is called the return value, and the method is said to return a value.
    • the following is an example of a method used as an expression within a larger expression:

    Methods must be called with arguments that matching their specified form, known as the function signature:

    • the signature is the combination of the name of the method with the pattern of its parameters.
    • the documentation for library-supplied methods will tell you the signature for those methods.
    • when you call a method, the name of the method and the parameters you pass to it will determine which method will be called, based on the available signatures.
    • for each argument, Java expects a value - which could be a literal value, a variable, or expression; it must be either the correct type or a value that can be implicitly typecast to the correct type.

    All methods in Java must be defined within a class definition. They have complete access to all other elements of the class (fields and other methods, regardless of the access modifier used for that element).

    Code Sample:

    Java-Basics/Demos/UseMethodsExample.java

    This class calls two methods from the Math class: sqrt and sin, both of which expect one parameter which is a double.

    When we call sqrt and pass an integer, the compiler converts that to a double to provide the type of data that sqrt expects

    Note that even if your program does not call any methods, it has one method that will be called: main(). Things to note:

    • The definition of main() is that it provides a start point and end point for your program.
    • Program execution starts with the first statement in main().
    • If the last statement in main() is executed, the program ends.
    • The main() does have arguments (any other words typed on the command line).

    Creating Methods


    There are three things you need to decide for any method:

    1. what it does.
    2. what inputs it needs.
    3. what answer it gives back.
    • modifiers include the accessibility of this method from outside the class (public, private, protected, or left blank) as well as other possibilities listed earlier in this section.
    • dataType is a type of data, like int.
    • methodName is the name of your method.
    • parameterList is a comma-separated list of parameters; each parameter is listed with its data type first, then its name.
    • methodBody is the set of statements that perform the task of the method.
    • return is a keyword that says to use the result expression value as the result of calling the method, and send that value back to the code that called the method (as an expression, a call to a method evaluates to the returned value; i.e., calling Math.sqrt(4) evaluates to the value that sqrt returned).
    • if a method declares that it returns a value of a certain type, then it must explicitly return a value of that type.

    Method Examples

    • public methods are accessible to any other class.
    • void is a keyword for a returned data type that means no data at all - this method does not calculate a result.
    • The name of the method is sayHello.
    • This method could be called as follows:
    showNumber(5); from within the class
    x.showNumber(5); from outside the class, for an instance x of this class
    • This method does calculate a result; the data type it calculates is int.
    • This method must be given two parameters, both of which are int data types.
    • This method could be called as follows:
    int value = calculateSum(4, 6); from within the class
    int value = x.calculateSum(4, 6); from outside the class, for an instance x of this class

    Return Values

    Note that the listing of a data type word in front of a name is something we have seen before, in declaring variables. The purpose is the same - to state what type of data this element provides when used in an expression.

    The first statement below states that the value of a is an int, so that the compiler knows what memory size to allocate and what type of processing to use with it when it evaluates the second statement.

    The effect is no different using a method; recall the function signature (the first line) of our calculateSum method:

    It states that the result of evaluating calculateSum is an int, so that the compiler knows what memory size to allocate for the result, and what type of processing to use with it when it evaluates a statement like:

    When this statement gets processed, the calculateSum method will run and return its result (which will be the value 10 as an int).

    Thus the statement in effect is reduced to:

    Method Parameters


    Method parameters are also declarations. They declare a type of data received by the method, and also provide a name for each value so it can be used within the method.

    Back to our method:

    • The parameter list declares two variables that will exist in this method: num1 and num2.
    • The order is important - num1 will be the first value given to the method, num2 will be the second.
    • The difference between method parameter declarations and the variable declarations we saw before is that the method parameters receive their values when the method is called.

    8 - JAVA VARIABLES SCOPE

    The variable scope rules are similar to those in C++.

    Variables can be declared at any point in your code, not just at the top of a block:

    • Local variables (those within methods) are not visible to any code that precedes the declaration.
    • Object elements are visible to any code within the object, regardless of the order of declaration.

    Variables declared within a set of curly braces cease to exist after the closing brace has been reached (it is said that they go out of scope); therefore, local variables exist only within that method.

    Variables can be declared in the control portion of a for loop, and will exist for the duration of the loop

    Parameters to a method are local variables within that method

    It is legal to use the same variable name in different scopes, as long as the two scopes have no irresolvable conflicts. Some explanation:

    • Non-overlapping scopes. For example, two different methods could each have a local variable called firstName.
    • Overlapping scopes. It is valid for a method to have a variable whose name conflicts with a property name for that class - in that case, the local variable hides the property, but there is a special syntax that allows the method to access the property; we will cover this later.
    • It is legal for a method and a field of a class to have the same name, although it is not considered a good practice to do so.
    • An example of an irresolvable conflict is declaring a local variable within a block when the same name is already in scope in that method as a local variable.

    Code Sample:


    Java-Basics/Demos/MethodExample.java

    We will cover the concept of static elements later, but, for now, since main is static, the methods it calls must be static as well

    9 - JAVA COMPARISONS AND CONTROL STRUCTURES

    Boolean-valued Expressions


    Java has a data type called boolean. Note the following:

    • Possible values are true or false.
    • boolean can be operated on with logical or bitwise operators, but cannot be treated as a 0 or 1 mathematically.
    • boolean can be specified as a parameter type or return value for a method.
    • A boolean value will print as true or false.

    The result of a conditional expression (such as a comparison operation) is a boolean value. Note that:

    • Simple comparisons, such as greater than, equal to, etc., are allowed.
    • Values are returned from functions.
    • Complex combinations of simpler conditions are allowed.

    Conditional expressions are used for program control. That means they provide the ability for a program to branch based on the runtime condition or iterate through a block of code until the condition is false.

    Comparison Operators


    This chart shows the comparison operators and the types of data they can be applied to.

    This chart shows the comparison operators and the types of data they can be applied to.
    Operator
    Purpose (Operation Performed)
    Types of Data
    boolean
    Numeric Primitives and char
    Object References
    == is equal to (note the two equals signs!) X X X
    != is not equal to X X X
    > is greater than X
    < is less than X
    >= is greater than or equal to X
    <= is less than or equal to X

    Note that it is unwise to use == or != with floating-point data types, as they can be imprecise.

    Comparing Objects


    The operators == and != test if two references point to exactly the same object in memory – they test that the numeric values of the two references are the same. The equals(Object o) method compares the contents of two objects to see if they are the same (you can override this method for your classes to perform any test you want).

    Conditional Expression Examples


    The following are conditional expression examples.

    • a = 3; b = 4;
    • a == b will evaluate to false
    • a != b will evaluate to true
    • a > b will evaluate to false
    • a < b will evaluate to true
    • a >= b will evaluate to false
    • a <= b will evaluate to true

    s == t will evaluate to false

    s != t will evaluate to true (they are not the same object - they are two different objects that have the same contents)

    s.equals(t) will evaluate to true

    s == t will evaluate to true

    s != t will evaluate to false (they are the same object)

    s.equals(t) will evaluate to true

    Note: Java will intern a literal String that is used more than once in your code; that is, it will use the same location for all occurrences of that String

    s == t will evaluate to true, because the String object storing "Hello" is stored only once, and both s and t reference that location

    s != t will evaluate to false (they are the same object)

    s.equals(t) will evaluate to true


    Complex boolean Expressions


    Java has operators for combining boolean values with AND and OR logic, and for negating a value (a NOT operation). Note that:

    • There are also bitwise operators for AND, OR, and bitwise inversion (changing all 1 bits to 0, and vice versa).
    • Since a boolean is stored as one bit, the bitwise AND and OR operators will give the same logical result, but will be applied differently (see below).
    • For some reason, the bitwise NOT cannot be applied to a boolean value.
    Logical Bitwise
    && logical AND & bitwise AND
    || logical OR | bitwise OR
    ! logical NOT ~ bitwise NOT (inversion)
    Code Effect
    Testing if a value falls within a range

    ( ( a >= 0 ) && ( a <= 10 ) )

    is true if a is falls between 0 and 10; it must satisfy both conditions

    Testing if a value falls outside a range

    ( ( a < 0 ) || ( a > 10 ) )

    is true if a falls outside the range 0 to 10; it may be either below or above that range

    ( !( ( a >= 0 ) && ( a <= 10) ) )

    inverts the test for a between 0 and 10; so a must be outside the range instead of inside it

    The && and || operations are called short-circuiting, because if the first condition determines the final outcome, the second condition is not evaluated.

    To force both conditions to be evaluated, use & and | for AND and OR, respectively.

    Example: to test if a reference is null before calling a boolean valued method on it.

    equalsIgnoreCase will be called only if the reference is not null.

    The if Statement


    or

    Causes "one thing" to occur when a specified condition is met.

    The one thing may be a single statement or a block of statements in curly braces. The remainder of the code (following the if and the statement or block it owns) is then executed regardless of the result of the condition.

    The conditional expression is placed within parentheses.

    The following flowchart shows the path of execution:

    if Statement Examples


    Absolute Value

    If we needed the absolute value of a number (a number that would always be positive):

    Code Sample:

    Java-Control/Demos/If1.java

    Random Selection

    Task: write a brief program which generates a random number between 0 and 1. Print out that the value is in the low, middle, or high third of that range (Math.random() will produce a double value from 0.0 up to but not including 1.0).

    • Although it is a bit inefficient, just do three separate tests: (note that Math.random() will produce a number greater than or equal to 0.0 and less than 1.0).

    Code Sample:

    Java-Control/Demos/If2.java

    Game01: A Guessing Game


    Duration: 15 to 20 minutes. Write a program called Game that will ask the user to guess a number and compare their guess to a stored integer value between 1 and 100.

    1. Use a field called answer to store the expected answer.
    2. For now, just hard-code the stored value; we will create a random value later (your code will be easier to debug if you know the correct answer).
    3. Create a method called play() that holds the logic for the guessing. Use the KeyboardReader class to ask for a number between 1 and 100, read the result, and tell the user if they are too low, correct, or too high.
    4. Create a main method, have it create a new instance of Game and call play().

    Solution:

    Solutions/Game01/Game.java

    Each of the the three possible cases is tested individually as shown below. All three tests will always be performed. In the next version, we will make the tests mutually exclusive, so that processing stops when one is true. we will use a more efficient approach.

    Payroll-Control01: Modified Payroll


    Duration: 10 to 15 minutes. We will modify our payroll program to check the pay rate and department values.

    1. The Employee class should protect itself from bad data, so modify setPayRate and setDept to check the incoming data (and ignore it if it is less than 0).
    2. Test your program to see what happens with negative input values.
    3. The code using Employee should avoiding sending it bad data, so also change main in Payroll.java to check for acceptable pay rate and department values (print an error message for any negative entry, then just set that variable to 0 (for lack of anything better that we can do right now. Later we will find a way to ask the user for a new value instead)

    Solution:

    Solutions/Payroll-Control01/employees/Employee.java

    The Employee class should protect itself from bad incoming data, so the setPayRate method simply ignores a value less than 0. A better practice, which we will add later, would be to throw an exception when an illegal value is passed in. Note the benefit of coding the constructors to use the setPayRate method; we do not have to go back and revise their code as well. (setDept has similar changes.)

    Solution:

    Solutions/Payroll-Control01/Payroll.java

    Even though Employee now protects itself from illegal incoming values, it should really be the responsibility of the progmmers for the classes using Employee to avoid sending it bad values. So, the payRate value is tested here as well. While this may seem to decrease efficiency (since, presumably, a non-object-oriented program might be able to avoid testing the value twice in a row), the maintainability aspects of OOP are still considered to outweigh the loss in efficiency.

    Two Mutually Exclusive Branches


    The if ... else Statement

    The if ... else Statement does "one thing" if a condition is true, and a different thing if it is false.

    It is never the case that both things are done. The "one thing" may be a single statement or a block of statements in curly braces.

    A statement executed in a branch may be any statement, including another if or if ... else statement.

    This program tells you that you are a winner on average once out of every four tries.

    Code Sample:

    Java-Control/Demos/IfElse1.java

    Nested if ... else Statements - Comparing a Number of Mutually Exclusive Options

    You can nestif ... else statements, so that an if or else clause contains another test. Both the if and the else clause can contain any type of statement, including another if or if ... else.

    You can test individual values or ranges of values. Once an if condition is true, the rest of the branches will be skipped. You could also use a sequence of if statements without the else clauses (but this doesn't by itself force the branches to be mutually exclusive).

    Here is the low/middle/high example rewritten using if ... else

    Code Sample:

    Java-Control/Demos/IfElse2.java

    Similarly, we do not test the high third at all. The original version worked because there was no chance that more than one message would print; that approach is slightly less efficient because all three tests will always be made. In the if ... else version, comparing stops once a match has been made.

    Game02: A Revised Guessing Game


    Duration: 10 to 15 minutes.

    1. Revise your number guessing program to use if . . . else logic (you can test for too low and too high, and put the message for correct in the final else branch).
    2. Once you have done that, here is a way to generate a random answer between 1 and 100:

    1.At the top:

    2.Add a private field for a random number generator:

    1.Then, you can initialize the answer field:

    the nextInt(int n) method generates a number greater than or equal to 0 and less than n, so r.nextInt(100) would range from 0 through 99; we need to add 1 to raise both ends of the range.

    4.You might want to print the expected correct answer to aid debugging.

    Note that until we cover looping, there will be no way to truly "play" the game, since we have no way to preserve the value between runs.

    Solution:

    Solutions/Game02/Game.java

    Comparing a Number of Mutually Exclusive options - The switch Statement


    The switch Statement

    A switch expression (usually a variable) is compared against a number of possible values. It is used when the options are each a single, constant value that is exactly comparable (called a case).

    The switch expression must be a byte, char, short, or int. Cases may only be byte, char, short, or int values; in addition, their magnitude must be within the range of the switch expression data type and cannot be used with floating-point datatypes or long and cannot compare an option that is a range of values, unless it can be stated as a list of possible values, each treated as a separate case.

    Cases are listed under the switch control statement, within curly braces, using the case keyword. Once a match is found, all executable statements below that point are executed, including those belonging to later cases; this allows stacking of multiple cases that use the same code.

    The break; statement is used to jump out of the switch block, thus skipping executable steps that are not desired. The default case keyword catches all cases not matched above - note that the default case does not need to be the last thing in the switch. Note that technically speaking, the cases are labeled lines; the switch jumps to the first label whose value matches the switch expression.

    Usage

    switch Statement Examples

    Code Sample:

    Java-Control/Demos/Switch1.java

    Three points to note:

    • Stacking of cases for uppercase and lowercase letters allows both possibilities.
    • break; statements used to separate code for different cases.
    • default: clause used to catch all other cases not explicitly handled.

    Here is a revised version that moves the default to the top, so that a bad entry is flagged with an error message, but then treated as an 'A' - note that there is no break below the default case.

    Code Sample:

    Java-Control/Demos/Switch2.java

    Another example is taking advantage of the "fall-though" behavior without a break statement.

    Code Sample:

    Java-Control/Demos/Christmas.java

    Game03: Multiple Levels


    Duration: 15 to 30 minutes. What if we want to offer gamers multiple levels of difficulty in our game? We could make the random number multiplier a property of the Game class, and set a value into it with a constructor, after asking the user what level they'd like to play.

    1. Add a range field to the Game class (an int).
    2. Add a constuctor that accepts a level parameter; use a char.
    3. Within that constructor, use a switch to process the incoming level:
      • Uppercase or lowercase B means Beginner, set the range to 10.
      • I means Intermediate; set the range to 100.
      • A means Advanced; set the range to 1000.
      • Any other value results a Beginner game; after all, if they can't answer a simple question correctly, how could we expect them to handle something more advanced.
      • You could put the default option stacked above the "B" cases, so that you can print an error message and then fall through to the 'B' logic
    4. object's nextInt method (move the logic that creates the Random object and generates the answer to this constructor).
    5. Add a default constructor that calls this new constructor, passing 'I' for intermediate.
    6. The prompt given by the play method should now take the range into account.
    7. In the main method, ask the user for the level and call the new constructor with their response.

    Solution:

    Solutions/Game03/Game.java

    The switch tests for the three letters, stacking cases for uppercase and lowercase values. The default catches all other responses and falls through to the Beginner logic.

    Comparing Objects


    The operators == and != test if two references point to exactly the same object in memory; they test that the numeric values of the two references are the same.

    The equals(Object o) method compares the contents of two objects to see if they are the same (you can override this method for your classes to perform any test you want).

    When comparing two objects, the == operator compares the references and not the values of the objects. Similarly, != tests to see if the references point to two different objects (even if they happen to have the same internal values).

    The Object class defines an equals(Object) method intended to compare the contents of the objects. The code written in the Object class simply compares the references using ==. This method is overridden for most API classes to do an appropriate comparison. For example, with String objects, the method compares the actual characters up to the end of the string. For classes you create, you would override this method to do whatever comparisons you deem appropriate.

    Code Sample:

    Java-Control/Demos/Rectangle.java

    The equals method compares another object to this object.

    This example is necessarily somewhat complicated. It involves a few concepts we haven't covered yet, including inheritance. Because the equals method inherited from Object, it takes a parameter which is an Object, we need to keep that that type for the parameter (technically, we don't need to do it by the rules of Java inheritance, but because other tools in the API are coded to pass an Object to this method). But, that means that someone could call this method and pass in something else, like a String.

    So, the first thing we need to do is test that the parameter was actually a Rectangle. If so, we can work with it; if not, there is no way it could be equal, so we return false.

    We will cover instanceof later, but, for now, we can assume it does what it implies: test that the object we received was an instance of Rectangle. Even after that test, in order to treat it as a Rectangle, we need to do a typecast to explicitly store it into a Rectangle variable (and again, we will cover object typecasting later). Once we have it in a Rectangle variable, we can check its height and width fields.

    In yet another complication, if we write an equals method, we should really write a public int hashcode() method as well, since their meanings are interrelated; two elements that compare as equal should produce the same hashcode.

    As an aside, note that private data in one instance of a class is visible to other instances of the same class; it is only otherclasses that cannot see the private elements.

    Code Sample:

    Java-Control/Demos/ObjectEquivalenceIdentity.java

    Since all the important work is done in Rectangle, all we need to do here is instantiate two and compare them using both == and the equals method to see the differing results.

    The output should be:

    Testing Strings for Equivalence

    Example - write a brief program which has a word stored as a string of text. Print a message asking for a word, read it, then test if they are the same or not.

    • you can preset the message assuming that they are incorrect, then change it if they are correct

    Code Sample:

    Java-Control/Demos/StringEquals.java

    • try this, then change equals(t) to equalsIgnoreCase(t)

    Conditional Expression


    Java uses the same conditional expression as C and C++

    This performs a conditional test in an expression, resulting in the first value if the condition is true,or the second if the condition is false

    Note: due to operator precedence issues, it is often best to enclose the entire expression in parentheses

    Example

    Code Sample:

    Java-Control/Demos/Conditional.java

    Note that the parentheses around the test are not necessary by the operator precedence rules, but may help make the code clearer

    The parentheses around the entire conditional expression are necessary; without them, precedence rules would concatenate the boolean result onto the initial string, and then the ? operator would be flagged as an error, since the value to its left would not be a boolean.

    while and do . . . while Loops

    Again, the loops in Java are pretty much the same as in C - with the exception that the conditional expressions must evaluate to only boolean values

    while loops

    or

    • continues as long as the expression evaluates to true
    • the condition is evaluated before the start of each pass
    • it is possible that the body of the loop never executes at all (if the condition is false the first time)
    do ... while loops

    or

    • evaluated after the end of each pass
    • the body of the loop will always execute at least once, even if the condition is false the first time
    for Loops

    A for loop uses a counter to progress through a series of values

    • a value is initialized, tested each time through, and then modified (usually incremented) at the end of each pass, before it is tested again
    • the for loop does not do anything that cannot be done with a while loop, but it puts everything that controls the looping at the top of the block


    or

    for loops can use a variable declared out side of the control portion of the loop or in the control portion. The latter gives the variable block-level scope (existing only for the duration of the loop)

    A for loop may use multiple control variables by using the sequence operator, the comma ( , )

    Note: if you use a block-scope variable (such as above) for the first counter, the additional ones will be block scope as well, and also will be the same type of data - i.e., the variable k above also exists only for the duration of the block. There is no way to declare two counters of different types at block-level scope.

    Note that neither while nor do . . . while loops allow declaring a looping variable with this type of scope. The looping variable must be declared in advance.

    ForEach Loops

    Java 5 introduced a new type of loop, the for-each loop. When you have an array or collection class instance, you can loop through it using a simplified syntax

    The looping variable is not a counter - it will contain each element of the array or collection in turn (the actual value and not an index to it, so its type should be the same as the type of items in the array or collection). You can read the : character as if it is the word "from". We will cover this type of loop in more depth in the Arrays section.

    For some reason, the looping variable must be declared within the parentheses controlling the loop - you cannot use a preexisting variable.

    Since the looping variable is a local variable, it gets a copy of each value from the array or collection. Therefore you cannot use the ForEach loop to write values back to the array/collection - assigning a new value to the variable in the body of the loop is only overwriting the local copy.

    Code Sample:

    Java-Control/Demos/Loops1.java

    Additional Loop Control: break and continue


    Breaking Out of a Loop

    The break statement will end a loop early and execution jumps to the first statement following the loop. The following example prints random digits until a random value is less than 0.1.

    Code Sample:

    Java-Control/Demos/Break.java

    This code loops, generating and printing a random number for each iteration. If the number is less than 0.1, we break out before printing it.

    Code Sample:

    Java-Control/Demos/BreakNot.java

    This code avoids the break, by creating and testing the random number in the control part of the loop. As part of the iteration condition, if the number is less than 0.1, the loop simply ends "normally".

    Continuing a Loop


    If you need to stop the current iteration of the loop, but continue the looping process, you can use the continue statement. Note that:

    • It is normally based on a condition of some sort.
    • Execution skips to the end of this pass, but continues looping.
    • It is usually a better practice to reverse the logic of the condition, and place the remainder of the loop under control of the if statement.

    Example - a program to enter 10 non-negative numbers

    Code Sample:

    Java-Control/Demos/Continuer.java

    A better way to handle the loop is shown in the commented out version of main - try removing the comment and comment out the original method.

    But,continue is easier to use in nested loops, because you can label the level that will be continued

    break and continue in Nested Loops

    In normal usage, break and continue only affect the current loop; a break in a nested loop would break out of the inner loop, not the outer one

    But, you can label a loop, and break or continue at that level. A label is a unique identifier followed by a colon character.

    Try the following example as is, then reverse the commenting on the break lines

    Code Sample:

    Java-Control/Demos/BreakOuter.java

    Game04: Guessing Game with a Loop


    Duration: 10 to 20 minutes.
    (Optional)

    1. Revise the number guessing program to force the user to guess until they are correct (loop-wise, to keep guessing as long as they are incorrect).
    2. Then add more logic to ask if they want to play again, read a Y or N as their answer, and loop as long as they enter a Y.

    Solution:

    Solutions/Game04/Game.java

    Payroll-Control02: Payroll With a Loop


    Duration: 20 to 40 minutes.

    1. Revise your payroll program to use only one Employee variable.
    2. Use a loop to repeatedly create a new instance to store in it, populate it from the keyboard, and display it on the screen (you can ask after each one if the user wants to enter another, or just use a loop that has a fixed number of iterations).
    3. Also, change the logic for reading the pay rate and department values from the keyboard to use do . . . while loops that will continue to loop as long as the user enters invalid values (note that you will need to separate declaring the variables from populating them - declare each of them before their loop starts, in order for the variable to be available to the test at the end of the loop).

    Solution:

    Solutions/Payroll-Control02/Payroll.java

    Classpath, Code Libraries, and Jar Files


    By now, you may have noticed that every demo and solution folder contains its own copy of util and KeyboardReader. Not only is it inefficient, but it means that we would have to locate and update each copy if we wanted to change KeyboardReader.

    A better solution would be to have one master copy somewhere that all of our exercises could access.

    Using CLASSPATH
    Java has a CLASSPATH concept that enables you to specify multiple locations for .class files, at both compile-time and runtime.

    By default, Java uses rt.jar in the current Java installation's jre/lib directory, and assumes that the classpath is the current directory (the working directory in an IDE).
    If you create a classpath, the default one disappears, so any classpath that you create must include the current directory using a period (.) character.

    To use an external library, you would need to create a classpath in one of two ways:

    1. you can create a system or user environment variable, with multiple directories and/or .jar files, separated by the same delimiter used by your PATH (a semicolon in Windows).
    2. You could use the -classpath option in java and javac (-cp is a shorthand version of that).

    Here is an example of a pair of commands to compile and run using an external library stored in a jar file. Note that we need the jar file at both compile-time and runtime. The -cp option in both commands replaces the system classpath with one specifically for that command.

    Many Integrated Development Environments (IDEs) have a means to specify project properties; usually an item like "Build Path" will have options to specify external jar files (as well as choose from various libraries supplied with the environment).

    Creating a jar File (a Library)
    If you wish to create your own library of useful classes, you can bundle one or more classes and/or directories of classes in a jar file. Yyou can also add other resources such as image files.

    A jar file contains files in a zipped directory structure. The root level of the file structure should match the root of the package structure; for example, to put KeyboardReader in a jar file, we would want to start at the directory where util is visible, and jar that

    The following command will create a jar file called utilities.jar for all files in the util package (just KeyboardReader, in this case).

    The options are create, verbose, and use a list of files supplied at the end of the command.

    Creating and Using an External Library


      Duration: 5 to 10 minutes.
    1. Run the command shown above to create utilities.jar.
    2. Move utilities.jar to the ClassFiles directory in your filesystem.
    3. If you remove the util directory from Payroll-Control02, you will not be able to compile or run Payroll as we have been doing.
    4. But, you should be able to compile and run by specifiying a classpath option as shown in the commands above.
    5. You can also temporarily modify the classpath for the duration of your command prompt window as follows (note that you may need to modify the line below to match your setup):

    The destination directory can be a relative path from the current directory, or an absolute path. It must already exist, but any subdirectories necessary for package structures will be created.

    Also, if you have existing compiled files in the source directories (like employees/Employee.class), then the compiler won't recompile those classes (and therefore they won't end up in the destination path) unless they are older than the associated .java file. You would need to "clean" the directories by deleting the .class files first.

    CLASSPATH=%CLASSPATH%;c:\Java102\ClassFiles\utilities.jar

    10 - JAVA ARRAYS

    Defining and Declaring Arrays


    An array stores a group of data items all of the same type.

    An array is an object.

    • An array variable does not actually store the array - it is a reference variable that points to an array object.
    • Declaring the array variable does not create an array object instance; it merely creates the reference variable - the array object must be instantiated separately.
    • Once instantiated, the array object contains a block of memory locations for the individual elements.
    • If the individual elements are not explicitly initialized, they will be set to zero.
    • Arrays can be created with a size that is determined dynamically (but once created, the size is fixed).
    • Declare an array variable by specifying the type of data to be stored, followed by square brackets [].

    You can read the [] as the word "array".

    To declare a variable for an array of integers:

    ..which you can read as "int array nums".

    To declare a variable for an array of String objects:

    ...which you can read as "String array names" - the array holds String references.

    You may also put the brackets after the variable name (as in C/C++), but that is less clearly related to how Java actually works.

    But, that syntax does allow the following, which is legal, but seems like a bad practice.

    Instantiating Arrays


    Instantiate an array object using new, the data type, and an array size in square brackets

    The second line constructs a new array object with 10 integer elements, all initialized to 0, and stores the reference into nums.

    You can declare and instantiate all at once:

    The elements of the array, String references, are initialized to null.

      As objects, arrays also have a useful property: length:
    • In the above example, names.length would be 3.
    • The property is fixed (i.e., it is read-only).
    • You can reassign a new array to an existing variable:

    The original ten-element array is no longer referenced by nums, since it now points to the new, larger array.

    Initializing Arrays


    An array can be initialized when it is created

    The notation looks like this:

    or

    This automatically creates an array of length 3, because there were 3 items supplied.

    This array will have a length of 6.

    If a new array is being assigned to an existing variable, you cannot use the shorter variant, you must use the new keyword and the data type:

    For arrays of other types of objects:

    Working With Arrays


      Array elements are accessed through the array reference, by their array index:
    • The index is the element number, placed within brackets.
    • Elements are numbered from 0 to one less than the specified size.

    The valid elements are 0, 1, and 2, as in:

    You could access array elements in a for loop with:

    Or, better programming practice would be to use the length property:

    The compiler does not check to ensure that you stay within the bounds of the array, but the JVM does check at runtime - if you try to exceed the bounds of the array, an exception will occur.

    Note that a zero-length array is valid:

    You might create a zero-length array as the return value from a method typed as returning an array, when there are no items to return (as opposed to returning null).

    Code Sample:

    Java-Arrays/Demos/Arrays1.java

    Array Variables


    The array as a whole can be referenced by the array name without the brackets, for example, as a parameter to or return value from a function

    Code Sample:

    Java-Arrays/Demos/Arrays2.java

    The array names is passed to printArray, where it is received as data.

    Note also the syntax to access a method directly for an array element: data[i].toUpperCase()

    Since an array reference is a variable, it can be made to refer to a different array at some point in time

    Copying Arrays


    You can use System.arraycopy to copy an array into another.

    You might do this to expand an array by creating a larger one and copying the contents of the smaller one into it (but any references to the original array will need to be changed to point to the new array).

    The declaration is:

    Code Sample:

    Java-Arrays/Demos/CopyArray.java

    • The first arraycopy line copys from nums into the first half of biggerNums. The number of items copied is determined by nums.length
    • The second arraycopy line again copys from nums, but now into the second half of biggerNums. The starting location for the "paste" is nums.length, since that is where we left off the first time. And the number of items copied is again determined by nums.length

    Using the args Array


      Duration: 5 to 10 minutes.
    1. Note that there has been an array declaration in all of our examples thus far; the array of strings passed to main: args
      • These are the additional words on the command line.
    2. Copy Hello.java to HelloArgs.java, and modify that to loop through args to print each element (remember to rename the class in the declaration line).
    3. Then run the program with something like java HelloArgs From Me and see what happens.

    Solution:

    Solutions/Arrays/HelloArgs.java

    The for loop iterates through the array; each separate word on the command line becomes one element in the array (note that java HelloArgs is not part of the array).

    Game-Arrays01: A Guessing Game with Random Messages


      15 20 (Optional - if time permits)
    • Modify your guessing game program to hold an array of several different String messages, all of which have some form of message for "Correct".
    • Generate a random number in the range from 0 to the size of the array.
    • Use this value to select one message to print when they guess correctly.
    • Continue this approach for "Too Low" and "Too High".

    There are three arrays of messages; note that they are not all the same size. The code to handle too high, too low, and correct generates a random number between 0 and the appropriate array's length, by using the Random object's nextInt method, and passing the length of the array.

    Arrays of Objects


    If an array contains objects, those objects' properties and methods may be accessed.

    The notation uses the array variable name, the index in brackets, a dot, and the property or method.

    Java-Arrays/Demos/Arrays2.java

    Code Sample:

    Payroll-Arrays01: An Array of employees


      Duration: 20 to 30 minutes.
    1. Modify the payroll program to use an array of Employee objects with a size of 3 or more (later we will come up with a more flexible solution that allows for the number of employees to change dynamically).
    2. Use a for loop to populate and display the data.
    3. After the loop is complete, ask the user to enter a last name.
    4. Loop through the array to find the element with the matching last name and display it.

    Solution:

    Solutions/Payroll-Arrays01/Payroll.java

    The code uses e[i].getPayInfo() to print the pay information for employee i. Element i of the array is one employee reference. It uses the same approach to call e[i].getLastName() for each employee to compare with the requested name.

    Enhanced for Loops - the For-Each Loop


      Java 5 introduced the for-each loop, which loops through a collection of values without using an index. Instead, the loop variable repesents each individual value.

      The syntax uses a loop variable and a collection of values, separated by a colon character (which can be read as the word "from"). Some things to note:

    • The collection of values can be any array or an instance of one of the Java Collections classes (to be discussed later)
    • The looping variable must be declared in the parentheses that create the loop - you cannot use a preexisting variable as the loop variable
    • The looping variable will represent each item from the collection or array in turn.

    You cannot write into the array using a for-each loop. The looping variable you declare receives a copy of the data in the array, so, if you change its value, you are only changing the local copy.

    Multi-Dimensional Arrays


      Arrays may have more than one dimension, for such things as:
    • A graphic image that is x pixels across and y pixels vertically.
    • Weather information modeled in a 3-dimensional space, with measurements for these axes: North/South, East/West, and altitude.
    • Declare a multidimensional array as:

    Arrays are objects, and, like other objects, declaring a variable does not instantiate the array - that must be done separately. To instantiate a multidimensional array:

    The most significant dimension is listed first; the least significant dimension listed last.

    The code below could be used to declare an array to store an image that is 640 pixels across and 480 pixels down - in a graphic the image data is stored sequentially across each row; each row is a 640 pixel block; there are 480 of these blocks in our image:

    This code might be used for an image where the data is stored in three layers, each of which is an entire 480 by 640 array:

    Multidimensional Arrays in Memory


      Recall that a matched pair of brackets after a data type means:
    • The array contains elements of that type.
    • The array itself is a type of data.
    • So a two-dimensional array written as this:

    ...could be thought of as an array of integer arrays, as if it were written as (note that this is not legal syntax): In Java, a two-dimensional array is actually a single array of array reference variables, each of which points to a single dimensional array. To extend the example above: This is an array of 3 elements, each of which is an array of 6 int elements as shown in the diagram below:

    Note that it is possible to replace any of the one-dimensional elements with a different one, or that the second-dimension arrays each have a different length - the following line would replace one of the arrays with another of a different length

    Example - Printing a Picture


      This example uses a two-dimensional array preloaded with text characters that make up a picture
    • There is a loop that processes each row (the first, or most significant, dimension of the array, each element of which is an array of characters).
    • Within that loop, another loop prints each character without ending the line.
    • Then, when the inner loop is done, a newline is printed.

    Code Sample:

    Java-Arrays/Demos/ArrayPicture.java

    public class ArrayPicture { public static void main(String[] args) { char[][] imgData = new char[][] { { ' ',' ',' ',' ',' ',' ',' ' }, { ' ',' ',' ','0',' ',' ',' ' }, { ' ',' ',' ','|',' ',' ',' ' }, { ' ','0','-','+','-','0',' ' }, { ' ',' ',' ','|',' ',' ',' ' }, { ' ',' ',' ','0',' ',' ',' ' }, { ' ',' ',' ',' ',' ',' ',' ' } }; for (int row = 0; row < imgData.length ; row++ ) { for (int col = 0; col < imgData[row].length; col++ ) { System.out.print(imgData[row][col]); } System.out.println(); } } }

    Because multi-dimensional arrays are implemented as arrays of array references, it is possible to partially instantiate an array:

    This creates nums as a two-dimensional array (better viewed in this case as an array of array references), and creates an array holding three null references to integer arrays

    Typecasting with Arrays of Primitives


    It is not possible to typecast an array of one type of primitive to an array of another type of primitive. For example, the following will cause compiler errors if the comment marks are removed:

    Code Sample:

    Java-Arrays/Demos/ArrayTypecast.java

    Neither an implicit or explicit typecast can be performed. With a single int i, the copy of it that is given to d can be expanded to a double. But, with the int[] inums, the value that would be given to dnums is just a copy of the reference to inums, so there is no way that each of the individual elements can be expanded to double.

    The next chapter will discuss typecasting from arrays of one type of object to another.

    11 - JAVA INHERITANCE

      Inheritance creates a new class definition by building upon an existing definition (you extend the original class).

      The new class can, in turn, can serve as the basis for another class definition.

    • All Java objects use inheritance.
    • Every Java object can trace back up the inheritance tree to the generic class Object.
    • The keyword extends is used to base a new class upon an existing class

      Several pairs of terms are used to discuss class relationships (these are not keywords).
    • Note that traditionally the arrows point from the inheriting class to the base class, and the base class is drawn at the top - in the Unified Modeling Language (UML) the arrows point from a class to another class that it depends upon (and the derived class depends upon the base class for its inherited code).
    • The parent class/child class terms are not recommended, since parent and child is more commonly used for ownership relationships (like a GUI window is a parent to the components placed in it).
    • A derived class instance may be used in any place a base class instance would work - as a variable, a return value, or parameter to a method. Inheritance is used for a number of reasons (some of the following overlap):
    • To model real-world hierarchies.
    • To have a set of pluggable items with the same "look and feel," but different internal workings.
    • To allow customization of a basic set of features.
    • When a class has been distributed and enhancements would change the way existing methods work (breaking existing code using the class).
    • To provide a "common point of maintenance."
    • When extending a class, you can add new fields and methods and you can change the behavior of existing methods (which is called overriding the methods).
    • You can declare a method with the same signature and write new code for it.
    • You can declare a field again, but this does not replace the original field; it shadows it (the original field exists, but any use of that name in this class and its descendants refers to the memory location of the newly declared element).

    Inheritance Examples


    Say you were creating an arcade game, with a number of different types of beings that might appear - wizards, trolls, ogres, princesses (or princes), frogs, etc. All of these entities would have some things in common, such as a name, movement, ability to add/subtract from the player's energy - this could be coded in a base class Entity.

    For entities that can be chosen and controlled by a player (as opposed to those that merely appear during the course of the game but can't be chosen as a character) a new class Playable could extend Entity by adding the control features.

    Then, each individual type of entity would have its own special characteristics; those that can be played would extend Playable, the rest would simply extend Entity.

    you could then create an array that stored Entity objects, and fill it with randomly created objects of the specific classes. For example, your code could generate a random number between 0 and 1; if it is between 0.0 and 0.2, create a Wizard, 0.2 - 0.4 a Prince, etc.

    The Java API is a set of classes that make extensive use of inheritance. One of the classes used in the GUI is Window; its family tree looks like this:

    Payroll with Inheritance


    Our payroll program could make use of inheritance if we had different classes of employees: exempt employees, nonexempt employees, and contract employees

  • They all share basic characteristics such as getting paid (albeit via different algorithms), withholding, having to accumulate year-to-date numbers for numerous categories.
  • But they have different handling regarding payment calculations, benefits, dependents, etc.
  • Exempt employees get a monthly salary, while nonexempt get a wage * hours, contract employees are handled similarly to nonexempt, but cannot have benefits or dependents.
  • This would leave us with an inheritance scheme as follows:

    Note that a scheme with ContractEmployee extending NonexemptEmployee might also be a reasonable approach

    Derived Class Objects


    You can view a derived class object as having a complete base class object inside it. Let's assume that the Entity class defines the fields name, energy, and position, and methods moveTo() and changeEnergy().

    The Playable class adds a field playerID, and the Wizard class adds a spells field (an array of spells they can cast) and a castSpell() method.

    Any Wizard object contains all the elements inside its box, include those of the base classes. So, for example, the complete set of properties in a Wizard object is:

    • name
    • energy
    • position
    • playerID
    • spells

    A Wizard reference to a Wizard object has access to any public elements from any class in the inheritance chain from Object to Wizard. Code inside the Wizard class has access to all elements of the base classes (except those defined as private in the base class - those are present, but not directly accessible).

    A more complete description of access levels is coming up.

    Note: although it appears that a base class object is physically located inside the derived class instance, it is not actually implemented that way.

    Polymorphism


    Inheritance and References

    If a derived class extends a base class, it is not only considered an instance of the derived class, but an instance of the base class as well. The compiler knows that all the features of the base class were inherited, so they are still there to work in the derived class (keeping in mind that they may have been changed).

    This demonstrates what is known as an Is A relationship - a derived class object is A base class instance as well.

    It is an example of polymorphism; that one reference can store several different types of objects. For example, in the arcade game example, for any character that is used in the game, an Entity reference variable could be used, so that at runtime, any subclass can be instantiated to store in that variable.

    For the player's character, a Playable variable could be used.

    When this is done, however, the only elements immediately available through the reference are those know to exist; that is, those elements defined in the reference type object. Note that:

    • The compiler decides what to allow you to do with the variable based upon the type declared for the variable.
    • merlin.moveTo() would be legal, since that element is guaranteed to be there.
    • merlin.castSpell() would not be legal, since the definition of Entity does not include it, even though the actual object does have that capability.
    • The following example gives a hint as to why this is the case:

    There is no way the compiler could determine what type of object would actually be created.
    The variables names above, shrek, merlin, and charles, are probably not good choices: presumably we know shrek is an ogre, and always will be, so the type might as well be Ogre (unless, of course, he could transmogrify into something else during the game ...).

    Dynamic Method Invocation

    When a method is called through a reference, the JVM looks to the actual class of the instance to find the method. If it doesn't find it there, it backs up to the ancestor class (the class this class extended) and looks there (and if it doesn't find it there, it backs up again, potentially all the way to Object).

    Sooner or later, it will find the method, since if it wasn't defined somewhere in the chain of inheritance, the compiler would not have allowed the class to compile.

    In this manner, what you could consider the most advanced (or most derived) version of the method will run, even if you had a base class reference.

    So, for our arcade game, an Entity reference could hold a Wizard, and when the moveTo method is called, the Wizard version of moveTo will run.

    An interesting aspect of dynamic method invocation is that it occurs even if the method is called from base class code. If, for example:

    • The Entity class moveTo method called its own toString method.
    • The Ogre class didn't override moveTo, but did override toString.
    • For an Ogre stored in an Entity variable, the moveTo method was called.

    The Entity version of moveTo would run, but its call to toString would invoke the toString method from Ogre!

    Creating a Derived Class


    The syntax for extending a base class to create a new class is:

    If you do not extend any class, Java assumes you are extending Object by default

    Your new class can use the fields and methods contained in the original class (subject to the note coming up in a few pages about access keywords), add new data fields and methods, or replace fields or methods.

    A derived class object may be stored in a base class reference variable without any special treatment. If you then want to store that object in a derived class reference again, you can force that with a typecast.

    Java doesn't allow multiple inheritance, where one class inherits from two or more classes. Note that:

    • It does have a concept called an interface, which defines a set of method names.
    • A class may implement an interface, defining those methods in addition to whatever other methods are in the class.
    • This allows for several otherwise unrelated classes to have the same set of method names available, and to be treated as the same type of object for that limited set of methods.

    Inheritance Example - A Derived Class


    When a derived class is created, an object of the new class will in effect contain all the members of the base and derived classes. In some cases, the accessibility modifiers can limit base class members availability in the derived class, but we will cover that issue later.

    The following maps out the relation between the derived class and the base class (note that the diagrams show the apparent memory allocation, in a real implementation the base class memory block is not inside the derived class block).

    Class Code Apparent Memory Allocation
    public class MyBase {
    public int x;
    public void show() {
    System.out.println("x =" + x);
    }
    MyBase memory structure
    class MyDerived extends MyBase {
    public int y;
    public void show() {
    System.out.println("x = " + x);
    System.out.println("y = " + y);
    	}
    }
    MyDerived memory structure

    Since everything in MyBase is public, code in the MyDerived class has free access to the x value from the MyBase object inside it, as well as y and show() from itself.

    The show() method from MyBase is also available, but only within MyDerived class code (but some work is required to get it, since it is hidden by the show() method added with MyDerived) - code in other classes cannot invoke the MyBase version of show() at all.

    Inheritance and Access


    When inheritance is used to create a new (derived) class from an existing (base) class, everything in the base class is also in the derived class. It may not be accessible; however, the access in the derived class depends on the access in the base class:

    Base class access Accessibility in derived class
    public public
    protected protected
    private Inaccessible
    Unspecified (package access) Unspecified (package access)

    Note that private elements become inaccessible to the derived class - this does not mean that they disappear, or that that there is no way to affect their values, just that they can't be referenced by name in code within the derived class

    Also note that a class can extend a class from a different package

    Inheritance and Constructors - the super Keyword


    Since a derived class object contains the elements of a base class object, it is reasonable to want to use the base class constructor as part of the process of constructing a derived class object.

    Constructors are "not inherited". In a sense, this is a moot point, since they would have a different name in the new class, and can't be called by name under any circumstances, so, for example, when one calls new Integer(int i) they shouldn't expect a constructor named Object(int i) to run.

    Within a derived class constructor, however, you can use super( parameterList ) to call a base class constructor. Note that:

      I
    • t must be done as the first line of a constructor.
    • Therefore, you can't use both this() and super() in the same constructor function.
    • If you do not explicitly invoke a form of super-constructor, then super() (the form that takes no parameters) will run.
    • For the superclass, its constructor will either explicitly or implicitly run a constructor for its superclass.
    • So, when an instance is created, one constructor will run at every level of the inheritance chain, all the way from Object up to the current class.

    Code Sample:

    Java-Inheritance/Demos/Inheritance1.java

    The diagram below shows the structure of our improved classes:

    • A MyDerived object has two constructors available, as well as both the getX and getY methods and the show method.
    • Both MyDerived constructors call the super constructor to handle storage of x.
    • The show method in the derived class overrides the base class version.
    • Note that you can tell which class's version of show() is running by the different spacing around the = sign.
    • x from the base class is not available in the derived class, since it is private in MyBase, so the show method in MyDerived must call getX() to obtain the value.

    Derived Class Methods that Override Base Class Methods


    As we saw before, you can create a method in the derived class with the same name as a base class method. Note that:

    • The new method overrides (and hides) the original method.
    • You can still call the base class method from within the derived class if necessary, by adding the super keyword and a dot in front of the method name.
    • The base class version of the method is not available to outside code.
    • You can view the super term as providing a reference to the base class object buried inside the derived class.
    • You cannot do super.super. to back up two levels.
    • You cannot change the return type when overriding a method, since this would make polymorphism impossible.
    • Example: a revised MyDerived using super.show()

    Inheritance and Default Base Class Constructors


    One base class constructor will always run when instantiating a new derived class object.

    • If you do not explicitly call a base class constructor, the no-arguments base constructor will be automatically run, without the need to call it as super().
    • But if you do explicitly call a base class constructor, the no-arguments base constructor will not be automatically run.
    • The no-arguments (or no-args for short) constructor is often called the default constructor, since it is the one that will run by default (and also because you are given it by default if you write no constructors).

    Code Sample:

    Java-Inheritance/Demos/Inheritance2.java

    Each constructor prints a message so that we can follow the flow of execution. Note that using new Violet() causes Purple() to run, and that new Violet(4) also causes Purple() to run.

    For the sake of simplicity, the i field has been made protected, but this is not considered a good practice.

    If your base class has constructors, but no no-arguments constructor, then the derived class must call one of the existing constructors with super(args), since there will be no default constructor in the base class.

    If the base class has a no-arguments constructor that is private, it will be there, but not be available, since private elements are hidden from the derived class. So, again, you must explicitly call an available form of base class constructor, rather than relying on the default.

    Try the above code with the Purple() constructor commented out or marked as private.

    The Instantiation Process at Runtime


    In general, when an object is instantiated, an object is created for each level of the inheritance hierarchy. Each level is completed before the next level is started, and the following takes place at each level:

    1. The memory block for that level is allocated (for derived classes, this means it is sized for the added elements, since the inherited elements were in the base class memory block.
    2. The entire block is zeroed out.
    3. Explicit initializers for that level run, which may involve executable code, for example: private double d = Math.random();
    4. The constructor for that level runs. Note:
      • Since the class code has already been loaded, and any more basic code has been completed, any methods in this class or inherited from superclasses are available to be called from the constructor.
      • Note that if this level's constructor calls a superconstructor, all you are really doing is selecting which form of superconstructor will run at the appropriate time. Timing wise, that superconstructor was run before we got to this point.

    When the process has completed, the expression that created the instance evaluates to the address of the block for the last unit in the chain.

    Inheritance and static Elements

    static methods in a class may not be overridden in a derived class. This is because the static method linkages are not resolved with the same dynamic mechanism that non-static methods use. The linkage is established at compile time.

    Example - Factoring Person Out of Employee


    Since personnel and probably other people in our overall corporate software suite (contact management, perhaps) would have some basic personal attributes in common, we will pull the first and last name fields into a base class representing a person.

    1. Create a new class, Person, in the employees package (that may not be the best place for it, but for convenience we will put it there).
    2. Cut the first and last name fields and the associated get and set methods out of Employee and paste them here (including getFullName).
    3. Create a constructor for Person that sets the first and last names; it would probably b e a good idea to create a default constructor as well.
    4. Declare Employee to extend Person; change the constructor that accepts the first and last name fields to call a super-constructor to accomplish that task.
    5. Note that if getPayInfo() uses firstName and lastname directly, you will need to revise it to call the get methods for those values - why?
    6. We can test the code using a simplified version of Payroll.

    Code Sample:

    Java-Inheritance/Demos/employees/Person.java

    This class includes the name fields and related set and get methods.

    Code Sample:

    Java-Inheritance/Demos/employees/Employee.java

    Since this class now extends Person, the name-related elements are already present, so we remove them from this code. We took advantage of the Person constructor that accepst first and last names in the corresponding Employee constructor.

    Note that since getPayInfo calls getFullName, which is now inherited and publicly accessible, that code did not need to change.

    Code Sample:

    Java-Inheritance/Demos/Payroll.java

    No changes need to be made to Payroll to take advantage of the addition of the inheritance hierarchy that we added. The only changes we made were for the sake of brevity.

    To revisit the sequence of events when instantiating an Employee using the constructor that accepts the first and last names, department, and pay rate:

    1. Memory for an Object is allocated.
    2. Any Object initializers would run.
    3. The Object() constructor would run.
    4. Memory for a Person is allocated.
    5. If there were any Person initializers, they would run.
    6. The Person constructor would run, because that was the version selected by the Employee constructor we called.
    7. Memory for an Employee is allocated.
    8. If there were any Employee initializers, they would run.
    9. Any additional steps in the Employee constructor we called would run.

    Payroll-Inheritance01: Adding Types of Employees


    Duration: 30 to 45 minutes. We wish to improve our payroll system to take account of the three different types of employees we actually have: exempt, nonexempt, and contract employees. Rather than use some sort of identifying code as a property, OOP makes use of inheritance to handle this need, since at runtime a type can be programmatically identified. So we will create three new classes that extend Employee:

    1. ExemptEmployee
    2. NonexemptEmployee
    3. ContractEmployee

    In our company, exempt employees get a monthly salary, nonexempt an hourly rate that is multiplied by their hours, as do contract employees. There won't be any real difference between nonexempt and contract employees within their code. Realistically, in a real application, there would be, but, even if there weren't, it would still be a good idea to have separate classes, since the class type itself becomes a bit of information about the object. In the exception class hierarchy, there are many classes that have no internal differences; The multiple classes serve merely to identify the type of problem that occured.

    We can inherit much of the logic from Employee, such as the pay rate fields and methods, as well as the name-related elements indirectly gained from Person. But, ContractEmployee and NonexemptEmployee will both add logic related to hours, and all three classes will override the getPayInfo method.

    Also, the solution code builds upon the Person base class from the preceding example. You can either copy the Person.java file into your working directory and edit Employee.java to match, or just copy the set of files from the Java-Inheritance/Demos directory into your working directory and use those.

    1. Create three new classes, ExemptEmployee, NonexemptEmployee, and ContractEmployee that extend Employee
      • One possible approach is to copy the Employee.java file into a new file, ExemptEmployee.java, and modify as appropriate.
      • Then copy that into NonexemptEmployee.java and edit.
      • Then copy NonexemptEmployee.java into ContractEmployee.java and make the required changes.
      changes.
    2. Add an hours field for non-exempt and contract employees, along with the associated get and set methods (note that the payRate field will hold a monthly amount for exempt and an hourly amount for nonexempt and contractors).
    3. Revise the getPayInfo method for each new class.
      • For all three, it should identify which type of employee it is.
      • For nonexempt and contract employees, calculate payRate * hours as the numeric value for their pay.
    4. Add constructors as you see fit, making use of calls to the appropriate super-constructors.
    5. There is a special main program already in the Exercises folder, Payroll4Inheritance01.java, that you can use to test your classes.

    Solution:

    Solutions/Payroll-Inheritance01/employees/ExemptEmployee.java

    The primary thing to notice about this file is that it rewrites each constructor with one line to call the equivalent form of super.

    Solution:

    Solutions/Payroll-Inheritance01/employees/NonexemptEmployee.java

    In addition to rewriting the existing constructors, this class adds another that accepts hours, as well as appropriate methods to get and set that value.

    Solution:

    Solutions/Payroll-Inheritance01/employees/ContractEmployee.java

    This class is virtually identical to NonexemptEmployee. Realistically, there would be differences due to benefits, dependents, etc.

    Given the similarity between ContractEmployee and NonexemptEmployee, it might be worth refactoring to have a common base class for hourly employees, especially if there were situations where we would want to work with all hourly employees, regardless of type.

    Solution:

    Exercises/Payroll4Inheritance01.java

    Typecasting with Object References


    Object references can be typecast only along a chain of inheritance. If class MyDerived is derived from MyBase, then a reference to one can be typecast to the other. An upcast converts from a derived type to a base type, and will be done implicitly, because it is guaranteed that everything that could be used in the base is also in the derived class.

    A downcast converts from a parent type to a derived type, and must be done explicitly.

    even though o came from a String, the compiler only recognizes it as an Object, since that is the type of data the variable is declared to hold.

    As a memory aid, if you draw your inheritance diagrams with the parent class on top, then an upcast moves up the page, while a downcast moves down the page.

    More on Object Typecasts

    The compiler will not check your downcasts, other than to confirm that the cast is at least feasible. For instance, there is no possibility of a typecase between String and Integer, since neither is a base class to the other.

    But, the JVM will check at runtime to make sure that the cast will succeed. A downcast could fail at runtime because you might call a method that is not there, so the JVM checks when performing the cast in order to fail as soon as possible, rather than possibly having some additional steps execute between casting and using a method.

    Since t was not actually a String, this would fail with a runtime exception during the cast operation. At that point, the runtime engine sees that it cannot make the conversion and fails.

    You can use a typecast in the flow of an operation, such as:

    ((MyBase) rv) casts rv to a MyDerived, for which the getY() method is run.

    Note the parentheses enclosing the inline typecast operation; this is because the dot operator is higher precedence than the typecast; without them we would be trying to run rv.getY() and typecast the result (technically, Java does not consider the dot an operator, but a separator , like curly braces, parentheses, and square brackets - the net effect is the same, since separators get applied before operators).

    Typecasting, Polymorphism, and Dynamic Method Invocation

    The concept of polymorphism means "one thing - many forms."

    In this case, the one thing is a base class variable; the many forms are the different types derived from that base class that can be stored in the variable.

    Storing a reference in a variable of a base type does not change the contents of the object, just the compiler's identification of its type - it still has its original methods and fields.

    You must explicitly downcast the references back to their original class in order to access their unique properties and methods. If you have upcast, to store a derived class object with a base class reference, the compiler will not recognize the existence of derived class methods that were not in the base class.

    The collection classes, such as Vector, are defined to store Objects, so that anything you store in them loses its identity. You must downcast the reference back to the derived type in order to access those methods. The introduction of generics in Java 1.5 provides a solution to this annoyance (more on this in the Collections lesson).

    During execution, using a base class reference to call to a method that has been overridden in the derived class will result in the derived class version being used. This is called dynamic method invocation.

    The following example prints the same way twice, even though two different types of variable are used to reference the object:

    Code Sample:

    Java-Inheritance/Demos/Inheritance3.java

    Situations where you would often see a base class reference:

    • Parameters to methods that only need to work with base class elements of the incoming object.
    • As fields of a class where the class code will only work with the base class elements of the object.
    • Return values from methods where the actual class returned is not important to the user, and you want to hide the actual class from the user - for example, a java.net.Socket object has a public OutputStream getOutputStream () method that returns an instance of a specialized class that will send data across the network connection that the Socket holds; to use this class you only need to know that it is an OutputStream, since there is no way you could use this class without the Socket it is attached to.

    More on Overriding


    Changing Access Levels on Overridden Methods

    You can change the access level of a method when you override it, but only to make it more accessible.

    • You can't restrict access any more than it was in the base class.
    • So, for example, you could take a method that was protected in the base class and make it public.
    • For example, if a method was public in the base class, the derived class may not override it with a method that has protected, private or package access.

    This avoids a logical inconsistency:

    • Since a base class variable can reference a derived class object, the compiler will allow it to access something that was public in the base class.
    • If the derived class object actually referenced had changed the access level to private, then the element ought to be unavailable.
    • This logic could be applied to any restriction in access level, not just public to private.

    As a more specific example of why this is the case, imagine that ExemptEmployee overrode public String getPayInfo() with private String getPayInfo().

    The compiler would allow

    • Because Employee, the type on the variable e, says that getPayInfo is public.
    • But, now at runtime, it shouldn't be accessible, since it is supposed to be private in ExemptEmployee.

    Redefining Fields

    • A new field is created that hides the existence of the original field.
    • Since it actually a new field being created, the access level and even data type may be whatever you want - they do not have to be the same as the original field.
    • I don't know of any good reason to do this deliberately, but it is possible.
      • A strange thing happens when you use a base class reference to such a class where the field was accessible (for example, public).
      • The base class reference sees the base class version of the field!

    But, if you were to extend a class from the Java API or other library, you wouldn't necessarily know what fields it had - this facility allows you to use whatever field names you want, and, as long as the base class versions were private, you would not get any adverse effects.

    Object Typecasting Example


    Say our game program needed to store references to Entity objects.

  • The exact type of Entity would be unknown at compile time.
  • But during execution we would like to instantiate different types of Entity at random.
  • Perhaps our code for Entity includes a method moveTo() that moves it to a new location. Many of the entities move the same way, but perhaps some can fly, etc. We could write a generally useful form of moveTo in the Entity class, but then override it as necessary in some of the classes derived from Entity.

    Code Sample:

    Java-Inheritance/Demos/EntityTest.java

    The compiler allows the calls to the moveTo method because it is guaranteed to be present in any of the subclasses - since it was created in the base class.

    If not overridden in the derived class, then the base class version will be used.

    If the method is overridden by the derived class, then the derived class version will be used.

    At runtime, the JVM searches for the method implementation, starting at the actual class of the instance, and moving up the inheritance hierarchy until it finds where the method was implemented, so the most derived version will run.

    Checking an Object's Type: Using instanceof


    Given that you can have base class references to several different derived class types, you will eventually come to a situation where you need to determine exactly which derived class is referenced - you may not know it at the time the program is compiled.

    In the above example, perhaps wizards, ogres, trolls, etc. have their own special methods.

    How would you know which method to call if you had an Entity reference that could hold any subclass at any time?

    The instanceof operator is used in comparisons - it gives a boolean answer when used to compare an object reference with a class name.

    It will yield true if the reference points to an instance of that class.

    It will also give true if the object is a derived class of the one tested.

    If the test yields true, then you can safely typecast to call a derived class method (you still need to typecast to call the method - the compiler doesn't care that you performed the test).

    For example:

    There is another method of testing:

    • Every object has a getClass() method that returns a Class object that uniquely identifies each class.
    • Every class has a class pseudo-property that provides the same Class object as above; this object is the class as loaded into the JVM (technically, class isn't a field, but syntax-wise it is treated somewhat like a static field).
    • With this method, a derived class object's class will compare as not equal to the base class.

    It is rare that you would need this type of test.

    Payroll-Inheritance02: Using the Employee Subclasses


    Duration: 45 to 60 minutes.

    1. n the main method of Payroll, reinstate the array of Employee objects.
    2. Create instances of the non-exempt employees, exempt employees, and contract employees to fill the array. You can ask which type of employee using getPromptedChar, then break up the existing sections of code that enter one specific type as in: You will see a slightly different approach in the solution code, which avoids duplicating the code to read the name and department data.
    3. Create a report that lists all employees, grouped by type, by looping through the array three times.
      • The first time, show all exempt employees and their pay information .
      • The second time. print only the non-exempt employees and their pay information.
      • The third time. print contract employees and their pay information.
      • Since you'll be writing the same loop multiple times, you could try both indexed loops and for-each loops (the solution uses for-each loops).

    Solution:

    Solutions/Payroll-Inheritance02/Payroll.java

    We reduced the amount of code by recognizing that some of the data entry logic is common to all three types - asking for first and last names and department before the switch. This required some additional shuffling of declarations, plus some restructuring to avoid asking for the name information all over again if the employee type is not valid (we used continue to avoid processing an employee if the type wasn't valid, and backed up the loop counter to go over the same array location on the next iteration).

    For the report, the same logic is essentially repeated three times:

    The instanceof test enables us to isolate just one type of employee to print; the others will be skipped over.

    Payroll-Inheritance03: Making our base classes abstract


    Duration: 5 to 5 minutes.

    1. Mark the Person and Employee classes as abstract
    2. Make the getPayInfo() method abstract in Employee

    Solution:

    Solutions/Payroll-Inheritance03/employees/Person.java

    Solution:

    Solutions/Payroll-Inheritance03/employees/Employee.java

    package employees; public abstract class Employee extends Person { ---- C O D E O M I T T E D ---- public abstract String getPayInfo(); }

    Methods Inherited from Object


    There are a number of useful methods defined for Object.

    Some are useful as is, such as:

    Class getClass() - returns a Class object (a representation of the class that can be used for comparisons or for retrieving information about the class).

    Others are useful when overridden with code specific to the new class:

    Object clone() - creates a new object that is a copy of the original object. This method must be overridden, otherwise an exception will occur (the Object version of clone throws a CloneNotSupportedException).

    The issue is whether to perform a shallow copy or a deep copy - a shallow copy merely copies the same reference addresses, so that both the original object and the new object point to the same internal objects; a deep copy makes copies of all the internal objects (and then what if the internal objects contained references to objects ...? ).

    boolean equals(Object) - does a comparison between this object and another. If you don't override this method, you get the same result as if you used == (that is, the two references must point to the same object to compare as equal - two different objects with the same field values would compare as unequal) - that is how the method is written in the Object class. You would override this method with whatever you need to perform a comparison.

    int hashCode() - returns an integer value used by collection objects that store elements using a hashtable. Elements that compare as the same using the equals(Object) method should have the same hashcode.

    String toString() - converts this object to a string representation.

    This method is called by a some elements in the Java API when the object is used in a situation that requires a String, for example, when you concatenate the object with an existing String, or send the object to System.out.println().

    Note that the call to toString is not made automatically as a typecast to a String - the only behavior built into the syntax of Java is string concatenation with the + sign (so one of the operands must already be a String); the code in println is explicitly written to call toString.

    If you don't override this method, you will get a strange string including the full class name and the hashcode for the object void finalize() - called by the JVM when the object is garbage-collected. This method might never be called (the program may end without the object being collected).

    There are also a several methods (wait, notify, and notifyAll) related to locking and unlocking an object in multithreaded situations.

    Code Sample:

    Java-Inheritance/Demos/ObjectMethods.java

    The clone method returns Object rather than ObjectMethods, since that is how it was declared in the Object class, and you can't change the return type when overriding - thus the typecast on the returned value.

    Similarly, the parameter to equals is Object, rather than ObjectMethods. This is not required by Java's syntax rules, but rather a convention that enables other classes to work with this class. For example, the Collections API classes use the equals method to determine if an object is already in a set. If we wrote the method as equals(ObjectMethods om) instead of equals(Object o), the collections classes would call equals(Object o) as inherited from Object, which would test for identity using an == test.

    The hashCode method was written out of a sense of duty - Sun specifies that the behavior of hashCode "should be consistent with equals", meaning that if two items compare as equal, then they should have the same hash code - this will be revisited in the section on Collections.

    Other Inheritance-related Keywords


    abstract

      abstract states that the item cannot be realized in the current class, but can be if the class is extended. Note:
    • For a class, it states that the class can't be instantiated (it serves merely as a base for inheritance).
    • For a method, it states that the method is not implemented at this level.
    • The abstract keyword cannot be used in conjunction with final.
    • abstract Classes abstract Classes are used when a class is used as a common point of maintenance for subsequent classes, but either structurally doesn't contain enough to be instantiated, or conceptually doesn't exist as a real physical entity.
    • We will make the Employee class abstract in the next exercise: while the concept of an employee exists, nobody in our payroll system would ever be just an employee , they would be exempt, nonexempt, or contract employees.
    • While you cannot instantiate an object from an abstract class, you can still create a reference variable whose type is that class.
    • abstract Methods The method cannot be used in the current class, but only in a inheriting class that overrides the method with code.
    • The method is not given a body, just a semicolon after the parentheses.
    • If a class has an abstract method, then the class must also be abstract.
    • You can extend a class with an abstract method without overriding the method with a concrete implementation, but then the class must be marked as abstract.
    • final final is used to mark something that cannot be changed. final Classes The class cannot be extended. final Methods The method cannot be overridden when the class is extended. final Properties final Properties marks the field as a constant.
    • A final value can be initialized in a constructor or initializer:
    • or Then, in a constructor: Note: String and the wrapper classes use this in two ways:
    • The class is final, so it cannot be extended.
    • The internal field storing the data is final as well, but set by the constructor (this makes the instance immutable - the contents cannot be changed once set)
    • in some cases, a declaration of final enables the compiler to optimize methods, since it doesn't have to leave any "hooks" in for potential future inheritance.
    • Note that final and abstract cannot be used for the same element, since they have opposite effects.

    12 - JAVA INTERFACES

    nterfaces define a standardized set of commands that a class will obey.

    The commands are a set of methods that a class implements.

    The interface definition states the names of the methods and their return types and argument signatures. There is no executable body for any method that is left to each class that implements the interface.

    Once a class implements an interface, the Java compiler knows that an instance of the class will contain the specified set of methods. Therefore, it will allow you to call those methods for an object referenced by a variable whose type is the interface.

    Implementing an interface enables a class to be "plugged in" to any situation that requires a specific behavior (manifested through the set of methods).
    An analogy: a serial interface on a computer defines a set of pin
    /wire assignments and the control signals that will be used. Note that:

    • The actual devices that can be used may do entirely different tasks: mouse, modem, etc.
    • But they are all controlled through the same digital instruction mechanism; the individual wires are specified to carry specific signals.
    Using an interface rather than inheritance to specify a certain set of methods allows a class to inherit from some other class.

    • In other words, if a class needs two different sets of methods, so it can behave like two different types of things, it could inherit one set from class A, and use an interface B to specify the other.
    • You could then reference one of these objects with either an A reference or a B reference.
    Interfaces can also specify constants that are public, static, and final.

    Creating an Interface Definition


    To create an interface definition:

    • Define it like a Java class, in its own file that matches the interface name.
    • Use the keyword interface instead of class.
    • Declare methods using the same approach as abstract methods.
      • Note the semicolon after each method declaration - and that no executable code is supplied (and no curly braces).
      • The elements will automatically be public and abstract, and cannot have any other state; it is OK to specify those terms, but not necessary (usually public is specified and abstract is not - that makes it easy to copy the list of methods, paste them into a class, and modify them).
    • The access level for the entire interface is usually public.
      • It may be omitted, in which case the interface is only available to other classes in the same package (i.e., in the same directory).
      • Note, for the sake of completeness, there are situations where the interface definition could be protected or private; these involve what are called inner classes.

    Code Sample:

    Java-Interfaces/Demos/Printable.java

    This interface requires only one method. Any class implementing Printable must contain a public void printall() method in order to compile.

    Because the above interface is defined as public, its definition must be in its own file, even though that file will be tiny.

    An interface definition may also define fields that are automatically public static final - these are used as constants.

    Implementing Interfaces


    A class definition may, in addition to whatever else it does, implement one or more interfaces.

    Once a class states that it implements an interface, it must supply all the methods defined for that interface, complete with executable code.

  • Note: it actually does not have to implement all of them, but in that case the class cannot be instantiated - it must be declared as an abstract class that can only be used as a base class (where some derived class would then fully implement the interface).
  • To implement an interface:
  • Add that the class implements the interface to the class declaration.
  • Add the methods specified by the interface to the body of the class. Note that you do need to specify the access terms on methods in a class that implements an interface.
  • It is important to note that a class may implement an interface in addition to whatever else it might do, so it could have additional fields and methods not associated with the interface.

    A class may implement more than one interface - that merely adds to the list of required methods. Use a comma-separated list for the interface names.

    Implementing Interfaces - Example


    The complete example will use three separate files (the third file will be shown shortly):

    Code Sample:

    Java-Interfaces/Demos/Printable.java

    Code Sample:

    Java-Interfaces/Demos/PrintableThings.java

    This file contains two classes with package access. Since the classes are not public, they can both be in the same file, and the file name does not need to match either class name. This is done purely as a convenience; it is not a good programming practice in general, but is sometimes useful if one class is highly coupled (interrelated) with the other, which is not the case here. Both classes implement the Printable interface, but are otherwise not related. Stock has another method not related to Printable.

    Reference Variables and Interfaces


    An interface is like a class where the internal structure and some of the behavior is hidden.

    Interfaces are listed like classes in the API documentation.
    They compile to a .class file, and get loaded by the same process that loads true classes.
    Since a class that implements an interface is a class in all other respects, you can create a reference variable for that class, as usual.
    You can also create a reference variable whose type is the interface name.

    Only the methods defined in the interface are visible through a variable whose type is the interface.
    For a Printable variable containing a Stock instance, the sell method is not visible, since it is not declared in Printable.
    Any constants defined by the interface can be accessed without a prefix from code within the class, since implementing the interface makes them part of this class.
    To access an interface-implementing class with an interface class reference:

    Example:

    • Both Person and Stock implement Printable.
    • Therefore, we can create a reference variable to a Printable, and assign either a Person or a Stock object to it.
    • We can then call the printAll() method from the Printable reference variable,
    • since the compiler knows that method will exist, no matter which type of object is actually stored in the variable.

    or

    or

    Calling an Interface Method

    If you have a variable that is declared as a reference to the interface type, you can use it to call an interface method.

    Note :that you cannot call any of the additional methods that are not defined by the interface.

    Code Sample:

    Java-Interfaces/Demos/PrintableTest.java

    Once pr has been assigned a Printable instance, we can call pr.printAll();

    We cannot directly call the sell() method when pr refers to a Stock, since the compiler would not associate it with a variable whose type was Printable. Note: to compile this, use *.java; since the name of the file containing Stock and Person is PrintableThings.java, the compiler won't be able to find those classes, since it would be looking for Person.java and Stock.java.

    Note: you can test the type of object actually contained in an interface reference, and typecast it back to that type.

    for instance, to use the sell() method for a Stock:

    Interfaces and Inheritance


    If a class implements an interface, then all subclasses of it will also automatically implement the interface.

  • They are guaranteed to have the necessary methods available.
  • It is a good practice to specify that the derived class implements the interface, just for self-documentation of the code (also for purposes of javadoc, if the base class is not in the same group of files).
  • An interface definition can inherit from another interface.
  • The new interface then adds fields and methods to the existing (base) definition.
  • A class that implements the new interface must implement all methods from the base interface as well as all the additional methods from the new interface definition.
  • An interface can actually extend multiple base interfaces, in which case the combination of all the methods will be required for any implementing class.
  • The following interface extends the Printable interface and adds another required method (the new method overloads printAll to print to a specified destination instead of to System.out):

    Code Sample:

    Java-Interfaces/Demos/Printable2.java

    A class implementing Printable2 must define both versions of printAll.

    Code Sample:

    Java-Interfaces/Demos/Printable2Test.java

    Solution:

    Solutions/Payroll-Interfaces01/Payroll.java

    The last several lines of code create an array of invoices, then use the CheckPrinter to print employees and invoices separately. It would also be possible to create an array of Payable objects, and add in the elements from both the employees and invoices arrays, but that seems like an unneccessary complication for this application.

    Exercise: Payroll-Interfaces01


    Duration: 30 to 40 minutes. It turns out that our hypothetical system is to be used for all payments our company makes, not just payroll checks, and things like invoices will be paid through the system as well.

  • Create a finance package, and within it create an interface called Payable.
  • ----it should define the public String getPayInfo() method that our employee classes already implement.
  • Specify that all the employee classes implement Payable.
  • The Solutions/Payroll-Interfaces01 directory contains a package called vendors with a class named Invoice - copy this directory to your working directory.
  • Modify the payroll program by adding an array inv of several invoices (you can just hard-code them).
  • The Solutions/finance folder also contains a file named CheckPrinter.java - copy that into your finance package. The class has a printChecks(Payable[]) method that you can call twice, once for employees and again for invoices.
  • Solution:

    Solutions/Payroll-Interfaces01/finance/Payable.java

    This interface declares the public String getPayInfo() method that our employee classes already implement.

    Solution:

    Solutions/Payroll-Interfaces01/employees/Employee.java

    The class has been marked as implementing Payable. Although it would not be required, we should mark the derived classes the same way, to have more self-documenting code.

    Some Uses for Interfaces


    Interfaces and Event-Handling

    A real-world use of interfaces is for event-handling

    • An object that can generate an event maintains a list of objects that would like to listen for that event (they will be notified when the event occurs by having one of their methods called).
    • The object that generates the event fires it by going through its list of objects that want to handle the event, and calling a specified interface method for each object.
    • A class may handle an event if it implements the interface that is expected for that event - therefore it will have the specified method.
    • You register an object to handle an event by passing a reference to it to the event-generating object's method that adds a handler.
    Assuming that there is an event type called XXXEvent:
    • The handler interface would probably be named XXXListener.
    • The method to register a listener would usually be called addXXXListener.
    • The method generating the event probably has a protected utility method called fireXXXEvent that it uses to trigger the event notifications (and it is available for you to call if you extend the class).

    The ActionListener interface is used for GUI events like button clicks.

    • The event is fired by the GUI object calling the actionPerformed method for any registered listeners (the code to do this is already built into the GUI classes, and the Java API defines the interface shown below).

    A class can listen for events if it implements ActionListener.

    • It can either register itself with the event-generating object, or code outside the class can register it - the example below shows how it would register itself using this:

    For the class that fires the event, registering is done with the addActionListener(ActionListener) method, which receives a reference to an ActionListener object:

    • It adds that reference to a list (maybe a java.util.Vector) of listeners.
    • When the time comes to fire the event, it walks through the list, calling actionPerformed() for each element on the list (and passing a reference to an event object that it creates).

    For the sake of completeness, when the listener interface has multiple methods, there are often abstract classes that implement most or all of the methods as do-nothing methods - so that all you need to do is extend the class and implement the methods that you choose

    Interfaces and "Pluggable Components"

    The TableModel interface

    The Swing classes contain a component called JTable, which displays a spreadsheet-like grid. Note that:

    • It uses a Model-View-Controller approach to separate these sections of logic into individual classes.
    • The TableModel interface defines a set of methods that allow a JTable (the controller) to query a data model to find out information in order to display it.
    • The interface forms a framework for a discussion that will take place between the controller and the model (like, "How many rows do you have?" and, "How many columns?", followed by "What's the value at column 0, row 0?", etc.).

    Below are some of the methods from TableModel:

    public interface TableModel
    int getColumnCount()
    Returns the number of columns in the model.
    int getRowCount()
    Returns the number of rows in the model.
    String getColumnName(int columnIndex)
    Returns the name of the column at columnIndex.
    Class<?> getColumnClass(int columnIndex)
    Returns the most specific superclass for all the cell values in the column.
    Object getValueAt(int rowIndex, int columnIndex)
    Returns the value for the cell at columnIndex and rowIndex.
    boolean isCellEditable(int rowIndex, int columnIndex)
    Returns true if the cell at rowIndex and columnIndex is editable.
    void setValueAt(Object aValue, int rowIndex, int columnIndex)
    Sets the value in the cell at columnIndex and rowIndex to aValue.
    You can see the conversation that will take place between the controller and the model. Note that:

    • The controller will ask the model for the number of rows and columns, and, with that information, ask for the value at each location.
    • It will ask for the type of data with getColumnClass, so it can determine from its settings how to display the values (instances of Number, which Integer, Double, etc., extend, get right-aligned, Boolean columns use a check box, all others get left-aligned - these settings are configurable).
    • It will get a heading for each column with getColumnName.
    • If a cell is double-clicked, it can ask if the cell is editable with isCellEditable.
      • If it is, when the user is done editing, it can put the new data into the model using setValueAt.

    Code Sample:

    Java-Interfaces/Demos/TableModelExample.java

    For convenience, all the classes are in one file.

    The DemoTableModel class implements TableModel by extending AbstractTableModel, thus gaining implementations of several methods (like those relating to model change event listener lists), then adding the remaining methods.

    The model is based on parallel arrays of student data: name, grade, and active or not- each array represents one column of data, and element 0 in each array is the same student.

    The titles array holds column names.

    getColumnCount returns 3, because we know that in advance.

    getRowCount returns the length of one of the data arrays.

    For getColumnName, we return an appropriate string from the titles array.

    For getValueAt, we pick an array based on the column number, and return the element at the row index.

    getColumnClass returns a class object that matches the type of data for each array.

    isCellEditable returns false, and setValueAt does nothing, because our model is not editable.

    We then have three possible views of the data: a Swing GUI view that uses a JTable, a console view that prints column-aligned data, and an HTML view that produces HTML code to the console (you can copy that and paste it into a file to view in a browser, like in tablemodel.html).

    Since the JTable is the whole reason TableModel exists, it knows what to do with the model. The TableConsole and TableHTML view objects have to explicitly call the appropriate methods in order to display the data.

    Marker Interfaces

    It is actually possible to have an interface that requires no methods at all! This creates what is called a marker interface.

    A declaration that a class implements the interface makes it an instance of that interface, so that it can be passed as a parameter to a method expecting an instance of the interface, or as a return value from a method that declares it returns an instance of the interface.

    An example from the API is Serializable

    • An object that implements Serializable may be turned into a serial data stream, perhaps to save in a file or send across a network connection.
    • The writeObject method of ObjectOutputStream accepts a parameter whose type is Object, but throws an exception if it doesn't implement Serializable.
    • The serialization mechanism is recursive, so not only must the object be an instance of Serializable, but any of its object fields must also reference objects that are Serializable (or marked as transient), and any of their fields ... .

    Annotations


    Java 5 added a new syntax element: the annotation. An annotation is a piece of descriptive data (metadata) about a class, field, or method. It is somewhat like a comment, except that individual annotations are predefined, reusable, and can have effects on either the compilation process or the use of the class once compiled. If you have used an IDE like Eclipse or NetBeans, you may have seen the @Override annotation on editor-supplied template code. This particular annotation tells the compiler that the method that immediately follows is meant to override a base class method (or a method required by an interface). If it does not (because perhaps you spelled the name incorrectly, or got the parameter list wrong), then a compiler error is issued.

    Annotations provide Java with a means to achieve, at least to some extent, Aspect-Oriented Programming, or AOP. AOP recognizes cross-cutting concerns, that is, aspects of an element that cut across classes that might not be related by inheritance or implementation of an interface.

    An example is a Java web service. While servlets usually extend a Java EE base class (and will always implement the Servlet interface), there is no specified base class or interface for a web service. Instead, configuration information informs the web server that a specific class is intended to be used as a web service, and the server takes steps to make that happen. Prior to annotations, that information was supplied solely by XML configuration files. With Java EE 5, annotations were provided with which a class could be internally marked as a web service.

    Annotation Details


    • Annotations are defined as a sort of interface, but an @ symbol precedes the interface keyword in the declaration (as in @interface). When used, an @ symbol is prepended to the name.
    • They can be parameterized with optional elements.
      • A parameter element named value is special - if it is the only element, then it does not need to be named when used (a single value passed to the annotation will be assumed to be the value).
      • For annotations accepting only one parameter, that parameter should be named value.
      • An annotation with no parameters serves as a marker, much like implementing the Serializable interface.
    • They are used as modifiers preceding any target code entities that are declared: class, field, method, constructor, method parameters, return values, package, or local variables.
    • Based on their specified retention policy, they can be discarded after compilation (the SOURCE policy), or preserved into the compiled class (CLASS persists, but the JVM isn't required to keep the information after the class is loaded, and RUNTIME annotations do remain with the class in the JVM).
      • @Override is an example of the source type, since it is only needed by the compiler
      • A runtime type that you might encounter the effect of is @Deprecated, which states that an element is deprecated - you will receive a compiler warning if your code uses an element marked with this annotation (and, since you might be accessing the element in an already-compiled class, this annotation must persist into the compiled class file).
      • @SuppressWarnings is another source annotation, with an optional element to specify what types of warnings are to be suppressed.
    • The annotation definitions are themselves annotated: -@Target and @Retention are used before the annotation definition to specify which type of element receives the annotation, and what the retention is.

    Using Annotations


    To apply an annotation to a class or element, precede the item with the name of the annotation, prefixed with the @ symbol.

    If the annotation takes parameters, supply them in parentheses, as a comma separated list of parameterName=parameterValue. If the only parameter is called value, then you can just supply the parameterValue, without specifying it by name.

    Code Sample:

    Java-Interfaces/Demos/AnnotatedWebService.java

    The @WebService annotation persists into compiled code. Tools that work with enterprise-level web servers (like Glassfish, JBoss, etc.), can read the annotation via reflection, and install the class as a web service, performing all the necessary tasks, such as creating a WSDL file, establishing a URL for the service, and installation it under that URL. The annotation can be parameterized with the name for the service (which defaults to the class name followed by "Service"), as well as several other items affecting the setup as a web service.

    • The serviceName parameter to the @WebService annotation tells the server to set up the service under that name, as opposed to the default, which would have been AnnotatedWebServiceService (the default behavior appends "Service" to the class name, which, in this case, would be redundant).
    • The @WebMethod annotations tell the server that these methods should be set up as RPC methods which can be remotely invoked (by default, the methods are exposed, the annotation is actually only needed when renaming the method, or to exclude the method from the service, but common practice is to include the unparameterized annotation for methods to be exposed as is).
    • The @WebParam annotation is used to rename the daysOffset parameter, which would be used from ordinary Java code, to days when the RPC is remotely invoked. Due to the limitations of reflection, where parameter names are not preserved into compiled classes, this annotation is necessary to avoid having the parameters be called arg0, arg1, etc.

    13 - JAVA EXEPTIONS

    xceptions are generated when a recognized condition, usually an error condition, occurs during the execution of a method. There are a number of standard error conditions defined in Java, and you may define your own error conditions as well.

    When an exception is generated, it is said to be thrown.

    Java syntax includes a system for managing exceptions, by tracking the potential for each method to throw specific exceptions. Note that:

    • For each method that could throw an exception, your code must inform the Java compiler that it could throw that specific exception.
    • The compiler marks that method as potentially throwing that exception, and then requires any code calling the method to handle the possible exception.
    • There are two ways to handle an exception:

    • You can try the "risky" code, catch the exception, and do something about it, after which the propagation of the exception ceases.
    • You can mark the method with the risky statement indcating that it throws an exception. Any statement that calls a method capable of throwing an exception must deal with it.
    • So, if you use a method in your code that is marked as throwing a particular exception, the compiler will not allow that code unless you handle the exception Once an exception is thrown, it propagates backward up the chain of methods, from callees to callers, until it is caught. Note that:
    • If the exception occurs in a try block, the JVM looks to the catch block(s) that follow to see if any of them match the exception type.
    • The first one that matches will be executed.
    • If none match, then this method ends, and execution jumps to the method that called this one, at the point where the call was made.
    • If an exception is not caught in your code (which would happen if main was marked as throwing the exception) then the JVM will catch the exception, end that thread of execution, and print a stack trace. There are cases where the compiler does not enforce these rules. Exceptions that fit this category are called unchecked exceptions.

    Handling Exceptions


    Let's say we are writing a method called getThatInt(ResultSet rs) and we want to use the method getInt(int column) from the ResultSet passed in as a parameter:

    A look at the API listing for ResultSet tells us that the getInt() method throws SQLException, so we must handle that in our code

    1.Use try and catch

    2.Declare that the method will throw the exception and let our caller handle it

    Note that although you are required to "handle" the exception, you aren't necessarily required to do anything useful about it!

    Your decision as to which approach to use should be based on where you think responsibility for handling the exception lies. In the example above, the second approach is probably better, so that the code that works more closely with the SQL handles the exception.

    Exception Objects


    When an exception is thrown, an exception object is created and passed to the catch block much like a parameter to a method. Note that:

  • Occurrence of an exception generates an object (an instance of a class in the exception hierarchy) containing information about the exception.
  • The exception object is passed to the code designated to catch the exception, which may then use methods of the exception object to help handle the situation.
  • There is an API class called Exception. Note that:

  • All exception classes inherit from Exception, which inherits from Throwable.
  • Another class, Error, also inherits from Throwable.
  • Your code must handle most exceptions, but generally should not attempt to handle Error subtypes (like OutOfMemoryError or StackOverflowError).
  • RuntimeException is a subclass of Exception that is a base class for all the exception classes that you are not obligated to handle, but still might want to anyway (examples are ArithmeticException, from dividing by zero, NullPointerException, and ArrayIndexOutOfBoundsException).
  • So, there are several classes of exceptions you are not required to handle (shaded in the image below). Note that:

  • These extend either Error or RuntimeException.
  • The ones you are required to handle are called checked exceptions.
  • Generally, runtime exceptions can be prevented by good coding practices:
    • Avoid null pointer exceptions by checking the reference first.
    • Check array indexes before using them to avoid ArrayIndexOutOfBoundsException.
    • Looking at the documentation for allowable parameter values and testing them before passing them to a method will prevent IllegalArgumentException.

    Attempting Risky Code - try and catch


    If a method is going to resolve a potential exception internally, the line of code that could generate the exception is placed inside a try block.

  • There may be other code inside the try block, before and/or after the risky line(s). Any code that depends upon the risky code's success should be in the try block, since it will automatically be skipped if the exception occurs.
  • There is usually at least one catch block immediately after the try block. A catch block must specify what type of exception it will catch.

  • There can be more than one catch block, each one marked for a specific exception class.
  • The exception class that is caught can be any class in the exception hierarchy, either a general (base) class, or a very specific (derived) class.
  • The catch block(s) must handle all checked exceptions that the try block is known to throw unless you want to throw that exception back to the method that called this one.
  • It is possible to have a try block without any catch blocks if you have a finally block, but any checked exceptions still need to be caught, or the method needs to declare that it throws them. We will cover finally later in this section.
  • If an exception occurs within a try block, execution jumps to the first catch block whose exception class matches the exception that occurred (using an instanceof test). Any steps remaining in the try block are skipped. If no exception occurs, then the catch blocks are skipped. The catch blocks will also be skipped if an exception that is not caught occurs, such as a RuntimeException, or an exception that the method declared it throws.

    You cannot catch an exception that would not occur in the try block, but you can mark a method as throwing an exception that it doesn't (this leaves open the possibility that an extending class can override the method and actually throw the exception).

    Notes on try ... catch Blocks and Variable Scope/Initialization

    If you declare a variable within a try block, it will not exist outside the try block, since the curly braces define the scope of the variable. You will often need that variable later, if nowhere else other than the catch or finally blocks, so you would need to declare the variable before the try.

    If you declare but don't initialize a variable before a try block, and the only place you set a value for that variable is in the try block, then it is possible when execution leaves the try ... catch structure that the variable never received a value.
  • So, you would get a "possibly uninitialized value" error message from the compiler, since it actually keeps track of that sort of thing.
  • Usually this happens with object references; you would generally initialize them to null.
  • Code Sample:

    Java-Exceptions/Demos/ExceptionTest.java

    The program will print the first result, then fail while performing the division for the second equation. Execution will jump to the catch block to print our message on the screen.

    Note: ArithmeticException is one of the few you are not required to catch, but you can still catch it if you wish.

    Example - An Exception You Must Handle

    The preceding example used a RuntimeException which your code is not obligated to handle.

    Most methods in the I/O classes throw IOException which is an exception you must handle.

    Our KeyboardReader class has try and catch to handle this, essentially stifling the exception, since it is unlikely, if not impossible, to actually get an IOException from the keyboard.

    Code Sample:

    Java-Exceptions/Demos/IOExceptionTest.java

    The line marked to comment out throws IOException, but is not in a try block, so the compiler rejects it. The second read attempt is within a try block, as it should be.

    • Ttry to compile this code as is and then comment out the indicated line.
    • There is no way we can force an IOException from the keyboard to test the catch block.

    Using Multiple catch Blocks

    It is possible that a statement might throw more than one kind of exception. You can list a sequence of catch blocks, one for each possible exception. Remember that there is an object hierarchy for exceptions. Since the first one that matches is used and the others skipped, you can put a derived class first and its base class later (you will actually get a compiler error if you list a more basic class before a derived class, as it is "unreachable code").

    Code Sample:

    Java-Exceptions/Demos/MultiCatchTest.java

    The code in the try block could throw NumberFormatException during the parsing, and ArithmeticException while doing the division, so we have catch blocks for those specific cases. The more generic catch block for Exception would catch other problems, like NullPointerException.

    Guaranteeing Execution of Code - The finally Block


    To guarantee that a line of code runs, whether an exception occurs or not, use a finally block after the try ... catch blocks.

    The code in the finally block will almost always execute.

    In summary, note the following:

    • A try block is followed by zero or more catch blocks.
      • If the catch block exception classes caught are related, the blocks must be listed in inheritance order from most derived to most basic.
    • There may one finally block as the last block in the structure.
    • There must be at least one block from the combined set of catch and finally after the try.

    It's possible to have a try block followed by a finally block, with no catch block. This is used to prevent an unchecked exception, or an exception the method declared it throws, from exiting the method before cleanup code can be executed.

    Code Sample:

    Java-Exceptions/Demos/FinallyTest.java

    import util.KeyboardReader; public class FinallyTest { public static void main(String[] args) { System.out.println("Returned value is " + go()); } public static int go() { int choice = 0; try { String name = KeyboardReader.getPromptedString("Enter your name: "); System.out.println("MENU:"); System.out.println("1 - normal execution"); System.out.println("2 - uncaught ArithmeticException"); System.out.println("3 - return from try block"); System.out.println("4 - call System.exit"); System.out.println( "5 - return 5 from finally after ArithmeticException"); System.out.println( "6 - return 6 from finally after try returns -1"); System.out.println("X - catch NumberFormatException"); choice = KeyboardReader.getPromptedInt("Enter your choice: "); if (choice == 1) System.out.println("Hello " + name); else if (choice == 2) System.out.println("1 / 0 = " + 1/0); else if (choice == 3) return 3; else if (choice == 4) System.exit(1); else if (choice == 5) System.out.println("1 / 0 = " + 1/0); else if (choice == 6) return -1; } catch (NumberFormatException e) { System.out.println("Number Format Exception occurred"); } finally { System.out.println("Goodbye from finally block"); if (choice == 5) return 5; if (choice == 6) return 6; } return 0; } }

    The program shows a menu of possible execution paths you can trigger. The "Goodbye from finally block " message will always appear except from an explicit call to System.exit in the try block:

    • When no exception occurs, the finally block will execute after the try.
    • If an uncaught exceptions occurs, like when we divide by zero, the finally block will execute before we are thrown out of the method.
    • If we execute a return from the try block, the finally block still executes before we leave.
    • Catching a NumberFormatException is still followed by executing the finally block.
    • But, calling System.exit in the try block causes the JVM to shut down without executing the finally block.
    • When we force an uncaught exception but return from the finally block, we do not get a stack trace, indicating that the ArithmeticException just disappeared (compare choices 2 and 5).
    • When both the try block and the finally block execute a return statement, the value from the finally block is the one actually returned.

    Letting an Exception be Thrown to the Method Caller


    A method that generates an exception can be written to not catch it. Instead it can let it be thrown back to the method that called it.

    The possibility that a method may throw an exception must be defined with the method.

    Then an instance of ExceptionClassName or a class that extends it may be thrown so, stating that a method throws Exception is about as generic as you can get (stating that it throws Throwableis as generic as you can get, but not recommended). A method can throw more than one type of exception; in which case you would use a comma-separated list of exception types.

    In this way, the method is now marked as throwing that type of exception, and a code that calls this method will be obligated to handle it.

    When you extend a class and override a method, you cannot add exceptions to the throws list, but a base class method can list exceptions that it does not throw in the expectation that an overriding method will throw the exception. This is another example of the "inheritance cannot restrict access" principle we saw earlier.

    If main() throws an exception, the JVM, which runs under Java rules, will handle the exception (by printing a stack trace and closing down the offending thread. In a single-threaded program, this will shut down the JVM).

    Throwing an Exception


    The keyword throw is used to trigger the exception-handling process (or, "raise" the exception, as it is often termed in other languages).

    That word is followed by an instance of a throwable object, i.e., an instance of a class that extends Throwable. Usually, a new instance of an appropriate exception class is created to contain information about the exception.

    For example, suppose a setAge() method expects a nonnegative integer; we can have it throw an IllegalArgumentException if it receives a negative value. It makes sense for the method that calls setAge() to do something about the problem, since it is where the illegal number came from.

    So, we can declare setAge() as throws IllegalArgumentException.

    Payroll-Exceptions01: Handling NumberFormatException in Payroll


    Duration: 5 to 10 minutes. Our program to this point has been prone to potential bad numeric inputs when reading from the keyboard. The parsing methods all throw NumberFormatException.
    We could now put each line that requests a number inside a small loop.

    The loop could be controlled by a boolean variable, perhaps with a name like isInvalid and initially set to true (using the reverse approach is also a possible strategy).

    • Inside the loop, we try the read and parse operations.
    • Then, still in the try block, change the state of the boolean to one that will end the loop (because we wouldn't get to that step unless we succeeded).
    • In the catch block, print an error message and request to try again.

    Where would you put this code? In the payroll main method or in the KeyboardReader class?

    Solution:

    As a general principle, tools shouldn't attempt to handle exceptions when the handling logic would vary depending on the code using the tool. But, it would be a tremendous burden to put each step of a program that requests a numeric input in a looped try/catch block.

    Instead, we could recognize that a common approach would be to loop until the input is numeric, printing an error message each time.

    We could overload the get methods in KeyboardReader to accept an error message string, so it could do the looping for us. This way a reasonable solution would be provided, but the original method would still be available if the programmer wants to customize the exception handling.

    If a programmer wants a different approach, they are still free to write it in their code and use the original KeyboardReader methods .

    Payroll-Exceptions01, continued


      Duration: 15 to 20 minutes.
    1. Go ahead and add a second version of each get numeric method in KeyboardReader that accepts an error message string as a second parameter; have it loop on each numeric input request until it succeeds without throwing the exception (and printing the error message each time the exception occurs).
    2. Then modify Payroll to call these methods.

    Challenge

    This approach still doesn't solve the problem of limited employee types, valid department numbers, etc. Can you think of an approach that would? (Hint: interfaces are a powerful tool ...).

    Solution:

    Solutions/Payroll-Exceptions01/util/KeyboardReader.java

    Solution:

    Solutions/Payroll-Exceptions01/Payroll.java

    The revised code uses the new overloads of the getPromptedXXX methods.

    Challenge Solution:

    Solutions/Payroll-Exceptions01-challenge/util/IntValidator.java

    This interface specifies a method that will be used to validate integers. A validator for a specific field (like department) would implement this with code to test for legal values for that field. The package contains similar interfaces for floats and doubles.

    Challenge Solution:

    Solutions/Payroll-Exceptions01-challenge/employees/DeptValidator.java

    This class validates department numbers to be from 1 - 5 inclusive. We also could create separate validators for pay rates, etc.

    Challenge Solution:

    Solutions/Payroll-Exceptions01-challenge/util/KeyboardReader.java

    Exceptions and Inheritance


    If a base class method throws an exception, that behavior will also occur in any derived classes that do not override the method.

    An overriding method may throw the same exception(s) that the base class method threw.
    An overriding method cannot add new exceptions to the throws list. Similar to placing more strict access on the method, this would restrict the derived class object in ways that a base class reference would be unaware of.

    If the derived class method does not throw the exception that the base class threw, it can either:

    Retain the exception in the throws list, even though it does not throw it; this would enable subclasses to throw the exception.
    Remove the exception from its throws list, thus blocking subsequent extensions from throwing that exception.
    If you have a base class method that does not throw an exception, but you expect that subclasses might, you can declare the base class to throw that exception.

    Exception Class Constructors and Methods

    There are several forms of constructors defined in the base class for the exception hierarchy.

    Constructor Description
    Throwable() Constructs a new throwable with null as its detail message.
    Throwable(String message) Constructs a new throwable with the specified detail message.
    Throwable(String message, Throwable cause) Constructs a new throwable with the specified detail message and cause.
    Throwable(Throwable cause) Constructs a new throwable with the specified cause and a detail message of (cause==null ? null : cause.toString()) (which typically contains the class and detail message of cause).

    The forms involving a cause are used in situations like Servlets and Java Server Pages, where a specific exception is thrown by the JSP engine, but it may be rooted in an exception from your code.

    In both cases, a method in a base class is overridden by your code since the writers of the base class did not know what specific exceptions your code might throw, and didn't want to specify something too broad like throws Exception, they settled on throws IOException, ServletException (or JSPException for Java Server Pages).
    You would try and catch for your expected exceptions and repackage them inside ServletException objects if you did not want to handle them

    Method Description
    getMessage() Prints the message that was associated with the exception (many of the exceptions that deal with outside resources pass on the message from the outside) - for example, when you connect to a database and run a query, that could generate an error in the database; getMessage() will show that message.
    printStackTrace() Prints to the standard error stream the trace of what function called what function, etc., leading up to the exception. There are variations of this method where you may specify a destination for the printing (note that stack trace includes the message).
    printStackTrace(PrintStream stream) Same as above, but prints to the specified output stream (which could be hooked to a log file, for example).

    Also worth noting is that the Java Logging API has logging methods that will accept a Throwable parameter and make a log entry with the stack trace.

    Creating and Using Your Own Exception Classes


    You can create your own exception class by extending an existing exception class.

    You could then add any fields or methods that you wish, although often that is not necessary.

    You must, however, override any constructors you wish to use: Exception(), Exception(String message), Exception(String message, Throwable cause), Exception(Throwable cause). Usually you can just call the corresponding super-constructor.

    If you extend RuntimeException or one of its subclasses, your exception will be treated as a runtime exception (it will not be checked).

    When a situation arises for which you would want to throw the exception, use the throw keyword with a new object from your exception class, for example:

    Code Sample:

    Java-Exceptions/Demos/NewExceptionTest.java

    The thrower method randomly throws a NewException, by creating and throwing a new instance of NewException.

    main tries to call thrower, and catches the NewException when it occurs.

    Payroll-Exceptions02


    Duration: 20 to 30 minutes.
    Our payroll program can now handle things like a bad numeric input for pay rate (valid format, but not sensible, like a negative number) in a more comprehensive manner. We already are checking the numeric inputs from the keyboard, but there is no guarantee that later code will remember to do this. Using an exception mechanism guarantees protection from invalid values.

    In the util package, create an exception class for InvalidValueException. Note that the Java API already contains a class for this purpose, IllegalArgumentException, but it is a RuntimeException - we would like ours to be a checked exception.
    In Employee (and potentially its subclasses), change the constructors that accept pay rate and the setPayRate methods to now throw that exception (a question to ask yourself - is it necessary to actually test the pay rate value anywhere other than in the Employee class setPayRate method?). You will see that the effect of throwing the exception ripples through a lot of code. For any code that calls those constructors/methods, choose an appropriate approach to dealing with the potential exception.
    The solution uses the validators from the previous challenge exercise, it will work without that feature, but feel free to add that logic into your code as well.

    Solution:

    Solutions/Payroll-Exceptions02/util/InvalidValueException.java

    Solution:

    Solutions/Payroll-Exceptions02/employees/Employee.java

    The marking of setPayRate throws InvalidValueException ripples through the constructors, so they should be marked as well.

    Solution:

    Solutions/Payroll-Exceptions02/employees/ExemptEmployee.java

    Calling super-constructors that throw our exception requires that these constructors also be marked. The other classes, not shown, should be similarly marked.

    Solution:

    Solutions/Payroll-Exceptions02/Payroll.java

    Since we are already checking the values of the pay rate and hours, we shouldn't expect to see any exceptions thrown, so it is reasonable to put the entire block that gets the employee data and creates an employee in a try block. If we decrement the counter upon a failure, then that employee's data will be requested again.

    You might want to test your logic by temporarily changing one of the test conditions you use when reading input (like hours > 0 to hours > -20), so that you can the result (keep count of how many employees you are asked to enter).

    Rethrowing Exceptions


    An exception may be rethrown.

    When we throw an exception, it does not necessarily have to be a new object. We can reuse an existing one.

    This allows us to partially process the exception and then pass it up to the method that called this one to complete processing. This is often used in servlets and JSPs to handle part of the problem (possibly just log it), but then pass the problem up to the servlet or JSP container to abort and send an error page.

    The stack trace will still have the original information. The fillInStackTrace method for the exception object will replace the original information with information detailing the line on which fillInStackTrace was called as the origin of the exception.

    Initializer Blocks


    Class properties that are object types can be initialized with a newly constructed object.

    The MegaString class constructor code will run whenever a MyClass object is instantiated.

    But what if the object's constructor throws an exception?

    The MyClass code won't compile - you cannot put a property declaration into a try ... catch structure and there is no place to state that the property declaration throws an exception.

    You can use an initializer block to handle this situation.

    This is not absolutely necessary, since the initialization could be done in a constructor, where a try ... catch would be legal. But then it would need to be done in every constructor, which someone adding another constructor later might forget.

    Initializers are run in the order in which they appear in the code, whether standalone initializers, or initializers in a field declaration so, in the above code:

    The Random object gets created for the first field.
    The MegaString gets the first generated random number.
    x gets the second generated random number.

    Static Initializer Blocks

    If a field is static, and is populated with a newly constructed object, that object's constructor code will run when the class loads. In our example, if we make the MegaString property static, its constructor will run when the class loads.

    Again, this won't compile, but now there is no way even to defer the issue to the constructors, since the element is static.

    You can use a static initializer block to handle this problem.

    Again, the initializers are run in the order in which they appear in the code, when the class is loaded.

    Assertions


    Java 1.4 added the concept of assertions, code lines that test that a presumed state actually exists

    -If the state is not as presumed, then an AssertionError will be thrown.
    -Assertions are not intended for testing values that could be expected; they are intended to be used when it is believed that a state exists, but we are not absolutely sure we have covered all the possible avenues that affect the state.

    To use an assertion in code:

    The optional messageExpression will be converted to a String and passed as the message to the AssertionError constructor, so it cannot be a call to a function declared as void.

    For example, perhaps we are using a third-party function that is specified to return a double value between 0 and 1, but we'd like to guarantee that is the case.

    Code Sample:

    Java-Exceptions/Demos/AssertionTest.java

    If the function returns a value outside of our expected range, like 5.0, the assertion condition will evaluate to false, so an AssertionError will be thrown with the message "thirdPartyFunction value 5.0 out of range."

    Note: in a 1.4 compiler, you must inform the compiler that you are compiling your code under Java 1.4 rules to use assertions, using the -source 1.4 command line switch:

    In Java 5 and later this is not necessary.

    Assertions are used for debugging a program, and usually not enabled for production runs. You must specifically enable assertions when you run the program, by using the command line switch -enableassertions (or -ea).

    java -enableassertions ClassName java -ea ClassName

    Oracle's "rules" for assertions emphasize that they will be disabled most of the time:

    -They should not be used for checking the values passed into public methods, since that check will disappear if assertions are not enabled.
    -The assertion code shouldn't have any side effects required for normal operation.

    14 - JAVA COLLECTIONS

    The Java Collections API is a set of classes and interfaces designed to store multiple objects.

    There are a variety of classes that store objects in different ways:

    • Lists store objects in a specific order.
    • Sets reject duplicates of any objects already in the collection.
    • Maps store objects in association with a key, which is later used to look up and retrieve the object (note that if an item with a duplicate key is put into a map, the new item will replace the old item).

    The basic distinctions are defined in several interfaces in the java.util package:

      Collection is the most basic generally useful interface that most, but not all, collection classes implement.
      • It specifies a number of useful methods, such as those to add and remove elements, ascertain the size of the collection, determine if a specific object is contained in the collection, or return an Iterator that can be used to loop through all elements of the collection (more on this later).
      • Methods include: add(Object o), remove(Object o), contains(Object o), iterator().
      • Note that removing an element removes an object that compares as equal to a specified object, rather than by position.
      • Collection extends the Iterable interface, which only requires one method, which supplies an object used to iterate through the collection.
    • The List interface adds the ability to insert and delete at a specified index within the collection, or retrieve from a specific position.
    • The Set interface expects that implementing classes will modify the add methods to prevent duplicates, and also that any constructors will prevent duplicates (the add method returns a boolean that states whether the operation succeeded or not; i.e., if the object could be added because it was not already there).
      • Sets do not support any indexed retrieval.
    • The Map interface does not extend Collection, because its adding, removing, and retrieving methods use a key value to identify an element.
      • Methods include: get(Object key), put(Object key, Object value), remove(Object key), containsKey(Object key), containsValue(Object value), keySet(), entrySet().
      • Maps do not support any indexed retrieval.

      In addition to the List, Set, and Map categories, there are also several inferences you can make from some of the collection class names:

    • A name beginning with Hash uses a hashing and mapping strategy internally, although the key values usually have no meaning (the hashing approach attempts to provide an efficient and approximately equal lookup time for any element).
    • A name beginning with Linked uses a linking strategy to preserve the order of insertion and is optimized for insertion/deletion as opposed to appending or iterating.
    • A name beginning with Tree uses a binary tree to impose an ordering scheme, either the natural order of the elements (as specified by the Comparable interface implemented by many classes including String and the numeric wrapper classes) or an order dictated by a special helper class object (a Comparator).
    • Several additional interfaces are used to define useful helper classes:

    • Enumeration provides a pair of methods that enable you to loop through a collection in a standardized manner, regardless of the type of collection (you test if there are more elements, and, if so, retrieve the next element).
      • This interface is less frequently used now that the following interface has been added to the API.
      • But, many of the elements in J2EE (servlets in particular) predate the Iterator concept and were specified to use enumerations, so they will still appear in new code.
    • Iterator is an improved version that allows an object to be removed from the collection through the iterator.

    The following diagrams show some of the classes and interfaces that are available:

    Using the Collection Classes


    The following are several examples of collection classes:

    Vector stores objects in a linear list, in order of addition. Some additional notes on Vector are:

    • You can insert and delete objects at any location.
    • All methods are synchronized, so that the class is thread-safe.
    • Vector predates the collections framework, but was marked to implement List when the collections API was developed
  • As a result, there are many duplicate methods, like add and addElement, since the names chosen for Collection methods didn't all match existing method names in Vector.
  • Vector was used extensively in the past, and therefore you will see it in a lot of code, but most recent code uses ArrayList instead.
  • ArrayList, like Vector, stores objects in a linear list, in order of addition. Methods are not synchronized, so that the class is not inherently thread-safe (but there are now tools in the Collections API to provide a thread-safe wrapper for any collection, which is why Vector has fallen into disuse).

    TreeSet stores objects in a linear sequence, sorted by a comparison, with no duplicates. TreeSet also:

  • Stores Comparable items or uses a separate Comparator object to determine ordering.
  • Uses a balanced tree approach to manage the ordering and retrieval.
  • Note that there is no tree list collection, because the concepts of insertion order and natural order are incompatible. Since sets reject duplicates, any comparison algorithm should include a guaranteed tiebreaker (for example, to store employees in last name, first name order: to allow for two Joe Smiths, we should include the employee id as the final level of comparison).

    TreeMap stores objects in a Map, where any subcollection or iterator obtained will be sorted by the key values. Note that:

  • Keys must be Comparable items or have a separate Comparator object.
  • For maps, an iterator is not directly available. You must get either the key set or entry set, from which an iterator is available.
  • Hashtable stores objects in a Map. Note also that:

  • All methods are synchronized, so that the class is thread-safe.
  • Hashtable predates the collections framework, but was marked to implement Map when the collections API was developed.
  • Like Vector, Hashtablehas some duplicate methods.
  • Hashtable extends an obsolete class called Dictionary.
  • HashSet uses hashing strategy to manage a Set. Note also that:

  • HashSet rejects duplicate entries.
  • Entries are managed by an internal HashMap that uses the entry hashCode values as the keys.
  • Methods are not synchronized.
  • Using the Iterator Interface


    Iterators provide a standard way to loop through all items in a collection, regardless of the type of collection. Note that:

      All collection classes implement an iterator() method that returns the object's iterator (declared as Iterator iterator()). This method is specified by the Iterable interface, which is the base interface for Collection. For maps, the collection itself is not Iterable, but the set of keys and the set of entries are. You can use a for-each loop for any Iterable object.

  • Without an iterator, you could still use an indexed loop to walk through a list using the size() method to find the upper limit, and the get(int index) method to retrieve an item, but other types of collections may not have the concept of an index, so an iterator is a better choice.
  • There are two key methods supplied by an iterator:
    1. boolean hasNext(), which returns true until there are no more elements.
    2. Object next(), which retrieves the next element and also moves the iterator's internal pointer to it.

    Some collections allow you to remove an element through the iterator. The remove method is marked in the docs as optional by the definition of interfaces it has to be present, but the optional status indicates that it may be implemented to merely throw an UnsupportedOperationException.

    In any case, if the collection is modified from a route other than via the iterator (perhaps by using remove(int index), or even just using the add method), a ConcurrentModificationException is thrown.

    The Enumeration class is an older approach to this concept; it has methods hasMoreElements() and nextElement().

    Code Sample:

    Java-Collections/Demos/CollectionsTest.java

    This program demonstrates the three types of collections. As is commonly done, the variables are typed as the most basic interfaces (List, Set, and Map).

    We attempt to add the same sequence of values to each: 1, 4, 3, 2, and 3; then:

  • They are deliberately out of sequence and contain a duplicate.
  • For the Map, the numbers are the keys, and single-letter strings are used for the associated values.
  • In the output, first note the true and false values resulting from attempting to add the values to the Set. Also note in the Map listing, which value associated with the key 3 is retained.

    An iterator is then obtained for each and the series printed out (for the Map, we try two different approaches: iterating through the keys and retrieving the associated entries, and iterating directly through the set of entries).

    Note the order of the values for each, and also which of the duplicates was kept or not. Note also that:

    • Tthe List object stores all the objects and iterates through them in order of addition.
    • The Map object stores by key; since a TreeMap is used, its iterator returns the elements sorted in order by the keys.
    • Since one key is duplicated, the later of the two values stored under that key is kept.
    • The Set object rejects the duplicate, so the first item entered is kept (although in this case it would be hard to tell from the iterator listing alone which one was actually stored).

    Creating Collectible Classes


    hashCode and equals

    Both the equals(Object) method and hashCode() methods are used by methods in the Collections API. Note also that:

    • The Map classes use them to determine if a key is already present.
    • The Set classes use them to determine if an object is already in the set.
    • All collections classes use them in contains and related methods.

    Oracle specifies that the behavior of hashCode should be "consistent with equals", meaning that two objects that compare as equal should return the same hash code. The reverse is not required; two objects with the same hash code might be unequal, since hash codes provide "bins" for storing objects.

    This is critical when writing collectible classes. For example, the implementation of HashSet, which should reject duplicate entries, compares a candidate entry's hashcode against that of each object currently in the collection. It will only call equals if it finds a matching hash code. If no hash code matches, it assumes that the candidate object must not match any already present in the set.

    Comparable and Comparator

      Sorted collections can sort elements in two ways:

    1. By the natural order of the elements - objects that implement the Comparable interface have a natural order.
    2. By using a third-party class that implements Comparator.
    3. Comparable specifies one method: compareTo(Object o) returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

      Comparator specifies two methods:
    4. compare(Object a, Object b) returns a negative integer, zero, or a positive integer if a is less than, equal to, or greater than b.
    5. equals(Object o), as in Object, is used not to compare the stored values for value, but to determine if two comparator classes can be considered equal. However, note that the behavior of the compare method should be consistent with equals, as Oracle's documentation advises; that is, compare(a, b) should return 0 when a.equals(b) returns true

    As an example: TreeSet uses a tree structure to store items. Tthe tree part of the name is just for identifying the algorithm used for storage; you cannot make use of any of the node-related behaviors from the outside. There are several forms of constructors, most notably:

    • TreeSet() uses the natural order of the items, so they must implement the Comparable interface (and the items should be mutually comparable, to avoid casting exceptions being thrown during a comparison).
    • TreeSet(Comparator c) - uses the specified Comparator to compare the items for ordering (and, again, the mutually comparable caveat applies).

    Code Sample:

    Java-Collections/Demos/UseComparable.java

    Since String implements Comparable, the names will appear in alphabetical order when we iterate through the set.

    The Arrays class provides useful methods for working with arrays, some of which will return a collection backed by the array (the Collections classes contain useful methods for working with collections, some of which perform the reverse operation).

    Creating a Comparable Class

    Classes that implement the Comparable interface may be stored in ordered collections. They must have a int compareTo(Object other) method to implement the interface. Note the following:

    • It is said that these objects have a natural order as determined by this method.
    • The function returns a negative value for this object considered less than the object passed as parameter other, a positive value for this object considered greater than the object passed as parameter other, and 0 if they are equal.
    • Since this capability is built into the object, it is important that it the results of the compareTo method match with the results of the equals and hashCode methods.

    Creating and Using a Comparator Class

    Classes that implement the Comparator interface may be also used with ordered collections, but the collection must be constructed with an explicit reference to an instance of the Comparator. The Comparator is a separate class that will compare two instances of your class to determine the ordering.

    The interface specifies int compare(Object a, Object b). The function returns a negative value for an object considered less than the object b, a positive value for b considered greater than a, and 0 if they are equal.

    It is still important that the results of the compareTo method match with the results of the objects' equals method. Note that you should usually implement this method to avoid "ties" for objects that would not be considered equal. For example, for two different employees who coincidentally have the same name would be returned in an indeterminate order.

    Code Sample:

    Java-Collections/Demos/UseComparator.java

    The compare method of our comparator makes use of the existing compareTo method in String and simply inverts the result. Note that the objects being compared are tested to make sure both are String objects. If the test fails, the method throws a ClassCastException.

    Code Sample:

    Java-Collections/Demos/UseComparableAndComparator.java

    Since all the collections store are references, it will not use a lot of memory to store the same references in different collections. This creates an analog to a set of table indexes in a database

    Collections in Java 5.0: Generics


    Java 5.0 added the concept of Generics, which allow data types to be parameterized for a class

    In earlier versions of Java, the collection methods to store objects all received a parameter whose type was Object. Therefore, the methods to retrieve elements were typed to return Object. To use a retrieved element, you had to typecast the returned object back to whatever it actually was (and somehow you had to know what it actually was).

    The collections in Java 5.0 use a special, new syntax where the type of object is stated in angle brackets after the collection class name.

    Instead of ArrayList, there is now ArrayList<E>, where the E can be replaced by any type. Within the class, method parameters and return values can be parameterized with the same type.

    For example, an ArrayList of String objects would be ArrayList<String>.

    Code Sample:

    Java-Collections/Demos/GenericCollectionsTest.java

    As you can see, the objects retrieved from the ArrayList are already typed as being String objects. Note the following:

    • We need to have them as String objects in order to call toUpperCase, whereas our previous examples only printed the objects, so being typed as Object was okay.
    • Without generics, we must typecast each retrieved element in order to call toUpperCase.
    • To use an iterator, we would declare the variable to use the same type of element as the collection we draw from, as in Iterator<String>.

    Bounded Types


    A type parameter may set bounds on the type used, by setting an upper limit (in inheritance diagram terms) on the class used. The extends keyword is used to mean that the class must either be an instance of the specified boundary class, or extend it, or, if it is an interface, implement it:

    In the first case, the class may be parameterized with Employee, or any class that extends Employee. In the second, the class may be parameterized with Payable or any type that implements the Payable interface.

    Extending Generic Classes and Implementing Generic Interfaces


    When extending a generic class or implementing a generic interface, you can maintain the generic type, as in public class ArrayList<T> implements List<T>. In this case, types are still stated in terms of T.

    You can lock in the generic type: public class EmployeeList extends ArrayList<Employee> or public class StringList implements java.util.List<String>. In these cases, methods would use the fixed type. For example, if you overrode add(E) in ArrayList<E> in the above EmployeeList, it would be add(Employee).

    Generic Methods


    Methods may be generic, whether or not they are in a generic class. The syntax is somewhat ugly, since it requires listing the type variable before the return type and requires that at least one parameter to the method be of the generic type (that is how the compiler knows what the type is).

    The above method is parameterized with type T. The type for T is established by whatever type of array is passed in; if we pass in a String array, then T is String. The method will then randomly pick one to return.

    The type may be bounded with extends.

    Variations on Generics - Wildcards


    In the documentation for a collections class, you may see some strange type parameters for methods or constructors, such as:

    he question mark is a wildcard, indicating that the actual type is unknown. But, we at least know limits in the second two cases. The extends keyword in this usage actually means "is, extends, or implements" (which is the same criteria the instanceof operator applies). The super keyword means essentially the opposite: that the type parameter of the other class is, or is more basic than, this class's type. The usages with extends and super are called bounded wildcards.

    This syntax only occurs when the variable is itself a generic class. The wildcards then state how that class's generic type relates to this class's type.

    Why this is necessary leads down a long and winding path. To start, consider the following:

    This seems reasonable at first glance, but then consider if this line followed:

    <textarea>exEmps.add(new ContractEmployee());</textarea>

    Perfectly legal as far as the compiler is concerned, since ContractEmploye fits within the Employee type that the exEmps variable requires, but now we have a contract employee in a list instance that is supposed to hold only exempt employees. So, an instance of a class parameterized with a derived class is not an instance of that class parameterized with the base class, even though individual instances of the derived class can be used in the base-parameterized generic class; e.g., our List<Employee> can add individual exempt employees.

    For the first wildcard case above, public boolean containsAll(Collection<?> c), it does no harm for us to see if our collection contains all the elements of some other collection that may contain an entirely unrelated type (but few, if any, of the items would compare as equal). Note that the contains method accepts an Object parameter, not an E, for this same reason.

    The extends term in public boolean addAll(Collection<? extends E> c)means that the unknown class is, extends, or implements the listed type. For instance, we could add all the elements of an ArrayList<ExemptEmployee> to an ArrayList<Employee>. That makes sense, since we could add individual exempt employees to a basic employee collection. But, since we don't actually know what the parameterized type of the incoming collection is (it is the ? class), we cannot call any methods on that object that depend on its parameterized type. So we can't add to that collection; we can only read from it.

    The super term is seen less often; it means that the parameterized type of the incoming collection must be of the same type or a more basic type. The TreeSet constructor can accept a Comparator for its actual type, or any type more basic (e.g., a Comparator<Object> can be used for a TreeSet of anything, since its compare method will accept any type of data). It is, however, likely that many "acceptable" comparators will end up throwing a ClassCastException at runtime if they can't actually compare the types involved. So, for example, if we had a Comparator<Employee> class that compared employee ids, we might still wish to use it in a TreeSet<ExemptEmployee>, where it would be perfectly valid (in fact, it would be an annoyance to have to write a special comparator for every employee type, if all the comparators did was compare the ids).

    Payroll Using Generics


    Duration: 15 to 25 minutes.
    We can modify our payroll application to use generic lists instead of arrays for our employees, invoices, and payables.

    1. Make the Employee[] variable a List<Employee>, and populate it with a new ArrayList<Employee>.</Employee>
    2. Since lists have no fixed size, you will need to change the first for loop, perhaps to a fixed number of iterations.</Employee>
    3. Modify the lines that add employees from using array indices to using the add method.</Employee>
    4. Turn the Invoice[] into a List<Invoice> populated with a Vector<Invoice>, similar to what we did in we did in step 1.</Invoice>
    5. Modify the lines that populate that list.</Invoice>
    6. Create an ArrayList<Payable> in a List<Payable> payables variable.</Payable>
    7. Create an ArrayList<Payable> in a List<Payable> payments variable.</Payable>
    8. Then call that list's addAll method once and pass in the employee list.</Payable>
    9. Then add all the invoices the same way.</Payable>
    10. Since we might not want to modify CheckPrinter, you can generate a Payable array for it with:</Payable>

    The parameter is a "dummy" array used to tell the generic method what type of array to create. Note in the Collection documentation that this method is typed with T rather than the E used in the rest of the class. This method has its own local type, which is determined by the type of the array passed in.

    Solution:

    Solutions/Payroll-Collections01/Payroll.java

    Notice that we didn't have to change the for-each loops; they work equally well for Iterable objects, like lists, as they do for arrays.

    Also, the addAll method accepts any Collection, so it can take an ArrayList or a Vector equally well. And, since it accepts Collection<? extends E>, it can take collections of either Employee or Invoice (both implement the Payable type used for E in the the receiving collection).

    15 - JAVA INNER CLASSES

    Inner Classes, aka Nested Classes


    Inner classes, also known as nested classes are classes defined within another class.

    They may be defined as public, protected, private, or with package access.

    They may only be used "in the context" of the containingclass (outer class, or enclosing class), unless they are marked as static.

    • The outer class can freely instantiate inner class objects within its code; they are automatically associated with the outer class instance that created them.
    • Code in some other class can instantiate an inner class object associated with a specific instance of the outer class if the inner class definition is public (and its containing class is public as well).
    • If the inner class is static, then it can be instantiated without an outer class instance, otherwise, the inner class object must be attached to an instance of the outer class.
    • Inner classes are used to (these uses overlap to some extent):
    • Create a type of object that is only needed within one class, usually for some short-term purpose.
    • Create a utility type of object that cannot be used elsewhere (which would allow the programmer to change it without fear of repercussions in other classes).
    • Create one-of-a-kind interface implementations (such as individualized event handlers).
    • Allow a sort of multiple inheritance, since the inner class may extend a different class than the outer class extends, and an inner class instance would have access to its private elements as well as the private elements of the outer class object it is attached to
    • Implement one-to-many relationships where the classes are tightly coupled (meaning that code for one or both of the classes needs access to many of the private elements of the other class) - the outer class would be the "one" side of the relationship, with the inner class being the "many" side.
    • Provide a specialized form of callback, with which a class may pass very limited access to some of its internal components. Note that:
      • The collections classes provide an iterator, a class that implements the Iterator interface to loop through the elements in the collection using hasNext and next methods.
      • Given that the internal structure of the collection may be complex, implementing the iterator as an inner class enables it to navigate the structure, while not exposing any other aspects of the collection to the outside world.

    Inner class code has free access to all elements of the outer class object that contains it, by name (no matter what the access level of the elements is). Outer class code has free access to all elements in any of its inner classes, no matter what their access term.

    An inner class compiles to its own class file, separate from that of the outer class (the name of the file will be OuterClassName$InnerClassName.class, although within your code the name of the class will be OuterClassName.InnerClassName); you cannot use the dollar sign version of the name in your code.

    An inner class occupies its own memory block, separate from the outer class memory block.

    An inner class may extend one class, which might be unrelated to the class the outer class extends.

    An inner class can implement one of more interfaces, and, if treated as an instance of one of its interfaces, external code may have no knowledge that the object actually comes from an inner class.

    Inner Class Syntax


    The definition of the inner class is always available for the outer class to use. Note that:

    • No inner class objects are automatically instantiated with an outer class object.
    • Outer class code may instantiate any number of inner class objects - none, one, or many.

    Code Sample:

    Java-InnerClasses/Demos/MyOuter.java

    This is a simple example of an inner class

    • MyOuter has one property, x; the inner class MyInner has one property, y.
    • The MyOuter constructor accepts two parameters; the first is used to populate x.
    • It creates one MyInner object, whose y property is populated with the second parameter.
    • Note that the inner class has free access to the private outer class x element.
    • The outer class has free access to the private inner class privateDisplay() method.

    The connection between the two classes is handled automatically.

    The following diagram maps out the memory used by the example.

    Instantiating an Inner Class Instance from within the Enclosing Class


    An inner class instance may be directly instantiated from code in the enclosing class, without any special syntax:

    Such an instance is automatically associated with the enclosing class instance that instantiated it.

    Code Sample:

    Java-InnerClasses/Demos/Inner1.java

    This code simply creates an instance of the outer class, MyOuter.

    The MyOuter constructor creates an instance of MyInner as mentioned earlier.

    Inner Classes Referenced from Outside the Enclosing Class


    If the access term for the inner class definition is public (or the element is accessible at package access or protected level to the other class), then other classes can hold references to one or more of these inner class objects

    • If the inner class is static, then it can exist without an outer class object, otherwise any inner class object must belong to an outer class instance.

    For code that is not in the outer class, a reference to a static or non-static inner class object must use the outer class name, a dot, then the inner class name:

    If the inner class has an accessible constructor, you can you instantiate one from outside of the enclosing class, although the syntax is ugly, and there is rarely a need for this capability.

    Referencing the Outer Class Instance from the Inner Class Code


    If inner class code needs a reference to the outer class instance that it is attached to, use the name of the outer class, a dot, and this. Remember that if there is no name conflict, there is no need for any special syntax.
    For code in MyInner to obtain a reference to its MyOuter:

    static Inner Classes

    An inner class may be marked as static.

    A static inner class my be instantiated without an instance of the outer class. Note that:

    • static members of the outer class are visible to the inner class, no matter what their access level.
    • Non-static members of the outer class are not available, since there is not instance of the outer class to retrieve them from.

    To create a static inner class object from outside the enclosing class, you must still reference the outer class name

    An inner class may not have static members unless the inner class is itself marked as static.

    Code Sample:

    Java-InnerClasses/Demos/StaticInnerTest.java

    We have a class StaticOuter that declares a static inner class StaticInner. StaticOuter has a method that will create instances of StaticInner. But, StaticInner also has a public constructor. Note that:

    • We can directly instantiate a StaticOuter.StaticInner object without an outer class instance.
    • Code for a StaticOuter can create a StaticInner, but the inner class object has no attachment to the outer class object that created it.
    • Note the commented out line; you cannot create a static inner class instance attached to an instance of its enclosing class.

    Better Practices for Working with Inner Classes


    It is easiest if inner class objects can always be instantiated from the enclosing class object. You can create a factory method to accomplish this.

    Code Sample:

    Java-InnerClasses/Demos/FactoryInnerOuter.java

    For convenience, this file contains both the main class and the FactoryOuter class (with package access). Note that:

  • An instance of FactoryOuter contains a three element array of FactoryInner objects.
  • The addInner method instantiates a FactoryInner object and adds it to the array (note that is still automatically associated with the FactoryOuter instance by the JVM, but we need our own mechanism for keeping track of the inner class instances we create).
    • A better approach would be to use one of the collections classes instead of an array, to avoid running out of room in the array

    This is exactly the sort of thing that happens when you obtain an iterator from a collection class. In order to successfully navigate what is most likely a complex internal structure, the object will need access to the private elements. So, an inner class is used, but all you need to know about the object is that it implements the Iterator interface.

    Code Sample:

    Java-InnerClasses/Demos/PayrollInnerClass/employees/Employee.java

    Payment is an inner class to a simplified Employee, and, as an inner class, has free access to all private elements of Employee. Unlike a standalone payment class, this class can retrieve the employee name from the outer class instance. We also use this access to defer updating the year-to-date amounts until the payment is posted, via the process method.

    To get this degree of interaction between two separate classes would be difficult, since it would mean that either:

    1. The ability to update ytdPay would have to be publicly available.
    2. Employee and Payment would have to be in the same package, with updating ytdPay achieved by using package access.

    Note that we have also separated the concepts of creating a payment from actually posting it. This gives us better control over transactions - note that a payment cannot be processed twice.

    Code Sample:

    Java-InnerClasses/Demos/PayrollInnerClass/Payroll.java

    We have only one employee for simplicity. As we loop for each month, a payment is created for each. We try to process the June payment twice (remember that the array is zero-based, so January is month 0; this matches the behavior of the java.util.Date class) . The second attempt to process the payment should throw an exception which our catch block handles.

    We retrieve and print the year-to-date pay each time we process a payment.

    At the end, we have the Employee object print the entire payment history created by our calls to the inner class' process method..

    Code Sample:

    Java-InnerClasses/Demos/PayrollInnerClassInterface/employees/Employee.java

    This code goes one step further to create a Payment inner class that implements the Payable interface.

    Code Sample:

    Java-InnerClasses/Demos/PayrollInnerClassInterface/Payroll.java

    The only difference here is that we declare the variable holding the payments as Payable, hiding the fact that it is an inner class.

    Enums


    In Java 5, the enum element was introduced. Long sought by the C/C++ part of the Java community, enums provide a set of predefined constants for indicating a small set of mutually exclusive values or states.

    Why Another Syntax Element for a Set of Constants?

    The other approaches all have some sort of flaw, particularly as involves type-safety.

    • Interfaces defining only constants were commonly used, and several are grandfathered into the API, like SwingConstants. But, there is a minor problem that if you implement an interface in order to gain the constants, you then have additional public elements in that class that you wouldn't really want to provide to the outside world. public class MyFrame extends JFrame implements SwingConstants { . . . } MyFrame frame = new MyFrame(); // frame.HORIZONTAL is now publicly available
    • Using plain old integers seems straightforward enough, but, if you perhaps have a method that requires one of that set of values to be passed in, the parameter would be typed as int. A caller could supply any int value, including ones you wouldn't expect.

    Java enums provide a type-safe way of creating a set of constants, since they are defined as a class, and therefore are a type of data.

    A disadvantage to this approach is that the set of values is written into the code. For sets of values that may change, this would require recompiling the code, and would invalidate any serialized instances of the enum class. For example, if we offered a choice of benefits plans to our employees, the set of available plans would not be a good candidate for an enum, since it is likely that the set of available plans would eventually change.

    Defining an enum Class

    To create a simple enum class:

    1. Declare like an ordinary class, except using the keyword enum instead of class.
    2. Within the curly braces, supply a comma-separated list of names, ending in a semicolon.

    One instance of the enum class will be created to represent each item you listed, available as a static field of the class, using the name you supplied which will be the individual values. Each instance can provide an integral value, with sequential indexes starting at 0, in the order that the names were defined - there is no way to change this, but there is a route to get specific values which have a complex internal state.

    There will be three instances of the class created, Alignment.left, Alignment.right, and Alignment.center. An Alignment type variable can hold any of these three values.

    Enums automatically extend the Enum class from the API, and they inherit several useful methods:

    • Each object has a name method that returns the name of that instance (as does the toString method).
    • The ordinal method returns that enum object's position in the set, the integer index mentioned above.
    • There are also several other methods that will be present, although they are not listed in the documentation for Enum.

    • A public static EnumName[] values() method that returns an array containing all the values, in order (so that the array index would match the ordinal value for that object). This method is not inherited, but is built specifically for each enum class.
    • A public EnumName valueOf(String name) method that returns the instance whose name matches the specified name (this is not the uglier method you will see in the documentation, but another built specifically for each instance - the one listed in the documentation is actually used internally by the simpler form).

    The reason for the last two methods not being in the documentation has to do with generics and type erasure - the methods cannot be declared in the Enum base class in a way that would allow the use of the as-yet unknown subclass.

    Individual values from the set may be accessed as static elements of the enum class. The JVM will instantiate exactly one instance of each value from the set. Therefore, they can be used in comparisons with ==, or in switch statements (using the equals method is preferred to ==, since it will serve as a reminder that you are dealing with true objects, not integers).

    Although enums may be top-level classes, they are often created as inner classes, as in the following example, where the concept of the enum is an integral part of a new BookWithEnum class. When used as an inner class, they are automatically static, so that an instance of an inner enum does not have access to instance elements of the enclosing class.

    Code Sample:

    Java-InnerClasses/Demos/BookWithEnum.java

    The Category enum is defined as an inner class to BookWithEnum. The full names of the complete set of values are: BookWithEnum.Category.required, BookWithEnum.Category.supplemental, BookWithEnum.Category.optional, and BookWithEnum.Category.unknown. From within the BookWithEnum class, they may be accessed as: Category.required, Category.supplemental, Category.optional, and Category.unknown.

    We set the category for a book constructed without one as Category.unknown, and provide methods to get the value, and to set it with either an enum object or from a string.

    Note that enums may be used in switch statements - for the cases you use only the short name for the value.

    More Complex Enums

    Enums are more than just a set of integer constants. They are actually a set of unique object instances, and, as objects, can have multiple fields. So, an enum is a class with a fixed number of possible instances, each with it's own unique state, and each of the possible instances is created automatically and stored as static field under the same name. (In design pattern terms, an enum is a Flyweight - a class where only a limited number of fixed states exist.)

    To create a more complex enum class:

    1. Declare as before.
    2. Declare any additional fields and accessor methods as with a regular class. While you can actually write mutator methods to create what is called a mutable enum, this practice is strongly discouraged.
    3. Write one constructor.
    4. Within the curly braces, again supply a comma-separated list of names, which will be the individual values, but this time with a parameter list. The enum values will be constructed with the data you provide.

    50-game