Sunday, November 28, 2010

Sunday 11/28/10

Continuing with the Jesse Liberty Console Tutorials


Option Strict On
Imports System

Public Class Time
'Private variables
Private AYear As Integer
Private AMonth As Integer
Private ADate As Integer
Private AHour As Integer
Private AMinute As Integer
Private ASecond As Integer

'public methods
Public Sub displayCurrentTime()
System.Console.WriteLine("{0} / {1} / {2} " & vbTab & "{3} : {4} : {5}", AMonth, ADate, AYear, AHour, AMinute, ASecond)
End Sub ' display current time

Public Sub New( _
ByVal theYear As Integer, _
ByVal theMonth As Integer, _
ByVal theDate As Integer, _
ByVal theHour As Integer, _
ByVal theMinute As Integer, _
ByVal theSecond As Integer)

AYear = theYear
AMonth = theMonth
ADate = theDate
AHour = theHour
AMinute = theMinute
ASecond = theSecond

End Sub
End Class 'Time

Module Module1

Sub Main()
Dim timeObject As New Time(2005, 3, 25, 9, 35, 20)
timeObject.displayCurrentTime()
Console.ReadLine()
End Sub
End Module


Here is a tutorial I wrote for getting the current time in seconds


Sub Main()
Dim second1 As Integer
Dim second2 As Integer

Dim keepGoing As Boolean = True


While keepGoing = True
Call printSeconds(second1, second2)
keepGoing = stopOrNot()
End While

End Sub

Sub printSeconds(ByRef second1, ByRef second2)

Call getSeconds(second1, second2)
Console.WriteLine("second1 is: " & second1 & " and second2 is: " & second2)
End Sub

Function stopOrNot()
Dim inputString As String = ""
inputString = Console.ReadLine
If inputString.ToUpper = "STOP" Then
Return False
Else
Return True
End If
End Function

Sub getSeconds(ByRef second1, ByRef second2)
Dim d1 As DateTime = DateTime.Now
Dim d2 As String = d1.ToString
second1 = (Val(d2.Chars(16)))
second2 = (Val(d2.Chars(17)))
End Sub


Here is another variant of the tutorial by Jesse Liberty


Imports System
Public Class Time
'private variables
Private aYear As Integer
Private aMonth As Integer
Private aDate As Integer
Private anHour As Integer
Private aMinute As Integer
Private aSecond As Integer = 30

'Public methods
Public Sub DisplayCurrentTime()
System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", _
aMonth, aDate, aYear, anHour, aMinute, aSecond)

End Sub

Public Sub New(ByVal theYear As Integer, _
ByVal theMonth As Integer, _
ByVal theDate As Integer, _
ByVal theHour As Integer, _
ByVal theMinute As Integer, _
ByVal theSecond As Integer)

aYear = theYear
aMonth = theMonth
aDate = theDate
anHour = theHour
aMinute = theMinute
aSecond = theSecond
End Sub

Public Sub New(ByVal existingObject As Time)
aYear = existingObject.aYear
aMonth = existingObject.aMonth
aDate = existingObject.aDate
anHour = existingObject.anHour
aMinute = existingObject.aMinute
aSecond = existingObject.aSecond
End Sub
End Class 'Time





Module Module1
Sub Main()
Dim timeObject As New Time(2008, 3, 25, 10, 25, 11)
Dim t2 As New Time(timeObject)
timeObject.DisplayCurrentTime()
t2.DisplayCurrentTime()
Console.ReadLine()
End Sub



End Module


Here is another tutorial



Dim fileName As String = "C:\Users\Alfred\My Documents\VBPractice\newStocks.txt"

Console.WriteLine("Created: " & _
System.IO.File.GetCreationTime(fileName))
Console.WriteLine("Last Modified: " & _
System.IO.File.GetLastWriteTime(fileName))
Console.WriteLine("Last accessed: " & _
System.IO.File.GetLastAccessTime(fileName))
Console.ReadLine()

3 comments:

Brad Jensen said...

The following are my thoughts and opinions as a result of looking at your recent tutorials. You might find some useful ideas among them.

The first tutorial on time showed me how to define a class in vb.net, which is interesting.

I also noticed that you explicitly defined the variable type for each parameter in the subroutine definition. I think this is a very good idea to do for every subroutine.

Example:

sub dosomething (byval athing as integer, byval bthing as string)

instead of

sub dosomething (athing, bthing)

The principle of this is preserving certainty. When the definitions are not explicit, but depend on the variable definitions on other lines, if you reuse the code by cutting and pasting it from a previous program, it's possible for errors to creep in when you use the subroutine because the variable types are different in the calling sequence in the new code. This extra bit of effort makes it easier for the programmer who is reusing the code (often that will be the programmer who wrote it)

By the way, there are two issues of using ByRef versus ByVal.

When a program calls a subroutine, it places the parameters on a shared piece of memory used by all the programs and subroutines in a single task, called 'the stack'. There are two different ways to communicate the parameters. One is to put the actual values on the stack, and the other is to put the address of the parameters.

So if you have

A = 5
B = "me"

And call

Dosomething( a, b)

Since VB.net defaults to passing parameters ByVal, the calling program will put the value 5 and the value "me" (and also the string's length, 2) on the stack.

The called subroutine or function knows to get the -values- off the stack. Although theoretically the subroutine could change the values of A and B and put those changed values on the stack, and the calling program could then put those values back into the variables A and B, in modern programming languages this is not done, for pragmatic reasons. So when a parameter is passed ByVal, you know the called subroutine or function cannot change the original calling variables. In effect, a -copy- of the paramaeter is being passed to the subroutine, and this provides valuable information to the programmer using this subroutine that the variables are 'safe' and will not be modified.

When the parameters are passed ByRef, the address of the parameter is on the stack, not a copy of the value. This means the subroutine or function is free to modify the original value. This is not the only reason to use ByRef. Suppose you have a string variable with 10 million characters that you are sending to a subroutine for examination. Copying that large amount of data to the stack takes time. Then the subroutine will likely look at each character of the string. In the case of using Byref, only the string address is on the stack, and the subroutine only use the time of looking at each character, not copying it to the stack. If you are writing a program that calls this subroutine thousands of times, the difference in speed can be large.

Really since VB.net defaults to ByVal (the C default, the opposite of the earlier VB6,5,4 default) it's really superfluous to use BYVal in the sub definition in most cases.

Brad Jensen said...

In that second tutorial you check for user input on whether to stop:

Function stopOrNot()
Dim inputString As String = ""
inputString = Console.ReadLine
If inputString.ToUpper = "STOP" Then
Return False
Else
Return True
End If
End Function


This forces the user to hit the return key on every loop of the program, whether or not they want to stop. Another way to do this where the subrtouine only stops for input when the user has actually typed a key, might be:

Function stopOrNot()
Dim inputString As String = ""
If Console.KeyAvailable() Then 'only look for input if there is a keystroke in the input bffer
inputString= Console.ReadKey(True).KeyChar ' get the keystroke, and print it on the screen as you do ('True') parameter prints it back to screen End If If inputString.ToUpper = "S" Then Return False Else Return True End If End Function

The problem with this, is the loop displaying the time on the screen is going to run so fast, it will be a blur, so you might want a sleep function in the loop.

VB.net uses

System.Threading.Thread.Sleep(1000)

Where the calling parameter is the number of milliseconds, 1000 = 1 second

So after testing the StopOrNot results, you might put a

System.Threading.Thread.Sleep(100)

Before the Wend ending the loop.

Most programs you write don't need to do this explicitly, but if you have a program with a tight loop that executes over and over, you might want to add this code to improve the visual look of your program, and reduce its impact on other programs that are running at the same time. You can see some of the effect by starting the Task Manager (right click on the Windows taskbar at the bottom of the screen) and find your program in the Task list, and watch the CPU % running without the sleep, and with it (assuming you use the console.keyavailable code that allows continuous processing in the loop.)

Note: If you set this parameter to 0, your program gives up its time slice to the other programs waiting to run. In the current case, you don't want to do that, because chances are the other programs are going to give you the time slice back so fast, your time display is still going to be a blur.

Brad Jensen said...

In the tutorial about the file dates and times, one thing to note is automatic casting of the returned values into a display format.

Console.WriteLine("Created: " & _
System.IO.File.GetCreationTime(fileName))

Concatenating it with constant string "Created: " causes the date/time variable returned by System.IO.File.GetCreationTime(filename) to be changed into the default display format for a date/time value on your system.

This is also true for

Console.WriteLine("Last Modified: " & _
System.IO.File.GetLastWriteTime(fileName))
Console.WriteLine("Last accessed: " & _
System.IO.File.GetLastAccessTime(fileName))

If you want more control over how the date/time value is displayed, you can format it explicitly:

Dim dateTimeInfo as DateTime = System.IO.File.GetCreationTime(fileName)

Dim strDate as String = dateTimeInfo.ToString("f") 'uses a named format, you can also use a detailed string of characters to manipulate display

See http://articles.techrepublic.com.com/5100-10878_11-6106789.html for a quick discussion of date/time formats, and

http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx for MSDN discussion of custome date/time formats.

If you are writing a program for international use, it is a good idea generally to select a named date/time format, because it will often localize to the user's local preferences. For example, if I remember correctly, much of the world uses dd/mm/yy rather than the US preference of mm/dd/yy.

I don't know for sure what the output of the dog tutorial is, because I don't know whether this line

Dim fido As dog = milo

Means fido is a copy of milo, or fido is another pointer to the same object as mido.

If the second statement is true, then changing the values of milo changes the values of fido, since they are just two pointers to the same object.

The way to avoid this behavior for certain is

Dim fido As dog
Fido.color=milo.color
Fidow.weight=mido.weight

In this case they are definitely two different objects, although they start with the same values.

It is a good mental construct to always think of any variable or object as an address in memory that has certain contents. In the good old days we referred to this concept by calling the variable a 'bucket'.