Lab 2: Our Most Important Building Blocks

In this lab we will focus on:

  • Console Programming (input, output, and as opposed to GUIs)
  • Control Structures (like ifs and fors and whiles)
  • Memory Structures (like single variables vs arrays)

This lab will be due Sunday, Feb. 18th, midnight eastern time.

Console Programming

In the last lab (Lab 1 under Week Two's folder) we introduced C# as a language compared to other languages some of you may have experience with, and saw how to create "quick and dirty" GUIs using Visual Studio. This was one advantage of C# many of you liked in your journals: getting to real programs quickly.

In this lab we'll deal with Console programming so we can see basic control structures on their own. When we return to GUIs later, then, we'll be better equipped to write the "business logic" to make our real programs actually do something.

Similar to how you started a WPF project last time, to start a Console project:

  1. File > New > New Project > Console Application
  2. Give the project a meaningful name like "Lab2"

You should see default code that looks like this:

using System;

namespace Lab2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Because C# is a compiled language, your code always begins and ends in the Main (where the Console.WriteLine is). With that in mind and for simplicity, all of my code examples today will just be "snippets." To run them, copy and paste into the Main from your default code and press Shift+F5.

Console Output

Working with the Console, there are two useful commands to know: Console.WriteLine for outputing text to the user and Console.ReadLine for inputing text from the user. Console.WriteLine has some nifty features that make it useful for displaying variable values to users. For example:

// Inside the Main
// Code:
string name = "Spencer";
string species = "cat";
int age = 3;
boolean isFluffy = true;

Console.WriteLine("Let me tell you about my pet:");
Console.WriteLine("My {0}'s name is {1}.", species, name);
Console.WriteLine("{0} is {1} years old.", name, age);
Console.WriteLine("It is {0} that {1} is fluffy.", isFluffy, name);

// Output:
// Let me tell you about my pet:
// My cat's name is Spencer.
// Spencer is 3 years old.
// It is True that Spencer is fluffy.

Console.WriteLine can be used to output a simple message, like "Let me tell you about my pet." We can also "plug-in" values from our variables.

In the second Console.WriteLine above, the text {0} will get replaced by the first thing we list after the message template (species) and the {1} will get replaced by the second thing (name). Since we set those equal to "cat" and "Spencer" respectively, Console.WriteLine knows to take the message template "My {0}'s name is {1}" and plug in the right values and display instead "My cat's name is Spencer."

Give the third and fourth lines a look and see how they are taking the values of the variables at the top of the code and outputting information about my cat. Console.WriteLine is very versatile in this way, letting you add as many variables and {...} things as you want, so long as you match the number inside the curly brackets with the right variable you want to display, with 0 being the first thing listed after the template, 1 the second thing, and so on.

Console Input

Console.ReadLine also has some interesting uses.

Although it always returns a string, a good amount of the time what we really want from the user is a number. So, we can combine Console.ReadLine with the Convert.To... methods. For example:

// Inside the Main
Console.WriteLine("What is your name?");
string name = Console.ReadLine();

Console.WriteLine("What is your age?");
int age = Convert.ToInt32(Console.ReadLine());

Console.WriteLine("How much money do you have?");
double balance = Convert.ToDouble(Console.ReadLine());

Console.WriteLine("Is it raining today? (True/False)");
boolean isRaining = Convert.ToBoolean(Console.ReadLine());

Notice how before each Console.ReadLine we use a simple Console.WriteLine to tell the user what they are expected to type. Otherwise, the program will appear to be frozen, when in fact it's just waiting for the user to type something that they don't know we want them to type!

Also notice how when we are getting a string from the user, such as their name, we can just use Console.ReadLine by itself. This is because Console.ReadLine always returns a string already, so no conversion is needed. For the other examples though, we need to process that text to turn it into the proper type.

What would happen if the user typed the text "cat" when we asked them for their age?

The program would crash and would output an error message like:

Exception in user code:

System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Convert.ToInt32(String value)
   at Program.Main(String[] args)

The important part of this message is the line "Input string was not in a correct format." Whereas the text "123" can easily be turned into a number, it makes no sense for the text "cat," so the best the program can do is just blow up!

So how do we make sure the user inputs the right kind of values?

There are ways to handle that, and we will cover that when we cover exceptions. For now, just blame the user for blowing the program up because the word "cat" is obviously not a good answer for the question, "What is your age?"

Control Structures

Above I said that your program always begins and ends in the Main. But what if we want a program that doesn't "move in a straight line," metaphorically?

For example, what if we want to ask the user if they are a dog or cat person, then, depending on their answer, we give them two different experiences. For this we would use an if statement.

Or what if we want to ask the user how many books they have they want to read, then once for each book, ask the user how many pages are in that book and at the end tell them how many pages total they still have to read? For this we would use a for loop.

Or what if we play a guessing game with the user and afterwards ask them if they want to keep playing; as long as they say yes we'll just keep looping back to the start of the game. For this we would use a while loop.

These are our three basic "control structures" and they allow us to control the "flow" of the program, letting the logic metaphorically move in all sorts of directions and branches and loop-de-loops: much more interesting than "moving in a straight line" the same way each time.

if statements

The syntax for an if is identical to how it is in JavaScript, Java, and C/C++, as well as most other languages. For example:

// Inside the Main
Console.WriteLine("How tall are you?");
double height = Convert.ToDouble(Console.ReadLine());
if (height < 4.0){
    Console.WriteLine("You must be taller to ride this coaster!");
} else {
    Console.WriteLine("Have a good time and smile for the camera!");
}

Most of the time when we have an if statement, we also have an else statement that lets us know what to do when the condition for the if is false. In the above example we are deciding what message to display based on the value of some height variable.

If you have more than two options, you might "chain" them together like so:

// Inside the Main
Console.WriteLine("How many items are in your cart?");
int items = Convert.ToInt32(Console.ReadLine());
if (items <= 10){
    Console.WriteLine("Go to the super-speedy checkout line!");
} else if (items <= 15){
    Console.WriteLine("Go to the kinda-speedy checkout line!");
} else if (items <= 50){
    Console.WriteLine("Go to a regular checkout line.");
} else {
    Console.WriteLine("I think you are buying too much.");
}

for loops

The syntax for the for loop in C# is also identical to those other languages. For example:

// Inside the Main
// Code:
for (int i=0; i < 4; ++i){
    Console.WriteLine("Loop #{0}", i);
}

// Output:
// Loop #0
// Loop #1
// Loop #2
// Loop #3

Notice that there is no else for a for loop, as that doesn't really make sense when you think about it. The for loop always begins by running the "initalization" snippet, which is the first part inside the parentheses (int i=0). Almost always we just use this to declare our starting point. Then the for loop checks the condition, which is the second part (i < 4). If this is true, then it runs the loop. Almost always we just say how many times we want to loop to run. After it runs the logic for the loop once, it runs the "update" snippet, which is the last part inside the parentheses (++i). Almost always we just say that we want to increase the value of counter variable by one.

You can also write for loops that run backwards, loops that count by two, loops that start at different numbers than zero, loops that double the counter each time, and so on. But, it's almost always clearer to just write your loop in the "typical" way as the example above and adjust your logic to fit. For example, if I want to print the numbers "1, 3, 5, 7" I can do:

// Inside the Main
for (int i=0; i < 4; ++i){
    int number = 1 + 2*i;
    Console.WriteLine(number);
}

The creative equation "1 + 2*i" lets me keep a typical for loop, which helps avoid annoying loop-related bugs.

while loops

In most books they teach while loops before they teach for loops. This is because while loops were invented first. However, I prefer to teach for loops first, since they come up much more in practice.

And as ifs and fors, while loops have the same syntax in C# as in most languages:

// Inside the Main
bool play = true;
while (play){
    // ... play a game here ...
    Console.WriteLine("Do you want to keep playing? (True/False)");
    play = Convert.ToBoolean(Console.ReadLine());
}

Here I've shown the example code for playing a game once (we just assume the user wants to play the game at least once, so we set the control variable to true at the top), then asking the user if they want to play again after each round.

The way the while loop works is similar to an if: if the condition is true, then it will run its code. However, like the for loop there is no else to a while loop. Instead, after it runs the loop once, it checks the condition again, and if it's still true, it runs it again, repeating forever until something causes that condition to become false.

This means the purpose of the while loop is to make the condition false. I stress this point because, unlike the for loop which ideally always runs X number of times, there is nothing preventing the while loop from "going infinite," which can cause a program to hang, consume a lot of memory, consume a lot of processing power, cause the machine to overheat...

Therefore, when using a while loop, you must include logic inside the while loop that has the power to make the loop's condition false. In my example above, I do this by asking the user if they want to play again and changing the value of play accordingly.

Memory Structures

Control stuctures let us change the "course" of our program from a "straight line." Memory structures let us represent more complex data than just simple numbers and strings. Arrays are our first memory structure in this course.

Arrays are, to put it most simply, lists of values. Whereas an int can hold the value of a single number, an int[] (the [] means "array") can hold the values of multiple numbers.

Because I've written a lot so far for this lab, and because arrays tend to be taught best visually, I recommend the following two videos, in order:

Data Structures: Crash Course Computer Science #14 - introduces the general concept of variable values as they relate to the machine's memory

How to program in C# - ARRAYS - Beginner Tutorial - introduces arrays as they appear in C#

A key take away from the above is this: An array variable's value is still just a single number. This number is equal to the address of a place in memory. That place in memory, then, holds our list of data.

The syntax is similar to how arrays work in C/C++ and Java, but very different from how they work in JavaScript and others. This is because arrays are one point where language designers differ greatly.

To create an array of three strings to hold the names of all my pets, for example:

// Inside the Main
string[] petnames = new string[3];
petnames[0] = "Spencer";
petnames[1] = "Clarence";
petnames[2] = "Okay I only have two cats.";

Here, similar to the way we count things with Console.WriteLine, we can use petnames[0] to refer to the first string value inside that block of memory that petnames is pointing to.

Similarly, petnames[1] refers to the second string value, petnames[2] to the third, and so on. Note, however, we only "allocated" enough room in memory to store three strings (with new string[3]). This means that trying to do petnames[17] (access the 18th name in the list) would result in an error like:

Error(s):
Exception in user code:

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Program.Main(String[] args)

The important part of this message is "Index was outside the bounds of the array" which means that the index (17) was too big for the number of things we have (3).

Of one final note here, arrays and for loops are meant for each other. For example:

// Inside the Main
for (int i=0; i < petnames.Length; ++i){
    Console.WriteLine("Name #{0} = {1}", i, petnames[i]);
}

Here, the variable i will loop through all of the valid index values for petnames and stop before it gets to one that is too big. The trick here is (1) we start i at zero and (2) we keep i strictly less than petnames.Length.

Grading and Submission Instructions

To submit, write your responses to the following questions in a Word document, then upload it to Blackboard under this week's folder in Current Assignments.

Labs are due two weeks from when they are assigned, on Sunday at 11:59pm eastern time.

Labs are each worth 5% of your final grade. Scoring on your submission will be based on the following rubric:

0% - Student does not submit on time or submits plagiarized or unacceptable work. Double check that you have attached the right file, as usually students get zeros because they upload a previous week's Lab by accident.

1% - Student answers less than half of the questions with sufficient or accurate responses. Make sure that you are leaving yourself enough time to complete the Lab each week, as usually students submit incomplete work because they were rushed at the last minute.

3% - Student answers almost all questions with sufficient and accurate responses. If you encounter a problem or have a question about one of the questions, be sure to post in Ask the Instructor well before 24 hours before the due date, then continue to attempt to resolve the issue on your own while you wait for a reply.

5% - Great job, maximum points! The student answers all questions accurately and sufficiently, demonstrating the best of their ability.

Note, because Labs span two weeks' worth of reading, it is recommended to go through the Lab twice, once after the first reading where you answer everything that you can, then again after the second reading where you answer everything else.

Part 1

  1. What type of value is always returned by Console.ReadLine?
  2. Fill in the blank: To get a whole number from the user, I would use Convert.To_____(Console.ReadLine()).
  3. For Console.WriteLine, which corresponds to the third variable listed after the template? (a) {0}, (b) {1}, (c) {2}, or (d) {3}?
  4. If x < y is false, then what is true, (a) x == y, (b) x != y, (c) x > y, or (d) x >= y?
  5. True or false: Every if statement must have an else statement to go with it
  6. True or false: Every else statement must have an if statement to go with it
  7. I will only go skateboarding during the day when it is not raining. Which of these ifs represents that?
    • (a) if (isDay && isRaining) ...
    • (b) if (isDay || isRaining) ...
    • (c) if (isDay && !isRaining) ...
    • (d) if (isDay || !isRaining) ...
  8. What are the three "snippets" that the for loop has in its parentheses?
  9. I want the 10th item from my shopping cart array. Which represents that, (a) cart[9], (b) cart[10], (c) cart(9), or cart(10)?
  10. I need an array to hold 100 items. Which of the following lines of code would make that array for me?
    • (a) string[] things = string[100];
    • (b) string things = new string[100];
    • (c) string[] things = new string[100];
    • (d) string things = new string(100);

Part 2

  1. What is the value of x at the end of the code below?
  2. What kind of control structure is the most appropriate for representing each of the following situations: (a) I am flipping a coin, (b) I need to give each of my 20 students an A+, (c) I want to drink sips of water from the water fountain until I am no longer thirsty, (d) I am looking for a word in the dictionary?
  3. What is the output of the code below? (Hint: use a pencil and paper to keep track of the "dancers" after each "swap")

Code for Question 1:

double x = 14.0;
if (x < 10.0){
    x = 2.0 * x;
} else if (x < 20.0){
    x = x + 5.0;
} else if (x < 30.0){
    x = 2.0 * x + 5.0;
} else {
    x = 0.0;
}

Code for Question 3:

// Everyone Get in Line...
string[] square_dancers = new string[5];
square_dancers[0] = "Alice";
square_dancers[1] = "Bob";
square_dancers[2] = "Cindy";
square_dancers[3] = "Denise";
square_dancers[4] = "Eugene";

// Now Let's Dance!
swap(square_dancers, 0, 1);

// swap is not a real C# method.
// pretend swap(X, i, j) swaps X[i] and X[j].
// for example, now Bob is at position 0 and
// Alice is at position 1

swap(square_dancers, 1, 2);
swap(square_dancers, 1, 3);
swap(square_dancers, 4, 5);
swap(square_dancers, 0, 5);
swap(square_dancers, 1, 2);
swap(square_dancers, 2, 3);

// Who's on First?
Console.WriteLine(square_dancers[0]);

Part 3

In today's last question we'll practice console input/output and ifs.

  1. Write a program to do the following, then embed screenshots of your code and your program running (once for each scenario) as your answer:
    • Ask the user what their age is and store the answer in an int variable
    • If the user is less than 4 years old, then ask them what their name is, store the answer in a string variable, and output, "Okay, let's find your mom, name here."
    • If the user is between 4 and 12, then ask them what their favorite TV show is, store the answer in a string variable, and output, "Oh, I like tv show here too!"
    • If the user is between 13 and 17, then ask them what their favorite number is, store the answer in an int variable, and output, "Well, I like that number plus one here better."
    • Otherwise (the user is 18 or older), simply display a polite but serious message reminding them to file their taxes

If you are unable to complete the above program by the due date, then submit screenshots of what you have, along with a description of any difficulties preventing your progress and a few ideas of what you could do to pass those roadblocks next time. (In other words, never leave an answer blank.)