| |
|
|
| |
|
|
| |
| |
|
Basic data types in VC#.NET
Integers:
byte (1 byte)
short (2 bytes)
int (4 bytes signed)
long (8 byte)
Strings and characters:
bool (1 byte)
Notice that type checking does not allow implicit conversion
between data types in cases where data might get lost (may implicitly
convert from short to int, but not from long to int).
Control flow
Loops:
Say 'Hello world...' five times:
class Hello
{
static void Main()
{
int i;
for (i = 0; i < 5; i++)
{
System.Console.WriteLine("Hello World...");
System.Console.WriteLine();
}
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Exit");
System.Console.ReadLine();
}
} /* end of Hello class */
class Hello
{
static void Main()
{
int i, j;
for (i = 1; i <= 10; i++)
{
for (j = 1; j <= 10; j++)
System.Console.Write(System.Convert.ToString(i * j) + " ");
System.Console.WriteLine();
}
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Exit");
System.Console.ReadLine();
}
}
while loops: Say 'Hello, world...' five times:
class Hello
{
static void Main()
{
int i = 1;
while (i <= 5)
{
System.Console.WriteLine("Hello, World...\n");
i = i + 1;
}
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
class Hello
{
static void Main()
{
int i, j;
i = 1;
while (i <= 10)
{
j = 1;
while (j <= 10)
{
System.Console.Write(System.Convert.ToString(i * j) + " ");
j = j + 1;
} /* end while j */
System.Console.WriteLine();
i = i + 1;
} /* end while i */
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
Decide if a number is prime (make sure you understand the logic of the code below. For instance, note that is_prime() returns a bool):
class Hello
{
static void Main()
{
int count = 1;
int number = 1;
while (count <= 100)
{
if (is_prime(number))
{
System.Console.WriteLine(System.Convert.ToString(count) + ": " + System.Convert.ToString(number));
count++;
}
number++;
}
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quite.");
System.Console.ReadLine();
}
static bool is_prime(int number)
{
double root;
int i;
if (number < 4)
return(true); /* numbers 1, 2 and 3 are prime */
if (number%2 == 0)
return(false); /* number is even; not a prime */
root = System.Math.Sqrt(number);
for (i = 3; i <= (int)root; i = i + 2)
if (number%i == 0)
return(false); /* number divides by an odd number; not a prime */
return(true); /* no divisors worked; is prime */
}
} /* end class Hello */
Arrays:
An array is a memory construct to hold a 'row' of variables of identical type (although mixed-type arrays exist as well); e.g.:
int[] i; i = new int[10];
gives you 10 ints all addressed by referring to i.
Notice the order of the declaration; you first declare the variable to be of type 'integer array,' after which you 'allocate' the memory of the array with the required length value.You can, of course, do this in one line as well:
int[] i = new int[10];
How to get to ('index') individual array elemants? Index into the array using a subscript:
i[1] = 45Store in an array the first 100 multiples of 2; then print them:
class Hello
{
static void Main()
{
int[] my_array = new int[100];
int j;
for (j = 0; j < 100; j++)
my_array[j] = 2 * (j + 1); /* this stores them */
for (j = 0; j < 100; j++)
System.Console.Write(System.Convert.ToString(my_array[j]) + " "); /* this prints them */
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
Notice how the array element subscripts start at 0 (!!) and how this forces us to add 1 to j when doing the arithmetic. (Alternatively we could subtract 1 when indexing into the array. Can you modify the code this way?)
class Hello
{
static void Main()
{
int[,] table = new int[10,10];
int i,j;
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
table[i,j] = (i + 1) * (j + 1);
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
System.Console.Write(System.Convert.ToString(table[i,j]) + " ");
System.Console.WriteLine();
}
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
Since an array is a 'referential object' in C#, you can pass it around between routines 'by value' and still have the receiving function access its members. Fill a small array in Main(); then pass it to a subroutine to have each of its elements doubled. Then print out the array contents in Main():
class Hello
{
static void Main()
{
int[] my_array = new int[5];
int j;
for (j = 0; j < 5; j++) /* fill up the array with consecutive numbers */
my_array[j] = j + 1;
for (j = 0; j < 5; j++) /* print it out */
System.Console.Write(System.Convert.ToString(my_array[j]) + " ");
System.Console.WriteLine();
do_this(my_array, 5); /* call the function that doubles the values */
for (j = 0; j < 5; j++) /* print it out again */
System.Console.Write(System.Convert.ToString(my_array[j]) + " ");
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
static void do_this(int[] num, int length)
{
for (int i = 0; i < length; i++)
num[i] = num[i] * 2;
}
}
Passing a two-dimensional array to a subroutine where it's printed out (notice the notation for receiving this array in the subroutine):
class Hello
{
static void Main()
{
int[,] table = new int[10,10];
int i, j;
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
table[i,j] = (i + 1) * (j + 1);
print_them_out(table);
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
static void print_them_out(int[,] mytable)
{
for (int i = 0; i < mytable.GetUpperBound(0); i++)
{
for (int j = 0; j < mytable.GetUpperBound(1); j++)
System.Console.Write(System.Convert.ToString(mytable[i,j]) + " ");
System.Console.WriteLine();
}
}
}
array_name.GetUpperBound(array_dimension_for_which_the_upper_bound_is_needed)
This shows that arrays are, in fact, objects of the 'arrray' class. (these objects
get created ('instantiated') through new.
I/O: Input Output: Getting external information to and from your program:
Write() and WriteLine() are output functions. Information is sent from your program to an output device, in all cases sofar, the console window.
Programs read from (input) and write to (output) so-called I/O streams. I/O streams can be 'hooked up' to a device; e.g., a printer, file, port, etc.
Example: Get an integer from the keyboard and print it to the console:
class Hello
{
static void Main()
{
int i;
System.Console.WriteLine("give me an integer...");
System.Console.WriteLine();
i = System.Convert.ToInt32(System.Console.ReadLine());
System.Console.WriteLine();
System.Console.WriteLine("You gave me: " + System.Convert.ToString(i));
System.Console.WriteLine();
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
The string version:
class Hello
{
static void Main()
{
string str;
System.Console.WriteLine("give me a name...");
System.Console.WriteLine();
str = System.Console.ReadLine();
System.Console.WriteLine();
System.Console.WriteLine("You gave me: " + str);
System.Console.WriteLine();
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
Create both an in.txt file and an out.txt file and place them in C:\temp\. Include an integer on the first line of in.txt.
class Hello
{
static void Main()
{
//Declare two streams (FileStream) for the input and output files:
System.IO.FileStream InFile;
System.IO.FileStream OutFile;
int my_int;
//Declare StreamReader and StreamWriter for reading and writing:
System.IO.StreamReader Reader;
System.IO.StreamWriter Writer;
//Open the streams by hooking them up to the files:
InFile = new System.IO.FileStream("c:\\temp\\in.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read);
OutFile = new System.IO.FileStream("c:\\temp\\out.txt", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
//Connect the StreamReader and StreamWriter to the streams:
Reader = new System.IO.StreamReader(InFile);
Writer = new System.IO.StreamWriter(OutFile);
//Read the integer from the Reader
my_int = System.Convert.ToInt32(Reader.ReadLine());
//Write the integer to the Writer
Writer.WriteLine(System.Convert.ToString(my_int));
//Close the Reader and Writer
Reader.Close();
Writer.Close();
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
Now go check the files!
Note the comment lines. ('//' for single lines, '/* ... */' for multiple lines)
Exception/Error Handling:
What to do if the input file c:\temp\in.txt is not present?
Remove c:\temp\in.txt and rerun the program. What do you observe?
Unhandled Exception: System.IO.FileNotFoundException
Program dies!
Notice that this is a so-called 'runtime' error; i.e., there is no syntactical errer-- the compiler does not ccomplain abaout the code; the problem is that the code does not cover for the file not being there.
Golden rule of programming: Your program should never die.
Your program MUST anticipate situations like this and gracefully handle them.
Include so-called 'exception detection and handling' in your code:
class Hello
{
static void Main()
{
int my_int;
System.IO.FileStream InFile = null;
System.IO.FileStream OutFile = null;
System.IO.StreamReader Reader;
System.IO.StreamWriter Writer;
try
{
InFile = new System.IO.FileStream("C:\\temp\\in.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read);
}
catch
{
System.Console.WriteLine("Error opening 'in' file...");
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
System.Environment.Exit(1);
}
try
{
OutFile = new System.IO.FileStream("C:\\temp\\out.txt", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
}
catch
{
System.Console.WriteLine("Error opening 'in' file...");
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
System.Environment.Exit(1);
}
Reader = new System.IO.StreamReader(InFile);
Writer = new System.IO.StreamWriter(OutFile);
my_int = System.Convert.ToInt32(Reader.ReadLine());
Writer.WriteLine(System.Convert.ToStringStr(my_int));
Reader.Close();
Writer.Close();
System.Console.WriteLine();
System.Console.WriteLine("Press Enter to Quit.");
System.Console.ReadLine();
}
}
Notice the try{}... catch(){}... blocks.
Notice how in the catches (the parts of the code that ccontain the instructions for what to do in case the try fails, we return the exit status of the program to the OS (nonzero for programs that run into a 'lethal' exception).
Notice that hardwiring the absolute path of the file in the code is bad!!! It is done here for demonstrative purposes only. Always!!! write your code so that it is entirely independent of the local file/machine system. We'll see some examples of this in future labs.
The Visual Studio.NET Debugger
As in most integrated development environments (IDEs), VS.NET
contains a debugger for stepping through code and for inspecting the
contents of variables and memory as the program runs.
When you 'build' your program, debug information is
automatically linked into your code; i.e., the compiler registers the
various instructions to particular lines in the source file.
To run your program in the debugger, first decide where in your code
you want to interrupt its execution. In the IDE, click your left mouse
button at the very beginning of that line (in the narrow, gray,
vertical band at the left of the text editor) and notice how the line
is now marked as a so-called 'breakpoint.' You
can set multiple breakpoints.
To now activate the debugger select Start Debugging from the Debug
menu. The application will run but execution will be interrupted as the
debugger reaches one of your breakpoints. At this point you can mouse
over your variables and have their value displayed. For more complex
variables, such as arrays, you can have them displayed by selecting
them with the mouse and then selecting the QuickWatch... option from
the Debug menu.
Once you're ready to move on to the next set of instructions, you have
several options:
Debug --> Continue will continue execution until the next breakpoint is reached.
Debug --> Step Over will execute the next line of code, but not debug it; i.e., if the next line of code is a function or subroutine call, the function will be executed in its entirety.
Debug --> Step Into
will execute the next line of code and debug it; i.e., if the next line
of code is a function or subroutine call, the debugger will act as if
the first line of code in the function or subroutine has a breakpoint
on it.
Debug --> Stop Debugging
will quit the debugger (you must stop debugging before you can edit
your source code).
!!! Make sure you feel at home
with the VS.NET debugger. It is a very powerful tool
for diagnosing runtime problems. Without it, finding the causes
of these problems is very, very laborious. !!!
Practice exercises
In case you would like to train yourself using the above VC#.NET
language constructs, try one or more of the following exercises:
Prompt your user for how many Fibonnaci numbers (0, 1, 1, 2, 3, 5, 8, 13, ...) to compute, then compute them and calculate the average ratio between adjacent numbers (should be close to 1.61804 (We'll talk about this number in one of our classes).
Write an HTML multiplication table. Prompt your user to give you the dimensions for the multiplication table (e.g., 10x10, or 5x5, or 10x5). Your program builds an HTML page containing the multiplication table and writes it to a file. Pick it up with your browser to see if the HTML is correct.