Up till now you have studied programs that follows a simple flow from the first instruction to the end. Most programs does not just do one thing and then terminate, like the programs we have written so far. Sometimes a program needs to do something repeatedly, sometimes make a decision to do this or that, or maybe nothing.
Now we will look at how we can alter the way instructions are executed in different ways:
- Conditionally
- Repeatedly
The most common program flow instructin is 'if', often followed by 'else'. Syntax is:
if (condion) code-block
[else code-block]
Oops, there is a new convention here, actually two:
- Things written between '[' and ']' are optional. They may or not may be present.
- A code-block is a simple line of program code, or multiple lines of code between curly brackets. You'll understand from the samples below.
if(<condition>) <code> [else <code>] | The next instruction, or block of code, will be executed if the condition is true, else the second code is executed, if present. |
while(<condition>) <code> | The next instruction, or block of code, will be executed repetedly as long as the condition is true. |
do <code> while(<condition>) | Same as 'while', but the code will always be executed at least once since the code is before the 'while(<condition>)' part. |
for(<initializer>;<condition>;<incrementor>) <code> | The condition is normally dependent on the initializer and the incrementor. The code will be repeated while condition is true. The incrementor will be performed after each iteration. |
foreach(<type> <object item>;<list of objects>) <code> | The next instruction, or block of code will be executed for each objec item in the list of objects. |
case(<expression> case <value>: <code> [break]; [case <value>: <code> [break;]]... [default: <code> [break;]]) | Depending on <expression> one of the case <value>: will be executed util a break; is found. This looks a bit more compicated than it is, but you will understand when we have an example. |
Well, I have out-done myself. That really was a piece of mumble-jumble. So, if this course is for newbee programmers, why do this to you? Well, I am taking this opportunity to show you what you migth find in various documentations. In my humble opinion this kind of documentation would be better read by a machine, not by a human. But still, it is very precise. And if you think this is hard, take a look at some SQL documentation. Scary, to say the least.
In my opinion, samples are the best way to help understanding. Unfortunatelly, when, at rare occations, samples are given, they are often over-compicated, describing a lot more than needed, thus it's hard to really filter out the needed parts.
But let's take the if statment for a starter. The word if and the parantheses are mandatory, so is the condition within. The else, however is not mandatory. You use the else part if you have need for it. Then there are the question about 'next instruction or block of code'. If the if() is followed by a line of code, then only that code is affected by the condition. If you need more than one line of code to be affected, use a code block. A code block is written within curly brackets, '{' and '}'.
And, finally, a sample:
if (<condition>)
{
<code line>
[<code line>]...
}
{
<code line>
[<code line>]...
}
Well, I did it again. Still some mumble-jumble in there. You should know what a code line is from previous samples, and that [<code line>]... means that it may be many code lines. But I have still not explained what <condition> is. This is exactly the way documentations will irritate you (and me). Now you'll have to look-up what <condition> is, and insert it into the sample. I even use to cut-and-paste nested definitions into a text editor (did you install Notpad++?). Anyway, now I will give you a syntax of the <condition>:
<expression> <comparision> <expression>
And again! What then is <expression>? What is <comparision>? Well, <expression> is something that has a value. It could be a constant, like 5 or "Hello world!" or Console.Readline(). Anything that results in a value. And <comparision> can be one of:
== | The <condition> is true if the <expression> to the left of '==' is the same as the <expression> to the rigth of the '==', else it is false. |
!= | The <condition> is true if the <expression> to the left of '!=' is not the same as the <expression> to the rigth of the '!=', else it is false. |
> | The <condition> is true if the <expression> to the left of '>' is greater than the <expression> to the rigth of the '>', else it is false. |
>= | The <condition> is true if the <expression> to the left of '>=' is greater or equal than the <expression> to the rigth of the '>', else it is false. |
< | The <condition> is true if the <expression> to the left of '<' is less than the <expression> to the rigth of the '<', else it is false. |
<= | The <condition> is true if the <expression> to the left of '<=' is less or equal than the <expression> to the rigth of the '<=', else it is false. |
! | The <condition> is true if the <expression> is not true, else the <condition> is false. |
Had I been attending a woodoo class I woud have graduated right now. All that mumble-jumble could really wake the dead. Or at least kill your interest of reading documentation. However, this is what you can expect of documentations, and I want you to get used to reading them. However, now I am trying to get you to understand this mumble-jumble. Therefore I will finally give you an understandable example. But an example must in that case be explained. Let us say that you have the need to add 5 to a number if it is less than 7. The number is stored in some variable, let's include the declaration in code:
Int32 myInteger;
... (some code in between that will set some value to myInteger)
if (myInteger < 7)
{
myInteger += 5;
}
... (some code in between that will set some value to myInteger)
if (myInteger < 7)
{
myInteger += 5;
}
Wow! Finally an understandable example! Still, there was one new element here, the '+=' business. It means 'add 5 to the variable to the left'. Let's do one more. If we are not done, add 5 to myInteger, else set done to true:
Int32 myInteger;
Boolean done = false;
... (some code in between that will set some value to myInteger)
if (!done)
{
myInteger += 5;
}
else
{
done = true;
}
Boolean done = false;
... (some code in between that will set some value to myInteger)
if (!done)
{
myInteger += 5;
}
else
{
done = true;
}
Above we looked a comparison operators. Those were '==', '!=', '>' etcetera. We have previously seen the '=' when assigning a value to a variable. Fact is that there are a few more assignmet operators:
= | The assignment operator. The value to the right of the operator is assigned to the variable to the left of the operator. |
+= | The add and re-assign operator. The value to the rigth of the operator is added to the variable to the left of the operator. |
-= | The subtract and re-assign operator. The value to the rigth of the operator is subtracted the variable to the left of the operator. |
*= | The multiply and re-assign operator. The value to the rigth of the operator is multiplied by the variable to the left of the operator. |
/= | Well, you got in now, right? |
%= | Same for the modulus operator, only problem is that I have not explained the modulus operator yet. |
?: | This is the ugly one. It's trinary, which means that it has 3 'sides'. Syntax is: <result> = <condition>?<result if condition is true>:<result if condition is false>. |
I really beleive I owe you some samples now. Lets start easy. I need a program that shows the square of all numbers from 1 to 10. I can use a 'for' clause for that. Like this:
for (Int32 i = 1; i <= 10; i++)
{
Console.WriteLine((i * i).ToString());
}
{
Console.WriteLine((i * i).ToString());
}
I can solve this task using 'while' or 'do - while' as well. Like this:
Int32 i = 1;
while (i <= 10)
{
Console.WriteLine((i * i).ToString());
i++;
}
while (i <= 10)
{
Console.WriteLine((i * i).ToString());
i++;
}
Int32 i = 1;
do
{
Console.WriteLine((i * i).ToString());
i++;
}while (i <= 10);
do
{
Console.WriteLine((i * i).ToString());
i++;
}while (i <= 10);
As you can see, the for-loop is more compact. You use what you feel is best for the moment.
Well, that was rather easy. Let me introduce you to three new instructions:
goto | This I regard foul language in C/C++/C# and most other languages. You'll understand when I have introduced you to JSP below. |
break | Not best practice, but can be useful in the rigth context. Breaks current context and jumps to next. |
continue | Same as break, but jumps to the beginning of current context. |
By context I mean the code-block the instruction is found in. Maybe better take a look at an example. Let us first nestle two loops in order to make a nice multiplication table from 1*1 to 10*10:
for (Int32 row = 1; row <= 10; row++)
{
for (Int32 col = 1; col <= 10; col++)
{
Console.Write((row * col).ToString() + '\t');
}
Console.WriteLine("");
}
{
for (Int32 col = 1; col <= 10; col++)
{
Console.Write((row * col).ToString() + '\t');
}
Console.WriteLine("");
}
Oops, new mumble-jumble. The '\t' is a special character, the tab character. I put it there to get a tabular result:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
As you can see, we have a fine table, but maybe we did not want to see all doublets. Maybe this is what we want (I also added column and row headers):
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 *
1 = 1
2 = 2 4
3 = 3 6 9
4 = 4 8 12 16
5 = 5 10 15 20 25
6 = 6 12 18 24 30 36
7 = 7 14 21 28 35 42 49
8 = 8 16 24 32 40 48 56 64
9 = 9 18 27 36 45 54 63 72 81
10 = 10 20 30 40 50 60 70 80 90 100
1 = 1
2 = 2 4
3 = 3 6 9
4 = 4 8 12 16
5 = 5 10 15 20 25
6 = 6 12 18 24 30 36
7 = 7 14 21 28 35 42 49
8 = 8 16 24 32 40 48 56 64
9 = 9 18 27 36 45 54 63 72 81
10 = 10 20 30 40 50 60 70 80 90 100
It is easy to add the extra row and left column, but how to remove the extra values and give it this triangular look? One way is to break out of the inner loop when the column just printed has the same, or a greater, value than the row number. Here's the code with all in it:
//Adding coumn headers:
Console.Write('\t');
for (Int32 col = 1; col <= 10; col++)
{
Console.Write(col.ToString() + " *" + '\t');
}
Console.WriteLine("");
// Main multiplication'body'
for (Int32 row = 1; row <= 10; row++)
{
// Print row header:
Console.Write(row.ToString() + " =\t");
// Now row content:
for (Int32 col = 1; col <= 10; col++)
{
// The result in current column and row:
Console.Write((row * col).ToString() + '\t');
// Break inner loop if col is at least same as row:
if (col >= row)
{
break;
}
}
Console.WriteLine("");
}
Console.Write('\t');
for (Int32 col = 1; col <= 10; col++)
{
Console.Write(col.ToString() + " *" + '\t');
}
Console.WriteLine("");
// Main multiplication'body'
for (Int32 row = 1; row <= 10; row++)
{
// Print row header:
Console.Write(row.ToString() + " =\t");
// Now row content:
for (Int32 col = 1; col <= 10; col++)
{
// The result in current column and row:
Console.Write((row * col).ToString() + '\t');
// Break inner loop if col is at least same as row:
if (col >= row)
{
break;
}
}
Console.WriteLine("");
}
Another way would be to make the condition in the inner loop a bit more complex in order to make it dependent on the value in the outer loop. You could combile two conditions with && or ||. Those mean 'and' and 'or' respectively.
<condition> && <condition> | The result is true if both conditions are fulfilled. |
<condition> || <condition> | The condition is true if at least one of the conditions is fulfilled. |
col <= 10 && col < row | The condition is true if col is less than or equal to 10 and if col is less than row |
As an extra exercise, rewrite the sample above using the condition in the last row of the table below. Don't forget to remove the break first and verify that the triangular look disappears. Otherwise you would not know if it is your new code or the break instruction that causes the triangular look.
Then take an extra look at your new code and see if you really need to use both condition in this case.
Jackson's Structured Programming
I'm now inclined to introduce you to an old-school programming model called 'Jackson's structured programming', or JSP for short (not to confuse with 'Java Server Pages'). (I really don't like abbreviations, and this is just one example why.)Jackson wanted to put structure into our code, and to get rid of some bad habits. That is why we should not use 'goto', for example. He saw how code complexity grew with the use of program flags, program jumps (goto) and other things that programmers used (some still use) as shortcuts to solve some specifics in their code. He replaced in essence all current programmers way of thinking with three types of blocks:
Sequence | Blocks of this type in a row are executed in sequence, from left to right. | |
Repeate | Blocks of this type are executed repeatedly depending on some condition. | |
Condition | One block of this type in a row is singled out for execution depending on some condition. |
Most programs can be very roughly described as 'In my program, first set up some things, then do all the main work, and at last do some clean-up and shut down'. That would look like this in JSP, using only sequence blocks:
This describes the main flow of a program (called 'MyProgram'): First do some initialization (a one-time initialization), then do all the program is supposed to do, and at last do any cleanup (if needed) and, of course, close the program. You can see there are two new symbols, labels, 'MyProgram' and 'A', as well as some lines that binds it all together.
The 'Do all stuff' part is a bit generalized. Normally that is where most of the code is. Rather than putting in the label 'A' we could have put a second line of blocks describing in more details what 'Do all stuff' is all about. Probably still a rough description, but still more detailed. If your paper, or Word document, Paint image or whatever, becomes too big, you can use a label, and on another sheet put the same label at the top, instead of the 'MyProgram' label. Then it would be obvious that this new paper, document or whatever, is describing the details of the center block of the picture above.
In the chapter 'Variables' we had an example where the user was asked to enter two numbers. Then the numbers was multiplied and the result was printed on the screen. As an ending, the user was instructed to press any key to terminate the program. Let us take a look at that program again:
static void Main(string[] args)
{
Int32 a;
Int32 b;
Console.Write("Enter first value: ");
a = Int32.Parse(Console.ReadLine());
Console.Write("Enter second value: ");
b = Int32.Parse(Console.ReadLine());
Console.WriteLine(a.ToString() + " * " + b.ToString() + " = " + (a * b).ToString());
Console.WriteLine("Press any key to terminate program...");
Console.ReadKey();
}
{
Int32 a;
Int32 b;
Console.Write("Enter first value: ");
a = Int32.Parse(Console.ReadLine());
Console.Write("Enter second value: ");
b = Int32.Parse(Console.ReadLine());
Console.WriteLine(a.ToString() + " * " + b.ToString() + " = " + (a * b).ToString());
Console.WriteLine("Press any key to terminate program...");
Console.ReadKey();
}
In the beginning of the program two variables was declared. That could be thought of as the initiation part of the program, because they could be re-used had we for example looped the middle part of the program in order to ask for more numbers to multiply, they would have been re-used rather than declared again.
The middle part, the one that could have been looped, consists of the asking and excepting values, and of printing the result. That is our 'Do all stuff' part.
Finally we instruct the user to press any key to terminate the program. That would correspond to the last, rightmost, block.
Let us change the program by adding a do-while loop. If the result is zero, that is if one or both of the numbers entered is zero, the program terminates. It could look something like this:
static void Main(string[] args)
{
Int32 a;
Int32 b;
do
{
Console.Write("Enter first value: ");
a = Int32.Parse(Console.ReadLine());
Console.Write("Enter second value: ");
b = Int32.Parse(Console.ReadLine());
Console.WriteLine(a.ToString() + " * " + b.ToString() + " = "+ (a * b).ToString());
} while (a * b != 0);
Console.WriteLine("Press any key to terminate program...");
Console.ReadKey();
}
{
Int32 a;
Int32 b;
do
{
Console.Write("Enter first value: ");
a = Int32.Parse(Console.ReadLine());
Console.Write("Enter second value: ");
b = Int32.Parse(Console.ReadLine());
Console.WriteLine(a.ToString() + " * " + b.ToString() + " = "+ (a * b).ToString());
} while (a * b != 0);
Console.WriteLine("Press any key to terminate program...");
Console.ReadKey();
}
Now we have a loop in the middle block. Jackson did not allow us to mix Sequences, Conditions and Repeats on the same line. I think it is possible to do, but with some caution. However, let's put a new, Repeat, block under the middle one. I don't need the label 'A' because the diagram is not yet too big. Here's our new diagram:
The star indicates that the block is repeated, and the short text above describes the condition of repeating. The comment within the block gives a short description of what is to be done in the block. Note that it does not describe how to write your code, only what is to be done. Had it been more like the code, it would limit the use of the diagram to console programs. As it is now, it can be used to describe a Windows forms program with two input fields and a result field, or a similar web-based application or even an Android or iPhone application.
As you might have noticed, each row of block has more details of the execution than the row above. The further down in the diagram we go, the more detailed we get. If we strictly follow the principle of not mixing types of blocks on a row, we could concider the following diagram:
This diagram describes some program with these specifics:
- On the first line, a sequence, we recognize initalization, the main processing block (this time I put in some condition), and the cleanup and close.
- On the next line, a condition line, we se in more detail what the center block of the previous line represents. Here we say that if the condition is not fulfilled, we do only the left branch, else only the right one.
- The third line, a sequence, has nothing in the left branch, it was something straight-forward to process in a repeating block, thus cannot be done on this line. However, the right branch had some specific needs demanding for some initialization before looping, and some fixup after the looping. The middle block doesn't do anything, it is just a placeholder for the looping part.
- On the bottom line we have a repeat in both branchas. That's just in this case. Had it been different types of block, well then we had had to put in more lines. However, the condition might have demands for differences in how looping is done, or what is to be looped, thus there are two loop blocks.
As you might realize, this is just some example. If we really had been picky about following Jacksons rule to the letter, we should have put in a block in the left branch on the third line, containing nothing, a 'dummy' block. He prefered that for clarity. Me myself would actually go the other way, and draw the block like this:
I think it is all up to you to select your style, unless you have some demands on you to do documentation the precise JSP way. I only use this as a means of sorting out my thoughts when doing some new logics. It helps me to get it right.
If you like, you could as an exercise make a JSP diagram of one of the multiplication table samples above. Use MS Paint, or some other prefered program, or just draw on a piexe of paper.
Lists
When looking at the multiplication tables above, and also thinking about the loops that only print values on screen, one could start thinking 'what if I want to store the valuse for later use'? Declaring one variable for each value is not very efficient. A better practice would be if we could use some kind of list of variables instead.Rest assure there are. The compiler writers thought about this long ago, and today we have a lot of different ways to store list of values and even objects. The eldest one and the most simple one is the list[] operator. Let us list a few examples using some lists:
Int32[] myInts = {4, 87, 2, 23, 7 }; | A list of five integers with the values assigned. |
Int32[] numbers = new Int32[5]; | A list of five integers that does not yet have any values. |
List<String> mytranslations=new List<String> | An expandable list of Strings. We will use this one more later. |
IEnumerable<type> myEnumerable = ... | An enumeration of some datatype assigned from some code that e.g. returns rows from a database. |
Why the keyword 'new' above? Well, that is a keyword that tells the compiler to create some variable of a more complex type than common intrinsic (built-in) variable. All old standard variables like int, bool and string has each a fixed size in memory. Well, the string is actually more a position in memory where the string starts, but that would still be a memory address, which is 32 or 64 bits on most computers today. But when something complex is to be created, the compiler might need to not only reserve space for the object, but also do some operations on it. We will learn more about that under classes later.
We will concentrate on the first two, or actually the second one, for now. The other examples just show that there are many other kind of lists, and we will encounter some of them later in this and other of my courses.
Assume we need to store some numbers that the user types from the keyboard. Say that we need 10 numbers. Then we could store them in a list like:
Int32[] number = new Int32[10];
Then we could populate the list in a for-loop something like this:
for(Int32 i = 0; i < 10; i++)
{
number[i] = Int32.Parse(System.Console.ReadLine());
}
Note that the value in i varies from 0 to 9 inclusive, not from 1 to 10. When using lists in any flavor of C, and many other languages, the first element is always element number 0, while the last element is always the one less than the length of the list. Why make it that complicated? Well it comes rather natural when we think about how the machine-code will work. The first element is stored in a position chosen by the compiler and the linker, and the rest of the elements follows in a sequence. The index, in this case the variable i, is used as an offset from the first element. The offset for the first element then must be zero, right?
Exercises
Here we will do three exercises. The third one builds on the second one, but the first one is by itself. You should think JSP, and you would most probably benefit from drawing the diagrams before you start coding.Exercise 1:
- Create a new console program and name it 'ListNumbers'.
- Declare a list of 5 variables that is assigned at declaration (Int32 blahblah = {values};).
- Make a loop that lists the values on one line.
- Wait for the user to press a key to close the program the usual way.
Exercise 2:
- Create a new console program and name it 'ByTheNumbers'.
- Declare a list of 10 integers using the new operator.
- Make a loop that asks the user to enter a value for each of the elements in the list.
- Wait for the user to press a key to close the program.
This is how it may look when you run it:
Exercise 3:
- Continue on program 'ByTheNumbers'.
- Ask Mr Google about bubble-sort algorithms.
- Draw a JSP-diagram of a bubble-sort algorithm.
- Add code for sorting your list of Int32 you created in exercise 2.
- Loop and list the list of integers on one line separated by tabs.
- Wait for the user to press a key to close the program.
Why do I tell you to ask Mr Google rather than presenting the bubble-sort algorithm here? Frankly, you do not learn it all in a course. The techniques are so many, and more evolves on a daily basis, that no course could ever teach it all to you. And you would not remember it all. You will use Mr Google a lot when writing programs, and I want to get you started to do so. Remember, this is a course for beginners, and aim is to get beginners started. Not to make them experts. That you will become after many years of programming experience.
This is how it should look: