How-To Series
This is part 3 of a 5 part series for Introduction To Programming
- Introduction To Programming: Getting Started
- Introduction To Programming: Your First Program
- Introduction To Programming: Variables, Types, And Manipulating Data
- Introduction To Programming: Flow Control
- Introduction To Programming: Object Oriented Programming
Returning to Our Program
In the previous two articles in this series, you have, on average, written one line of code per article. In this one, we’re adding another line, but we’re also going to modify the lines we already have because now we’re going to start talking about variables and data types.
The object of this article is to teach you about variables and types and how to manipulate these to create a program that does more than just print “Hello World!”
We have a lot to cover, so get your fingers ready, and let’s get to it.
.
Using Variables
Our current program remains exceptionally simple with just two lines of code:
Console.WriteLine("Hello World!"); Console.ReadLine();
The first line outputs a piece of text to the console, and the second reads a line from the user. But where does this line that we entered end up? Currently, it just drops out into nothingness because we do nothing to retrieve it, so let’s change that immediately.
Change the second line so that it looks like the following:
String input = Console.ReadLine();
What we are doing here is saying that “String input” (whatever that might be) should be assigned to whatever comes out of the method ReadLine
called on the Console
static class.
We use the equal sign to assign values in C# and many similar languages. Whatever is on the left side of the equal sign is assigned the value of whatever is on the right side.
The two words in String input
have different meanings. String
denotes the type of value and input
is the name we use to represent the value. What we are doing here is creating a variable called “input” that has a type of “String”. I will explain types later in this article.
In programming, we use variables to hold data in memory so that we can manipulate it easily. You use this in your daily life, too, without actually calling it a variable. Think, for example, of “Your phone”, which is simply an easy way to remember the name for a particular electronic device that may change over time. Or, consider “the US dollar to Euro exchange rate”. You don’t go around remembering that rate all the time, and it changes rapidly, so you probably find it easier to refer to it by name rather than value.
Variables allow us to refer to any particular piece of data by name instead of value, regardless of what the value is or whether it changes. In our program, the data is whatever the user enters before hitting the Enter
key. The name we give that particular piece of data, in this case, is “input”, but we can call it different things. In fact, there’s a whole range of patterns just for naming variables, and you’ll probably be very confused by it later on in your career.
.
Debugging with Breakpoints
You can try this out now, but before you do, I want to show you a Visual Studio trick called a breakpoint. A breakpoint allows you to stop the execution of a program and see which line of code is executing–it will even allow you to step through the code line by line from that point.
To create a breakpoint, either move your cursor to the first line of your code and hit F9
or click in the margin to the left of the line numbers on the line where you want to set your breakpoint. If done correctly, the whole line should turn red, and you should get a red circle in the margin.
Note that the breakpoint stops execution before the line at which you set it. Also, breakpoints only work when you run your application through a development tool such as Visual Studio, so if you don’t remove your breakpoints before distributing your application, that’s perfectly fine.
Now, hit F5
or that Start button in the menu and watch your application fire up. Right after it does, Visual Studio should pop back up and show you the next line to execute in yellow.
At this point, you can control the execution step by step and observe the results in the console window. To go one step ahead hit F10
in Visual Studio. Bring the console window to the front and observe that your code has now stepped one line ahead, and there’s now “Hello World!” shown in the window as expected.
Note: Programmers often refer to this process of hooking into your code as it is executing as “debugging”. This process is one example of the kind of debugging you might do to verify your code is working as expected.
.
Step forward through your code once more in Visual Studio. Notice that as you do, the console window appears automatically. This event happens because the console needs input from the user when executing the Console.ReadLine()
method.
Enter any bit of text you like and hit Enter
. When you do, Visual Studio will pop back up because now that you’ve provided the input, execution can continue, and we’re still just stepping through the code.
In this Visual Studio window, I’d like to draw your attention to the bottom part of the screen where you should see a tab called “Locals”. If you cannot find it, you can open it by going to the menu and selecting Debug->Windows->Locals or hitting CTRL+D
and then L
.
Once you open the Locals window, you should see that there is a variable there called “input” that has a value set to whatever you entered in the console window. In my case, I entered “Hi there!”.
The Locals tab shows variables that are available to you to use in the current scope. However, before we start manipulating and using this data, it is important to understand the concept of variable types.
.
Variable Types: Static and Dynamic
You see, there are two approaches to what programmers call “typing”, and neither has anything to do with pressing keys on a keyboard. Both approaches have strengths and weaknesses. And no, I’m not going to tell you which is best; you will have plenty of time to determine that yourself, and, perhaps, you may come to understand why some programmers develop an almost fanatical preference for one over the other.
The two approaches are static and dynamic typing. C#, the language you are using in these articles, is a statically typed language, whereas other popular languages like JavaScript are dynamically typed languages. Let me explain the difference.
You noticed earlier that when we created the variable “input”, we decided that it was a String
variable. String
is a term that serves to indicate what type of data can go into the variable. You cannot add incompatible data to a variable because Visual Studio–or technically the compiler that translates your programming code into machine code–will object and refuse to cooperate.
A String
is just a piece of text and can hold almost anything, which makes sense when we’re asking the user to enter any piece of text. However, there’s a potential problem when we want to start working with our data.
Let’s say that we want to ask the user to enter their age and that we want to limit certain functionality if the user is below age 13, for example.
How do you determine whether “Hi there!” is smaller than 13? You cannot, because there’s no way to do arithmetic on a piece of text. “Tomato” plus 45 doesn’t make sense.
A situation such as this one is why statically typed languages have different variable types. We can know whether we can perform arithmetic or other operations on the data before we even send the program to the user.
In statically typed languages, such as C#, VisualBasic, and Java, you must define in advance what a variable can hold, and you cannot create or compile your program without adhering to these rules. In return, you are guaranteed that you won’t be comparing Apples to 3.42 or trying to figure out whether it is legal to sell alcohol to a person who is “none of your business” years old.
In dynamically typed languages, you get no such guarantees. Instead, you just work with variables that can hold any type of data. An example of dynamically typed languages is JavaScript. In JavaScript, programmers need to check that the data they get is of an expected value because their code may crash if they try to add or compare “yes” to 18.
Note: You can actually add “yes” to 18 in most languages, depending on how you do it. You will most likely end up with “yes18”, though, which probably isn’t what you expect.
.
In statically typed languages, you will also find that all methods return a specific type of data–or, in some cases, nothing at all. For example, the Console.ReadLine()
method returns a string value, so it works great to set our String input
variable to the output from that method just like we did.
However, what will happen if we want to ask the user to pick a number between 1 and 10 because we want to use that number for something later? Let’s start building a simple game and look, shall we?
.
A Guessing Game Program
The game we’re going to build is a guessing game. We pick a secret number between 1 and 10, and then we ask the user to guess which number it is. We’ll make this game more advanced later, so for now, the user just gets one guess and thus has a 10% chance of getting it right. In fact, we’re not even going to test whether they are correct in this article because doing so would involve conditions and flow control, which are concepts we’re not going to learn yet.
First, the variable type for a number that does not have decimals is called an integer, or int
for short. An int
can hold very large numbers, usually limited by the CPU architecture type, with a 32-bit CPU holding integers up to around 4.4 billion. Beyond that, we can use other variable types. However, for our simple examples, a regular int
will work well.
For all types of variables, we can assign simple values directly. For example:
int value = 10; string name = “Frank”;
We can also perform operations on variables, as long as they “make sense”. For example, you can add two integer values together.
int value1 = 10; int value2 = 3; int value3 = value1+value2;
The integer stored in the variable “value3” is 13 after the portion of code containing these lines runs through this point.
We can also assign values from the return value of methods. Let’s try just assigning the result from the Console.ReadLine()
method into an int
, shall we? If you haven’t already, stop the execution of your program. We are now going to update our two lines of code as such:
Console.WriteLine("Guess a number between 1 and 10:"); int input = Console.ReadLine();
When you do, you will get a case of the red squigglies (as shown below in Figure 5) and an error message in the Error list stating “Cannot implicitly convert type ‘string’ to ‘int'”.
We get this error because the value that comes out of the Console.ReadLine()
is a string, and the compiler cannot guarantee that it can convert what a user may enter into a number. A user might enter “NO!” for example, and there is no way to turn that input into a number.
There are, of course, ways around this problem. We can force the compiler to accept whatever comes in as being of a specific type. In fact, we can do this with any types. It is a process called casting.
When we cast variable types, the compiler will do its best to convert from one variable type to another. This cast may, for example, work if you have a decimal number and want an integer.
decimal decimalvalue = 3.14M; int integervalue = decimalvalue;
The first line assigns the value 3.14 to the decimal
variable called decimalvalue
. The second line tries to assign that decimal value to an integer.
Note: The M is there simply as a hint to the compiler that we are creating a decimal value because, to add even more confusion to this point, there are several types of
decimal
values, including double precision and floating point values. While useful to know, none of these points are things you’ll need to worry about in this article.
.
If you enter these lines in Visual Studio, you’ll notice that even now, we get a case of squigglies because a decimal
value doesn’t fit into an int
value. If we tried, we would lose the .14 and be left with just 3 as the value of integervalue
.
This behavior may be exactly what we want. In this case, we can cast the decimal
value to an int
, effectively forcing the compiler to accept the explicit conversion of a decimal value to an integer value. We do so by preceding the value with the type we want in parentheses. Compare these lines of code to the ones from above.
decimal decimalvalue = 3.14M; int integervalue = (int)decimalvalue;
Now our Visual Studio squigglies will go away, and the compiler is happy. We’re losing some details in the numbers, but you might be confident that this is what you want.
In C#, the compiler will demand that you cast values if there is a chance of data loss, such as is the case if you go from a decimal to an integer value. However, it will gladly accept a compatible conversion when there is no chance of data loss. If you tried to assign an int
value to a decimal
type, for example, you’d get no quarrel from the compiler.
So far, though, we’re not really getting close to a solution to our problem. We can try to cast the string value coming from Console.ReadLine()
into an int
, but the compiler will complain that it cannot convert a string value to an integer automatically (as shown below in Figure 6) because there is no way to guarantee in advance that it is possible to turn what comes from the user into a number.
Fear not, because there’s a better way to solve this! The solution is using a static method to parse the string value into an integer, and it’s located right in the int
type itself. As such, we can call on the int.Parse
method, send it whatever comes in from the Console.ReadLine()
method, and get an integer back out.
So, let’s update your program code to first prompt the user to enter the data, then retrieve the data into a string
variable called “text”, and finally to parse “text” into an integer.
Console.WriteLine("Guess a number between 1 and 10:"); string text = Console.ReadLine(); int input = int.Parse(text);
Once you do, all of your squigglies should go away, and your program should execute as expected. Feel free to set a breakpoint after the last line to stop execution and inspect your variables. See what happens when you enter a number during the execution.
You’ll see that “input” now shows that it has a value of 3 whereas “text”, in my case, has a value of “3” (notice the double quotes; double quotes signify a string value).
But what happens if we enter something other than a number? Well, if you enter something like “Hello” instead of a number, the program will crash. In Visual Studio, the execution will stop and tell you about an exception, as shown below in Figure 8.
As programmers, we don’t want our software to crash, so we need to handle this bug. However, we’re going to leave that for the next article because it involves manipulating the flow of the program, and we’ve already covered quite a bit to get to this point.
.
Variables, Types, and Manipulating Data Wrap-Up
For now, it’s time to wrap up this third article, and despite writing only one more line of code, we have covered a lot of new material. Don’t worry, when I started learning this many years ago, there were many confusing aspects for me, too.
In this article, we have covered the concept of variables and looked at data types and when and why data types are important. You’ve learned about how to create variables and even how to turn data from one type into another through casting. You have learned about step-by-step debugging, breakpoints, and how to inspect available variables in Visual Studio.
You should also note that the things you have learned now are very common across languages and platforms, and I have taken care to introduce and explain concepts that vary, such as static versus dynamic typing.
In the next article, we will look at flow control so that you can learn how to control the execution of your program and check various conditions to determine what the program should do next.
How-To Series
This is part 3 of a 5 part series for Introduction To Programming