Common Concepts of Programming Part 4 – Conditions

Introduction

In this segment of the introduction to programming concepts, you’ll learn about the basics of some additional common programming elements by adding in some conditions. When this section is done, you’ll be ready to start discussing more significant programming concepts, and will be able to handle the solid fundamental lessons, building some simple programs that build up core skills.

Hello, World – enhanced

Up to this point, we’ve only worked in a limited fashion with actual code; it was very important to discuss key concepts before we dove right in. Now that we have looked at concepts like data types, we’re ready to expand the function of our HelloWorld program. Rather than modifying the existing code, however, we’re going to add another project into the solution we started, and use that to build a slightly more advanced version of the original application.

Open up Visual Studio 2019. You’ll end up at the launch menu, where you should see the HelloWorld.sln solution we made in our prior lesson. Go ahead and click on that entry to get started.

Our existing application should open up with the source code for the HelloWorld file.

We’re going to create a second project within the solution, and use that to make our expanded program. From the File menu in the upper left hand corner of the window, select New > Project. Since we have already created a Console App (.NET Framework) before, it will show up under “Recent project teamplates”. Click it once to highlight it, and click the “Next” button.

We are presented with the “Configure your new project” screen.

For Project name, enter HelloAdvancedWorld. Change “Solution” from “Create new solution” to “Add to solution”. The location should default to the fold containing the existing HelloWorld solution. The solution name field will be grayed out, but will say “HelloWorld”. Finally, make sure you’re set to the latest Framework. For my system, this is .NET Framework 4.7.2. Click on the “Create” button. A quick note, it is also possible to add projects in using the “Solution Explorer” panel on the right side of the Visual Studio Screen. You simply right click on the solution name, scroll down to “add” and click on “New project”. The process will be nearly the same, though the “Configure your new project” window will look like the one below, instead of the one we saw above.

You should now notice a few changes. First, in the “Solution Explorer” panel, we’ll see our new project, “HelloAdvancedWorld”, along with the existing “HelloWorld”. Each project will have a few elements underneath: Properties, References, App.config and Program.cs. Now at first, it might seem odd that there are two entries for each of these, but realize that each project has it’s own folder in the solution (both in the application and on your hard drive), and the elements of each project are independent of each other.

Additionally, the main toolbar up above now has an additional drop down menu in it. After “Debug” and “Any CPU”, we should now see “HelloWorld”, followed by the play arrow / Start button.

If you click on that drop-down, you’ll see our other project, HelloAdvancedWorld, as an option.

If you change to our new project, you’ll be able to run that project instead of the original one. And you can always change back if you need to. Also note; if you change which project is the Active one in this menu, the title of that project will take on a bold font face in the Solution Explorer.

In the new Project.cs, replace the existing code with this:

using System;

namespace HelloAdvancedWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, world!");
            Console.ReadKey();
        }
    }
}

This is the same as the code from the original project, with two small differences. First, we’ve removed all of the using statements we don’t need. Second, you should see that the namespace on this version is HelloAdvancedWorld. If you recall in the Getting Stated with Visual Studio 2019 article, I mentioned that a namespace is a sort of container for code. The common practice in C sharp and many other C-styles languages is to have a namespace that matches the project name. A namespace allows you to have multiple blocks of code in there which are then all part of the same “package”. The advantage of this is, if you use a meaningful naming convention for your namespace values, if you have a component that has a similar name to a component from another project or library, the C sharp compiler will understand that you mean this specific version; it’s a way of clarifying which blocks of code you are referring to when names of those code blocks could overlap.

For now, HelloWorld and HelloWorldAdvanced are sufficient. In later projects, we’ll look at better ways to organize using the namespace approach, and you’ll be able to see how it benefits you to have unique namespace values.

If we run this program, nothing new is going to happen yet, because it matches the original HelloWorld application exactly. It’s time to change that a bit.

Let’s replace lines 9 and 10 with some new code:

Console.Write("What is your name? ");
string myName = Console.ReadLine();

Console.WriteLine("Hello, " + myName + "!");
Console.ReadKey();

Make sure you switched that drop-down to “HelloWorldAdvanced”, then go ahead and run the project.

You should be prompted for your name. Go ahead and type in your first name, then hit enter.

It might not seem like much, but you actually did accomplish something important. You received input from the user, and you used it to display back out a message. It’s an important first step in building something much larger. Go ahead and exit the application by pressing any key, or closing that window.

So what did we do? Let’s look at the code. I’m only going to focus on the 4 critical lines, but here’s the total code we have.

using System;

namespace HelloAdvancedWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("What is your name? ");
            string myName = Console.ReadLine();

            Console.WriteLine("Hello, " + myName + "!");
            Console.ReadKey();
        }
    }
}

Line 9 – We’re writing out the message “What is your name? “. The extra space character at the end is to allow us to make the input look a bit neater. Note how this line is “Console.Write” instead of “Console.WriteLine”. I mentioned in a prior article that WriteLine automatically adds a carriage return, or a new line character, at the end of the display process. Write does not add on the character. By using the “Write” command, we can then read in the input directly after the display; it’s a nice way of setting up an input form. It doesn’t affect anything, logically, but it’s nice to know we have that sort of option.

Line 10 – We start out by declaring a variable named myName, with a type of “string”. This means we’re creating a placeholder and assigning it an easy to remember name. Next, the = sign indicates that we’re going to store something into that variable. In the simplest of terms, we’ll need to store in a value that is of the string type. Remember that numbers can be included in a string, but if you use them, they’re being used for non-calculation functions; in other words, they hold no significant mathematical value, they’re just more character that we’re going to display.

Line 10 finished off with Console.ReadLine(), followed by a semi-colon. The Console object, part of our System library, allows for both input and output to the command line / console window. In this case, Console.ReadLine() indicates that the program will continue reading in characters until it encounters a carriage return / new line character – indication that you have pressed your enter key. So the entirety of this line reads as: create a new string variable, call it, myName, and use it to hold the value that the Console reads in, up until the point that the user presses the enter key. It might sound like a lot, but the syntax actually is pretty simply if you stop to think about it.

Line 11 is just a blank line, and remember that the computer will just ignore those blank lines and spaces. It’s convenient to us for organizing code, but the computer doesn’t care if you’re not ordering it to do anything there; it just moves to the next instruction.

Line 12 – Now that we have a value for “myName”, we are going to print it out as part of a message. We indicate that we are going to perform a Write to the Console. We’ve used Console.WriteLine before, so let’s take a look at the information that we’re sending in between the parenthesis. “Hello, ” + myName + “!” turns into “Hello, Greg!” if we type in my name when prompted. The data in the parenthesis is a string; but it is one that is concatenating a variable into the rest of a hard-coded string; in other words, we’re using the actual text “Hello, ” and concatenating (or adding on) the value of the myName variable; then we add on another actual text string, the final exclamation point. When working with string, you can concatenate multiple string together by using a + and either a literal string encased in double quotes, or a variable that can output data as a string. It is possible to output actual numeric variables as string as well. There are other ways of printing out the data, using essentially a substitution approach. I’ll cover that in just a little bit.

Line 13 – This should also be familiar from the original HelloWorld application. This command is essentially pausing for more input; the difference is that this time, the input will be any single character. Whatever we press will qualify as a read key, and the program will move to the next instruction. However, given that there aren’t any more instructions, the program will simply end. If we did not include this line, the prior line printing our message would execute and the program would exit immediately. And in all likelihood, no one would have been able to read the message fast enough to know what it said. So this is useful to make sure you can see everything that appears on the screen, and not quit until you’re really ready to do so.

So much code, so little action

It might seem like we had to go through a lot to make that little bit happen; and in some ways, that is very true. However, the fact is that we’ve learned how to process both input AND output, and that covers a big chunk of what we do with programming. Remember that a computer is primarily a device to speed up mundane, repetitious processes, or to handle complex calculations rapidly without error. So being able to read and write output is a major part of the process; having the ability to process data would be of little use if you could never set up what to calculate, or never see the results of those calculations.

And the truth is, as we build more sophisticated programs, some (or much) of the code will be repeatable and reusable, so while a simple program like Hello, World seems like a lot of work for a very minimal payoff, remember that it’s really serving as a foundation for building something more meaningful. Boiling water isn’t exactly exciting or special, but if you don’t learn how to boil water properly, there are a lot of dishes you’d never be able to cook properly, if at all.

Success doesn’t mean having an answer…

So what do we do if a person is prompted for data and just hits enter? Well, under our current program, the output would be: “Hello, “. Well, that’s not really correct, is it? They could put in any sort of value and it would at least seem plausibly correct. But what about if they leave it blank? Maybe we should do something different. Let’s use a condition to handle that.

We’re going to modify our code a bit. Replace the code on line 12 with the following:

if (myName == string.Empty)
{
    Console.WriteLine("Hello.  You didn't tell me your name!");
}
else
{
    Console.WriteLine("Hello, " + myName + "!");
}

Now, run your program again, and when prompted for your name, just press enter.

Now, by not putting in any value, we get a different message. Let’s break down the new code.

Line 12 – This is a test for a condition; commonly, we can use the key word “if” to indicate that we need to test one or more conditions for truth – hence the name “if statement”. If statements are one type of conditional test; we check to see if one or more conditions evaluates to true, and if they do, we will execute the code nested in curly braces following the “if” line.

Now, some languages will let you state “if” followed immediately by the condition. Most proper languages, however, require you to put your test inside at least a single set of parenthesis. So in this case, we’ll check to see if myName is equal to an empty string. “if (myName == string.Empty)” is literally able to translate into “if the value of myName is equal to an empty string”. The double equal sign is critical here. Remember from earlier, we used a single equal sign to set myName to the value of the Console.ReadLine. If you used a single equal symbol during the condition test, you’d be trying to say “if I store an empty string into myName”. First, this would mean that you’re overwriting the value that was already stored in your variable; second, it would conceivably mean that any time you hit this logical test, the result would always be true – you’d always be able to store the variable. Some languages allow this sort of syntax; C Sharp, however, will thrown an error, because it is expecting the conditions in the parenthesis to be something it can evaluate. Storing a variable is an action, not an evaluation, so the compiler won’t even let you do this. A double equal (==) always indicates comparison. The string.Empty portion of our condition actually is a property that translates into a string with no characters. This means that there is technically a string, it’s just that it has no significance. It is possible to have a string variable that is set to nothing (also called null) which has a different meaning. Null values are something we will discuss another time. For now, we’ll move on.

Line 13 is an opening curly brace that is matched by the closing brace on line 15. And the line in between is what will happen when we have met the condition of an empty string.

Line 16 – Else is the alternative, default condition that is assumed if the conditional check is not met. It is a ways of saying “if any other test we did did not succeed, we’ll do this instead”. The else statement must always follow the closing curly brace of a prior “if” condition. Then the bracketed code following it will execute instead of the initial conditional block.

There is a problem with this code, however. If you run the application, a user might decide to hit the space bar instead, and then hit enter. This is a problem; we’re only alerting them that they didn’t enter a name if they have a string that has no characters. We haven’t accounted for a string that has characters that are all blank spaces.

Go ahead and run the application and you’ll see what I mean.

Well, that isn’t any good. What we need to do is test to make sure they’re not just entering a string consisting of blank characters. But there is a problem; that string could be up to 2 billion or more characters in length; and if we want to check for a string with that many possible spaces, it means we’d need to test each case individually. That means having to check for 2 billion possibilities!

Fortunately, we don’t need to do something crazy like that. Instead, we’re going to modify line 12 from this:

if (myName == string.Empty)

to this:

if (myName.Trim() == string.Empty)

Trim() is a method that exists on all string variables, and on all methods or functions that generate a string as a return value. The Trim() method in it’s basic form removes any blank characters before the first non-blank character, and after the last non-blank character. So for example, if you had a string with a value of: ” Test “, the Trim() method would turn that into “Test”, without any spaces before or after the first and last T. By applying that method to our variable, we will only print our hello message if we have a value in myName that consists of visible characters.

Comment your concerns

Let’s be honest; you’re probably not going to carry this website around with you all the time – so you won’t necessarily have my documents ready to explain what we did here handy immediately. If only there was a way to leave a note for ourselves in our programs that explains what we did, but will not actually be treated like instructions for the program itself. Well of course, we can do that!

The notes we want to leave for ourselves are called “comments”. And every language has them in some form. In most C-styles languages, comments can be made in one of two ways. The first, is to put to forward slashes next to each other, like so:

//this is a single line comment

The single line comment starts the moment you have the two slashes, and continues on until the end of that line. The nice thing about this is that you can put them after an actual programming command, like so.

int i = 0; // Initialize the variable to 0

The second option is to use /* and then use */ at the end of the comment. This allows for multiple-line comments. This way, if you have a longer explanation, you can prevent a need to scroll sideways a long distance to read the whole message.

/* This is an example of a multiple-line comment.  It makes it
   very easy to read this comment if you don't need to scroll sideways
   to read all of it.  This is a great way to leave detailed explanations
   in your code.  That's a very good habit to get into. */

All of those lines will be ignored by the compiler now. There is one other great use of the commenting system – it’s good for temporarily disabling a block of code for testing, or to disable a block of code if you’re replacing it with a new block of code, so you can compare what was there previously. Like so:

   /* if (i == 0)
   {
       Console.Write(" Print out a value ");
   } */

   if (i < 1) // Changed to this to handle negative values - less than 0
   {
        Console.Write(" Print out a value ");
   }

Now that you know this, I will give you a piece of advice – DO NOT HESITATE TO LEAVE YOURSELF COMMENTS. Trust me when I say, commenting your code, regardless of the language, regardless of the platform, is an invaluable capability. Never feel that it’s ridiculous to leave yourself a lot of notes. The more effort you put into leaving detailed, meaningful notes, the less of a strain it is later to remember what you did, and why.

Nesting Code

We’ve already discussed nesting code to some extent, using the curly braces { and } to block out code. Let’s take that a step further by getting some additional information from the user and nesting our code to process it. First, comment out the “if… else” block on lines 12 – 19. You can either do a series of single line comments, or use the multi-line comment approach by placing /* at the start of the block and */ at the end of the block.

//if (myName.Trim() == string.Empty)
//{
//    Console.WriteLine("Hello.  You didn't tell me your name!");
//}
//else
//{
//    Console.WriteLine("Hello, " + myName + "!");
//}
/*if (myName.Trim() == string.Empty)
{
    Console.WriteLine("Hello.  You didn't tell me your name!");
}
else
{
    Console.WriteLine("Hello, " + myName + "!");
}*/

One neat trick to make you aware of with Visual Studio is that you can select a bunch of lines, press the control key (Ctrl) and then press the k key, then release and press the c key. This will turn all of the selected lines into comments. By using the Ctrl key, pressing k and then u, you can un-comment those same lines. It’s a handy shortcut to know.

OK. Let’s add a comment in to keep track of out code. On line 10, before the creation of our variable, hit your enter key, so we can put in a new line. Then go back to the new, blank line, and type in a comment that says “Get variable for name”. That should leave your variable creation on line 11. Create an extra line on 12 so we can space out the next block of code. Then add in a console write for “What is your gender (m/f) ?” Go to the next line and leave a comment that says “Get variable for gender”. Finally, add in a line to create another variable of type string, call it myGender, and set it equal to “Console.ReadLine();” When you’re done, the new block of code should look like this.

Console.Write("What is your name? ");
//Get variable for name
string myName = Console.ReadLine();

Console.Write("What is your gender? ");
//Get variable for gender
string myGender = Console.ReadLine();

Next, let’s write some more code to handle using this input. First, we’ll determine the output based on the gender. This will introduce us to a few concepts. We’re going to do a test for multiple conditions. We want to see if the gender is equal to an ‘m’, an ‘f’, or any other value; we will then print out an appropriate message. Here’s the code we can plug in to do this.

//Check if myGender is set to an f or an m
if (myGender.Trim() == "f" || myGender.Trim() == "m")
{
    //Start printing the message for a specified gender
    Console.Write("You specified a gender of: ");
    
    //If gender is f
    if (myGender.Trim() == "f")
    {
        //finish print - female
        Console.WriteLine("female.");
    }
    //If gender is m
    else
    {
        //finish print - male
        Console.WriteLine("male.");
    }
}
//If gender is not f or m
else
{
    //Print alternative message
    Console.WriteLine("You specified a gender of other or did not specify a gender.");
}

Phew! That’s a lot of code, isn’t it? This code should follow the line where we read in the myGender variable. I put in an extra blank line just to keep things a bit easier to read. Go ahead and run the application 3 times. For each run, enter a different value for the Gender question. Try m, f and o. If you want, you can try any other value for the 3rd test. You can even leave it blank.

You should be able to get an answer of male, female and our “other” message. Now, try running it one more time, and this time, make your gender a capital M or capital F. You might see something you don’t want.

We put in M. Why didn’t we get the male message? Our condition was case sensitive. We have a few ways we can deal with this. The first is to do multiple tests, the second will allow us to streamline our coding. But first, let’s talk about our “if” statements.

When we did our first test, we said:

if (myGender.Trim() == "f" || myGender.Trim() == "m")

This translates into: if we trim the value of myGender of blank space and get a value of f, or if we trim the value of myGender of blank spaces and we get a value of m, we’re going to proceed into this part of our logic. The alternative condition(s) will be met about 18 lines later, with the line that simply states “else”. The double pipe characters || indicates a logical “or” statement. On most models of keyboard, the pipe characters are found on the same key as the backslash key \, which is usually near the backspace key. A pair of these characters will always be a logical OR. If you wanted to say AND, you’d use two ampersands instead &&.

So here we’ll checking for an f or m, and a failure to match those values will jump down to the else statement. Inside, we print out the star of our message about the gender. Note that I used the Console.Write and NOT Console.WriteLine – this way we can print the actual answer on the same line. This isn’t necessary, it’s just an aesthetic choice. The only problem here is, a user might put in a capital M or F… and though it’s the same letter, the fact that it’s capital means that our code will not execute.

One way we could do this is to test for those two additional conditions. First, we could modify our initial test to say this:

if (myGender.Trim() == "f" || myGender.Trim() == "F" || myGender.Trim() == "m" || myGender.Trim() == "M")

This works, and if you do that, you’ll have part of the solution we need. Of course, we’ll also need to modify the blocks that finish the print, specifically the condition that tests for female. Our else will handle either option for male. But there is an easier way.

C sharp allow for operations that are “chainable”. In other words, we can have the results of one operation passed to another operation on the same data object. And with data types like strings, there are actually a number of additional methods that we can chain on. In this case, we can use a method called “Upper” or “Lower” to transform all the characters in the string to one case, and then we can compare against just that single case. So we could convert our logic to this, which will be shorter, and yet perform the same exact operation.

if (myGender.Trim().Upper() == "F" || myGender.Trim().Upper() == "M")

We could then do the exact same thing for the further test for printing the female message. Again, we don’t need to do anything for the male message, because we’re not testing an individual condition.

Now, that we have that part done, we can expand our “alternative” answers. What if we wanted to differentiate between non-specified and other? Enter the next step of conditions… else if.

Else if let’s us chain a series of conditional tests, one sequence after another. In this case, we can modify our block to work like this (please note, I am skipping the internal content for the male and female option to focus on the else if portion).

//Check if myGender is set to an f or an m
if (myGender.Trim().ToUpper() == "F" || myGender.Trim().ToUpper() == "M")
{
    //Our logic to clarify M and F still goes in here.
    //I omitted it to keep this shorter.
}
//If gender is not f or m, but was specified
else if (myGender.Trim().ToUpper() != "F" && myGender.Trim().ToUpper() != "M")
{
    //Print alternative message
    Console.WriteLine("You specified a gender of other.");
}
//If gender is not f or m or other value
else
{
    //Print unspecified message message
    Console.WriteLine("You did not specify a gender.");
}

If you run a series of tests, you’ll see our logic split out more, and the answers are a bit more detailed when it comes to the other / no answer options. Likewise, a capital M or F will yield the correct response.

Another way we could write this code would be to split out the Male and Female options, like so:

//Check if myGender is set to an F
if (myGender.Trim().ToUpper() == "F")
{
    //Write female
    Console.Write("You specified a gender of: female");
}
//Check if myGender is set to an M
else if (myGender.Trim().ToUpper() != "M")
{
    //Write female
    Console.Write("You specified a gender of: male");
}
//If gender is not f or m, but was specified
else if (myGender.Trim().ToUpper() != "F" && myGender.Trim().ToUpper() != "M")
{
    //Print alternative message
    Console.WriteLine("You specified a gender of other.");
}
//If gender is not f or m or other value
else
{
    //Print unspecified message message
    Console.WriteLine("You did not specify a gender.");
}

We could also switch the “non-specified message” and the “other” message and simplify the cases as well.

//Check if myGender is set to an F
if (myGender.Trim().ToUpper() == "F")
{
    //Write female
    Console.Write("You specified a gender of: female");
}
//Check if myGender is set to an M
else if (myGender.Trim().ToUpper() != "M")
{
    //Write female
    Console.Write("You specified a gender of: male");
}
//If gender is not specified
else if (myGender.Trim() == string.Empty)
{
    //Print unspecified message
    Console.WriteLine("You did not specify a gender.");
}
//If gender is populated, but not recognized
else
{
    //Print alternative message
    Console.WriteLine("You specified a gender of other.");
}

There is even an option so we don’t need to use the double equal == sign for comparison. There is a chainable method on string objects called “equals” which take in the parameter of a string, or can take the string.Empty property.

//Check if myGender is set to an F
if (myGender.Trim().ToUpper().Equals("F"))
{
    //Write female
    Console.Write("You specified a gender of: female");
}
//Check if myGender is set to an M
else if (myGender.Trim().ToUpper().Equals("M"))
{
    //Write female
    Console.Write("You specified a gender of: male");
}
//If gender is not specified
else if (myGender.Trim().Equals(string.Empty))
{
    //Print unspecified message
    Console.WriteLine("You did not specify a gender.");
}
//If gender is populated, but not recognized
else
{
    //Print alternative message
    Console.WriteLine("You specified a gender of other.");
}

Why are there so many alternative ways to do this?

At this point, you’re probably wondering why all these alternative methods exist for accomplishing essentially the same thing? The answer is that more elaborate conditions to test for are more optimally achieved through the use of alternate tests. Much like you can often describe the route to get between two different places using a number of different streets and routes, you can use different combinations of logic to achieve a desired outcome.

Which is the right way to do it? The answer may annoy you at first, but it’s the one that works. What I mean is, the approach you take needs to be the one that accomplishes what you want, but your best bet is to lay out the conditions on paper, and try to keep the rules as simple as you can. When you do that, you’ll fine that the conditional logic will be easier to handle.

Frankly, that last sample of logic is probably the simplest looking of all the ways I’ve shown you. It kept each condition to its own block, and minimized the number of cases to test for. This might not be the best way to do it in all cases, but given that it’s simple to walk through, this approach works just fine here.

Go ahead and add back in the responses to the name, however you’d like to. You can just uncomment the code we had before, though if you’d like to specify more details, or to play around with the logic some more, go ahead! This will help you to get a better handle on playing with logical conditions.

Our final version of this file will look like this:

using System;

namespace HelloAdvancedWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("What is your name? ");
            //Get variable for name
            string myName = Console.ReadLine();

            Console.Write("What is your gender? ");
            //Get variable for gender
            string myGender = Console.ReadLine();

            //Check if myGender is set to an F
            if (myGender.Trim().ToUpper().Equals("F"))
            {
                //Write female
                Console.Write("You specified a gender of: female");
            }
            //Check if myGender is set to an M
            else if (myGender.Trim().ToUpper().Equals("M"))
            {
                //Write female
                Console.Write("You specified a gender of: male");
            }
            //If gender is not specified
            else if (myGender.Trim().Equals(string.Empty))
            {
                //Print unspecified message
                Console.WriteLine("You did not specify a gender.");
            }
            //If gender is populated, but not recognized
            else
            {
                //Print alternative message
                Console.WriteLine("You specified a gender of other.");
            }

            //If no name was specified
            if (myName.Trim() == string.Empty)
            {
                //Tell us that we didn't remember the name
                Console.WriteLine("Hello.  You didn't tell me your name!");
            }
            //Otherwise
            else
            {
                //Say hello to the name.
                Console.WriteLine("Hello, " + myName + "!");
            }
            Console.ReadKey();
        }
    }
}

It’s a lot of code, and it doesn’t go too much; but we’re actually accomplishing a few things here that make for a good demonstration. At this stage, we have a good starting point for our logical demonstration. We understand a bit about multiple conditions, we’ve looked at how we can simplify that process, and we’ve learned about how we can have multiple cases with a fair amount of ease (using the if…else if…else approach).

Conclusion

So far we’ve expanded our functionality from a very simple hello application that just prints a message into one that processes some input and churns out responses based on what we typed in. Our next step will be to learn about another step of programming; namely loops and repetition. That will be another long lesson, but it’s another major step towards being able to produce more expansive projects.