Thursday, May 8, 2008

Subroutines

Subroutines and functions allow us to package similar instructions together. We've seen built-in subroutines before like:

Math.Sqrt()
Int()
Math.Round()
FormatNumber()
FormatCurrency()
FormatPercent()
str.IndexOf()
str.Length()
str.Substring()
...etc...


Each one of these subroutines/functions does something useful. We can use them to do a certain job, whether it is changing a number value in some way, formatting output or figuring out certain characteristics of strings.

We also learned that we can make our own functions and subroutines to do things that we decide. So let's say that we want to write a print subroutine that will just print out our report, and a calculate() function that will take in three of the expenses and add them together and return the answer. Take a look at the code:
Click for larger image.



You just have to make sure to write the function and subroutine code outside of the button1_click() subroutine and inside the Class Form1 block.

Tuesday, May 6, 2008

2-Dimensional Arrays

We can declare 2-Dimensional arrays by using the following statement:

Dim arrayName(r,c) As Type

Where arrayName is the name of the array you have created and Type is the array's type. The subscripts r and c represent the Row and Column of the array.

So we could declare an array as type double to hold students' grades:

Dim grades(3,3) As Double
'Four students with four grades


This creates a 4x4 matrix with rows and columns starting at 0 and ending at 3:

0 1 2 3
+---+---+---+---+
0 | | | | |
+---+---+---+---+
1 | | | | |
+---+---+---+---+
2 | | | | |
+---+---+---+---+
3 | | | | |
+---+---+---+---+

We can set any cell in the array by issuing a call such as:

grades(1,1) = 90
grades(3,0) = 99
grades(1,0) = 100

With the above code our resulting matrix will look like:

0 1 2 3
+---+---+---+---+
0 | | | | |
+---+---+---+---+
1 |100| 90| | |
+---+---+---+---+
2 | | | | |
+---+---+---+---+
3 |99 | | | |
+---+---+---+---+

If we wanted to set all the cells to a particular value, such as 0 for example, we would have to use a nested loop:

For i As Integer=0 To 3
For j As Integer=0 To 3
grades(i,j) = 0
Next
Next


We can also declare the 2-dimensional array without a size as we can with regular arrays:

Dim arrayName(,) As Type
Dim array2(,) As Type = {{ROW0},{ROW1},{ROW2},...,{ROWm}}

ReDim arrayName(r,s)
ReDim Preserve arrayName(r,s)

Real Examples:

Dim grades(,) = {{99,50,80},{100,80,70},{90,88,90}}
ReDim Preserve grades(3,4)

GetUpperBound

There are two different GetUpperBound calls for 2-dimensional arrays:

arrayName.GetUpperBound(0)
arrayName.GetUpperBound(1)

The first call gives you the upperbound on the number of rows, while the second one gives you the upperbound on the number of columns.

Thursday, May 1, 2008

Some Exam Problems

Problems from the first sample test are as follows (Hopefully without typos):

1) D
2) A
3) C
4) C
5) C
6) C
7) C
8) D
9) B
10) B

Discussion:
Code from #10:
Dim place, i As Integer
Dim character, sentence, phrase(9) As String
sentence = "Every path hath a puddle."
place = 0
i = 0
character = sentence.Substring(place, 1)
Do
If character = " " Then
phrase(i) = sentence.Substring(0, place)
i += 1
End If
place += 1
character = sentence.Substring(place, 1)
Loop Until character = "."


The answer is ``Every path".

We have the following variables:
i 'The current index of the array
place 'The current location in the sentence string
character 'The current character at which we are looking
sentence 'String: "Every path hath a puddle."
phrase() 'Array of size 10


What the code does, loosely, is going through the sentence string one character at a time and every time it hits a space, it saves the all of the i+1 words in the current array index i into the array phrase().

If we look at the part of the code that actually changes the array (highlighted above) then we can see that every time the array is updated it starts at the very beginning and goes up to place characters. Therefore the final array should look like:

0 1 2 ...
+-------+------------+-----------------+----
| Every | Every path | Every path hath | ...
+-------+------------+-----------------+----

Where every cell has one extra word in it from the beginning. The program stops when character = "." which is at the end of the sentence string.

Programming Problem:
a)

Dim arr(1000) As Integer
For i As Integer = 1 To 1000
arr(i) = CInt(InputBox("Enter number: " ,""))
Next

For j As Integer = 1000 To 1, Step -1
lstBoxOut.Items.Add( arr(j) )
Next

b)
Dim arr(1000) As Integer
For i As Integer = 1 To 1000
arr(i) = CInt(InputBox("Enter number: " ,""))
Next

For j As Integer = 1000 To 1, Step -1
If arr(j) Mod 2 = 0 Then
lstBoxOut.Items.Add( arr(j) )
End If
Next

Second Practice Exam

You can find a past exam 2 here. I made a mistake on the first question when I gave you the answers. Here are the correct answers:

1) D
2) C
3) B
4) B
5) D
6) D
7) C
8) B
9) C
10) A

Part II
a) 70^2 = 4900
b) 24^2 = 576

Part III
Answer: 3

Discussion:
The first two loops simply save all of the numbers from the files into arrays a() and b()

sr = IO.File.OpenText("DATA1.TXT")
For k As Integer= 0 To 19
a(k) = CDbl(sr.ReadLine)
Next
sr.Close()
sr = IO.File.OpenText("DATA2.TXT")
For k As Integer = 0 To 19
b(k) = CDbl(sr.ReadLine)
Next


After this, a() contains:
3, 2, 5, 1, 7, 8, 3, 5, 6, 2, 3, 6, 1, 6, 5, 5, 7, 2, 5, 3

and b() contains:
5, 3, 3, 4, 8, 2, 3, 5, 9, 5, 3, 7, 3, 7, 6, 3, 2, 1, 3, 4

This is in order so a(0) equals 3 and a(1) equals 2; b(0) equals 5 and b(1) equals 3 etc...

The last loop is what changes variable c before it is output:

For k As Integer = 0 To 19
If a(k) = b(k) Then
c += 1
End If

Next
lstBox.Items.Add(c)


What the loop is doing is simply traversing all of the indeces (cells) of the arrays one at a time. Variable c only changes if the numbers in the cells are equal. Therefore we only need to count when the numbers are equal to each other:

a() contains:
3, 2, 5, 1, 7, 8, 3, 5, 6, 2, 3, 6, 1, 6, 5, 5, 7, 2, 5, 3

b() contains:
5, 3, 3, 4, 8, 2, 3, 5, 9, 5, 3, 7, 3, 7, 6, 3, 2, 1, 3, 4

This occurs three times, so the answer is 3.

Tuesday, April 8, 2008

Structures

Instead of using parallel or 2-dimensional arrays for storing various information that we would like to manipulate. For example, universities have various information about them that is universal. Each university has the following properties:

  • Name
  • State in which the university is located
  • Date that the university was founded
  • Population


Of course there are many more things that universities have, but this is a start.

Now we could use parallel arrays to store this information (like in our ATM project). Doing so, would mean that we would have 4 arrays to store the above information and that we could use the same index to reference information for a particular university:

Dim uName(3) As String
Dim uState(3) As String
Dim uFounded(3) As String
Dim uPopulation(3) As String

Let's say that we set the following:

uName(1) = "Queens College"
uState(1) = "NY"
uFounded(1) = "1960" 'I'm not sure about the date
uPopulation(1) = "5,000" 'Or the population :-)

So all of Queens College's information is accessible by accessing index 1 of each array. Thus the parallel Nature.

But suppose that we do not want to keep track of four arrays. We could then create a Structure or a container to keep all of this information in one place:

Structure uInfo
Dim name As String
Dim state As String
Dim founded As String
Dim population As String
End Structure

Now we have created our own type and we can declare a variable of this type like this:

Dim college As uInfo

In order to set (or use) any property of colleges, we use the ``dot'' method:

college.name = "Queens College"
college.state = "NY"
college.founded = "1960"
college.population = "5,000"


Declaring an Array of type uInfo

We can declare arrays of any type, including our own defined types.

Dim colleges(10) As uInfo
colleges(0).name = "Queens College"
colleges(0).state = "NY"
colleges(0).founded = "1960"
colleges(0).population = "5,000"

The resulting array will look like (except up to 10):
        0          1    2 ...
+---------------+----+----+
| Queens College| | |
+---------------+----+----+
| NY | | |
+---------------+----+----+
| 1960 | | |
+---------------+----+----+
| 5,000 | | |
+---------------+----+----+


You can see that every cell is broken up into 4 parts that contain the items from the structure itself.

Of course if we had an array of things, it would make more sense to take in the information from a file:

For i As Integer = 0 To 10
colleges(i).name = sr.Readline()
colleges(i).state = sr.Readline()
colleges(i).founded = sr.Readline()
colleges(i).population = sr.Readline()
Next

Student Grades Example

Today we talked about dealing with student grades using arrays. We would have an array that would hold the students' identifying information (such as name or ID number) and then arrays for all of the students' grades. Remember, these are called Parallel Arrays.

Example:

Public Class Form1
'Global Variables:
Dim students(5) As String
Dim hw1(5) As Double
Dim hw2(5) As Double
Dim hw3(5) As Double
...
...


We have declared these arrays as Global so that we will be able to use them in all subroutines, and also so that we will not loose the information stored in them for the duration of the program. Here are what the resulting arrays look like:

students()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw1()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw2()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw3()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+


As we can see, Student1's information will reside in index 1 of all the arrays.

Code

We wrote two subroutines, one to get the information from the user and one to find and print the information for a particular student.

Here is the code for getting the student information:

Sub form_load()
For i As Integer=0 To students.GetUpperBound(0)
students(i) = InputBox("Enter student " & _
CStr(i) & "'s name:")
hw1(i) = CDbl(InputBox("Enter homework 1:"))
hw2(i) = CDbl(InputBox("Enter homework 2:"))
hw3(i) = CDbl(InputBox("Enter homework 3:"))
Next
End Sub


Here is the code for a linear search of a student:

Sub btnSearch_Click()
Dim sname As String
Dim found As Boolean = False
sname = InputBox("Enter student's name:")
For i As Integer = 0 To students.GetUpperBound(0)
If sname = students(i) Then
listbox1.Items.Add(hw1(i))
listbox1.Items.Add(hw2(i))
listbox1.Items.Add(hw3(i))
found = True
Exit For

End If
Next


If Not found Then
MsgBox("Student not found",,"")
End If
End Sub


2-Dimensional Conversion

We can convert the 1-dimensional grade parallel arrays into a two dimensional array. The names of the students must remain a separate 1-dimensional array, however since its type is different. Here are the declarations:


Public Class Form1
'Global Variables:
Dim students(5) As String

Declare hw() with 3 rows and 5 columns:
Dim hw(3,5) As Double
...
...

Resulting in the following arrays:

students()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw()
0 1 2 3 4
+----+----+----+----+----+
0 | | | | | |
+----+----+----+----+----+
1 | | | | | |
+----+----+----+----+----+
2 | | | | | |
+----+----+----+----+----+


Rewritten Code

In the hw() array, each row represents a HW grade and each column represents the grades for each student. Now we will rewrite our subroutines:

Sub Form_Load()
For i As Integer=0 To students.GetUpperBound(0)
students(i) = InputBox("Enter student " & _
CStr(i) & "'s name:")
hw(0,i) = CDbl(InputBox("Enter homework 1:"))
hw(1,i) = CDbl(InputBox("Enter homework 2:"))
hw(2,i) = CDbl(InputBox("Enter homework 3:"))
Next
End Sub


Here is the code for a linear search of a student:

Sub btnSearch_Click()
Dim sname As String
Dim found As Boolean = False
sname = InputBox("Enter student's name:")
For i As Integer = 0 To students.GetUpperBound(0)
If sname = students(i) Then
listbox1.Items.Add(hw(0,i))
listbox1.Items.Add(hw(1,i))
listbox1.Items.Add(hw(2,i))
found = True
Exit For

End If
Next


If Not found Then
MsgBox("Student not found",,"")
End If
End Sub


If we wanted to reduce the three lines dealing with the HW grades into one line, we could add another For loop to loop through the grades:

Sub Form_Load()
For i As Integer=0 To students.GetUpperBound(0)
students(i) = InputBox("Enter student " & _
CStr(i) & "'s name:")
For j As Integer=0 To hw.GetUpperBound(0)
hw(j,i) = CDbl(InputBox("Enter homework " & CStr(j)))
Next
Next
End Sub


Here is the code for a linear search of a student:

Sub btnSearch_Click()
Dim sname As String
Dim found As Boolean = False
sname = InputBox("Enter student's name:")
For i As Integer = 0 To students.GetUpperBound(0)
If sname = students(i) Then
For j As Integer=0 To hw.GetUpperBound(0)
listbox1.Items.Add(hw(j,i))
Next
found = True
Exit For

End If
Next


If Not found Then
MsgBox("Student not found",,"")
End If
End Sub


.GetUpperBound

Remember for 1-dimensional arrays the .GetUpperBound() function returns the number of the last possible index so:
   students.GetUpperBound(0)

returns 4.

For 2-dimensional arrays we have two indeces in which we are interested: one that indicates the highest index of rows, and one that indicates the highest index of columns. Therefore there are two possible GetUpperBound() calls:

'Get the last index of rows
hw.GetUpperBound(0)
'Get the last index of columns
hw.GetUpperBound(1)

We have used this in our rewritten subroutines above.

Monday, April 7, 2008

mp3 Files in VB .NET


You can play mp3 files in VB .NET also. The link above shows how to add a Windows Media Player to your project and to hide if you like. Otherwise you can show the player like shown at left.

You only have to change one line of code if you want it to allow the user to search for files (shown in red):

Private Sub Button1_Click(...)

Const DATA_FILE_EXTENSION As String = ".mp3"
Dim dlgFileDialog As New OpenFileDialog
With dlgFileDialog
.Filter = DATA_FILE_EXTENSION & _
" files (*" & DATA_FILE_EXTENSION & "|*" & _
DATA_FILE_EXTENSION

.FilterIndex = 1
.RestoreDirectory = True
If .ShowDialog() = Windows.Forms.DialogResult.OK Then
'Play the sound file
Me.AxWindowsMediaPlayer1.URL = dlgFileDialog.FileName
End If
End With

End Sub

Using Two Forms

Since there is some confusion about how to use two forms, I have made a video to help clear this up. First of all you have to add a second form to your project before you can use it. To do this, go to:

-> Projects
--> Add Windows Form
---> Add

Then in the Solution Explorer [usually top right] you should see two forms. You can double click one of them to begin design on it. So you have to double click ``Form2'' in order to add things to it. You will have to add a listbox to it.

From form1, you have to add one button. You have to program the button so that it will show form2.

When you run the program, only the first form will be shown by default. Therefore, you will have to manually make the second form appear by writing the following code in the button:

Form2.Show()

If you want the first form to disappear, you will have to do so manually by writing the following code:

Me.Hide()

Notice that it does not say ``Form1.Hide().'' This is because a form can only refer to itself using ``Me'' kind of like in English. You wouldn't talk about yourself in the third person, would you?

In order to skip lines you can simply Add nothing to the listbox:

Form2.Listbox1.Items.Add("") 'Skips a line

Since you will be adding several lines, you may want to use the With option:

With Form2.Listbox1.Items
.Add("Business Expense Report")
.Add("")
.Add("Information for Conference")
.Add(txtBox1.Text)
.Add(txtBox2.Text & " in " & txtBox3.Text)
.Add("")
...etc...
End With


Video of Two Forms
You may click on this link, where you can watch it full screen.