Gigi Labs

Please follow Gigi Labs for the latest articles.
Showing posts with label characters. Show all posts
Showing posts with label characters. Show all posts

Sunday, May 12, 2013

C# Basics: Morse Code Converter Using Dictionaries

Hi all! :)

Today's article is an easy one. We're going to learn to use dictionaries, and use them to make a program that converts text into the Morse Code equivalent.

Just for a change, today I'm going to use Visual Studio 2010 instead of SharpDevelop. If you want to try it, grab an express edition from Microsoft's website. Otherwise, you can manage just as well with SharpDevelop. Let's start off by creating a new console application. In Visual Studio, you can click on the "New Project..." link below the VS logo, or else from the menu, File -> New -> Project...:


Under Visual C# -> Windows, select "Console Application". As with SharpDevelop, specify a name for the project and where to put it. Note: I'm using the Ultimate edition, so your Express edition will be a little different (e.g. less project types).


The sample code given by Visual Studio is a bit different from that of SharpDevelop:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CsMorse
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}


In particular, there's nothing in Main(). It doesn't matter. However, if you're using SharpDevelop, you're going to need the using System.Collections.Generic; so make sure you add it.

So, now we're going to make a little program based on the Morse Code. In case you don't know, the Morse Code is something that Chuck Norris used to communicate with the aliens who built the pyramids in Egypt. Obviously, he was the one telling them how to construct them.

As you can see from the Wikipedia link in the previous paragraph, each letter of the alphabet has a corresponding representation in Morse as a series of dots and dashes. In order to speed up transmissions, more common characters (e.g. 'E') are much shorter than others.

In C#, we can use a dictionary to map keys (e.g. 'L') to values (e.g. ".-.."). In other programming languages, dictionaries are sometimes called hash tables or maps or associative arrays. The following is an example of a dictionary mapping the first two letters of the alphabet to their Morse equivalents:

            Dictionary<char, String> morse = new Dictionary<char, String>();
            morse.Add('A', ".-");
            morse.Add('B', "-...");

            Console.WriteLine(morse['A']);
            Console.WriteLine(morse['B']);

            Console.WriteLine("Press any key...");
            Console.ReadKey(false);

First, we are declaring a dictionary. A dictionary is a generic type, so we need to tell in the <> part which data types we are storing. In this case, we have a char key and a String value. We can then add various items, supplying the key and value to the Add() method. Finally, we get values just like we would access an array: using the [] syntax. Just that dictionaries aren't restricted to using integers as keys; you can use any data type you like. Note: you'll know from the previous article, "The ASCII Table (C#)", that a character can be directly converted to an integer. Dictionaries work just as well if you use other data types, such as Strings.

Here is the output:


If you try to access a key that doesn't exist, such as morse['C'], you'll get a KeyNotFoundException. You can check whether a key exists using ContainsKey():

            if (morse.ContainsKey('C'))
                Console.WriteLine(morse['C']);

OK. Before we build our Morse converter, you should know that there are several ways of populating a dictionary. One is the Add() method we have seen above. Another is to assign values directly:

            morse['A'] = ".-";
            morse['B'] = "-...";

You can also use collection initialiser syntax to set several values at once:

            Dictionary<char, String> morse = new Dictionary<char, String>()
            {
                {'A' , ".-"},
                {'B' , "-..."}
            };

Since we only need to set the Morse mapping once, I'm going to use this method. Don't forget the semicolon at the end! Replace your current code with the following:

            Dictionary<char, String> morse = new Dictionary<char, String>()
            {
                {'A' , ".-"},
                {'B' , "-..."},
                {'C' , "-.-."},
                {'D' , "-.."},
                {'E' , "."},
                {'F' , "..-."},
                {'G' , "--."},
                {'H' , "...."},
                {'I' , ".."},
                {'J' , ".---"},
                {'K' , "-.-"},
                {'L' , ".-.."},
                {'M' , "--"},
                {'N' , "-."},
                {'O' , "---"},
                {'P' , ".--."},
                {'Q' , "--.-"},
                {'R' , ".-."},
                {'S' , "..."},
                {'T' , "-"},
                {'U' , "..-"},
                {'V' , "...-"},
                {'W' , ".--"},
                {'X' , "-..-"},
                {'Y' , "-.--"},
                {'Z' , "--.."},
                {'0' , "-----"},
                {'1' , ".----"},
                {'2' , "..---"},
                {'3' , "...--"},
                {'4' , "....-"},
                {'5' , "....."},
                {'6' , "-...."},
                {'7' , "--..."},
                {'8' , "---.."},
                {'9' , "----."},
            };

           

            Console.WriteLine("Press any key...");
            Console.ReadKey(false);


In the empty space between the dictionary and the Console.WriteLine(), we can now accept user input and convert it to Morse:

            Console.WriteLine("Write something:");
            String input = Console.ReadLine();
            input = input.ToUpper();

            for (int i = 0; i < input.Length; i++)
            {
                if (i > 0)
                    Console.Write('/');

                char c = input[i];
                if (morse.ContainsKey(c))
                    Console.Write(morse[c]);
            }

            Console.WriteLine();

Here, the user writes something and it is stored in the input variable. We then convert this to uppercase because the keys in our dictionary are uppercase. Then we loop over each character in the input String, and write its Morse equivalent if it exists. We separate different characters in the Morse output by a forward slash (/). Here's the output:


Awesome! :) In this article we used Visual Studio to create a program that converts alphanumeric text into the Morse-encoded equivalent. In the process, we learned to use dictionaries, and also revisited things like for loops and String methods.

Watch this space for more practical articles! In particular, after a few more articles, we'll be doing some network programming. Some great stuff is coming your way. :)

Saturday, May 11, 2013

The ASCII Table (C#)

Hi! :)

In previous articles, we have seen how to create a simple game based within the console window (Part 1Part 2). In this article we're going to find out what ASCII is about, and how we can draw some basic shapes  using the characters available in the console. Don't mind the length of this article... there's a really long chunk of code that you can just copy and paste. Read on! :)

So far we have displayed strings in the console window many times. However, a computer does not know anything about text; it can only work with numbers. So when you do something like this:

             Console.WriteLine("Hello world!");

...each character maps to a particular number (e.g. the 'H' is 72, the 'e' is 101, and so on). ASCII is a standard defining a set of basic characters such as these. Check out an ASCII Table to see how the characters are organised.

The standard ASCII is a set of 128 characters, the first 32 and last 1 of which are control characters such as the Carriage Return (13) and Line Feed (10), which together make a newline. The remaining characters are the text characters that we are used to.

There is also an extended set of another 128 ASCII characters. These consist of some non-English characters as well as some line and block characters that can be used to draw something like the screenshot towards the beginning of my article "C#: ASCII Art Game (Part 1)".

We can write all the 256 ASCII characters to the console window using a simple loop. Start a new SharpDevelop project, and use the following code:

            int i = 0;
            while (i < 256)
            {
                Console.Write(Convert.ToChar(i));
                i++;
            }

All we do is run this loop from 0 to 255 and write the corresponding ASCII character. We use the Convert class that is familiar from my article "C# Basics: Fun with Integers", but this time we convert from an integer to a character.

This is easy, but there's a better way to do this. Replace the above code with this:

            for (int i = 0; i < 255; i++)
            {
                Console.Write((char) i);
            }

This for loop does the same as above, but is much more compact. Initialising i, incrementing it, and the loop condition are all contained within the brackets of the for statement. The braces contain the statements to carry out with each iteration. If you have just one statement, as in this case, you may omit the curly brackets.

Also, you'll notice that I changed how we convert between integer and character. This method is called type casting - you just put the desired type (char in this case) beside the variable to be converted. The end result is still the same as with using Convert.ToChar().

When you run this code (F5), you'll hear a beep and see this:


Some things will seem weird here. There are what appear to be smiley faces, an uncalled-for newline, a whole bunch of question marks, and lots of strange characters after that, not to mention the beep.

The smiley faces, newline and beep are all due to the control characters at the beginning of the ASCII set. The beep is due to the bell character (7); the newline is due to the line feed character (10). The smiley faces and other crap at the beginning are just the character representations of those control characters. Additionally, what you're not seeing is that the carriage return (13) is moving the cursor position to the beginning of the line, so characters 11 and 12 are being overwritten. Let's rectify this:

            for (int i = 0; i < 255; i++)
            {
                if (i == 13)
                    Console.Write(' ');
                else
                    Console.Write((char) i);
            }

As for the extended character codes not matching the ASCII Table, that's due to some encoding mumbo-jumbo that I'm not going to get into, but the solution is pretty simple: just add the following line before the for loop:

            Console.OutputEncoding = System.Text.Encoding.GetEncoding(1252);

The result is now different:


That's better! Now, we can use those extended ASCII characters to draw something. This is called ASCII art. Here's some full code:

            Console.OutputEncoding = System.Text.Encoding.GetEncoding(1252);
        
            for (int i = 0; i < 255; i++)
            {
                if (i == 13)
                    Console.Write(' ');
                else
                    Console.Write((char) i);
            }

            // top-left corner
        
            Console.SetCursorPosition(3010);
            Console.Write((char201);
        
            // top-right corner
        
            Console.SetCursorPosition(5310);
            Console.Write((char187);
        
            // mid-left T-junction
        
            Console.SetCursorPosition(3013);
            Console.Write((char204);
        
            // mid-right T-junction
        
            Console.SetCursorPosition(5313);
            Console.Write((char185);
        
            // bottom-left corner
        
            Console.SetCursorPosition(3015);
            Console.Write((char200);
        
            // bottom-right corner
        
            Console.SetCursorPosition(5315);
            Console.Write((char188);
        
            // horizontal edges
        
            for (int i = 31; i < 53; i++)
            {
                Console.SetCursorPosition(i, 10);
                Console.Write((char205);
                Console.SetCursorPosition(i, 13);
                Console.Write((char205);
                Console.SetCursorPosition(i, 15);
                Console.Write((char205);
            }
        
            // vertical edges
        
            Console.SetCursorPosition(3011);
            Console.Write((char186);
            Console.SetCursorPosition(3012);
            Console.Write((char186);
            Console.SetCursorPosition(3014);
            Console.Write((char186);
            Console.SetCursorPosition(5311);
            Console.Write((char186);
            Console.SetCursorPosition(5312);
            Console.Write((char186);
            Console.SetCursorPosition(5314);
            Console.Write((char186);
        
            // text
        
            Console.SetCursorPosition(3211);
            Console.Write("     Welcome to");
            Console.SetCursorPosition(3212);
            Console.Write(" Programmer's Ranch");
            Console.SetCursorPosition(3214);
            Console.Write("by Daniel D'Agostino");
        
            Console.SetCursorPosition(024);

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);

...and the output:


Right... although we have achieved our goal, you'll notice two things here that feel a little uncomfortable. First, the code is rather long. For this kind of thing, the drawing data is best kept in files. Secondly, there is quite a bit of repetition: lots of Console.SetCursorPosition() calls followed by Console.Write() calls. This may be alleviated by using methods, but more on that in another article.

Great! In this article we learned about what the ASCII table has to offer us. It doesn't sound like much, but if you're creative, you can use it to make some really cool games. Also, ASCII is probably the most basic character encoding there is; if you do advanced programming using text later on, knowing ASCII is a useful foundation.

I have more good things coming up in the next few articles, so don't go away! :)

Optional exercises:

  1. Replace the 'X' representing the player in our ASCII art game (Part 1Part 2) with a smiley face from the ASCII character set.
  2. Draw a top-down view of a house in the console window using ASCII art. Use '-' for doors and '+' for windows.
  3. If you feel like going overboard, draw something complex (such as an elaborate logo design or an overworld map) using ASCII art and send me a screenshot. I'll post the best ones here.

Monday, May 6, 2013

C# Basics: Working with Strings

Hey guys and girls!

In the articles so far, we used Strings, which are just variables that hold text, such as "Doh!" (always surrounded by double quotes). In this article we'll learn a bit more about what we can do with these Strings.

A String is actually made up of a series of characters (char data type), and each character has a number (called an index), starting at zero. If your String is "Hello!", then it looks like this:


You can access a particular character like this:

            String str = "Hello!";
            char secondCharacter = str[1];
            Console.WriteLine("The second character of {0} is: {1}", str, secondCharacter);

Result:


Since the character numbering starts at zero, then the second character ('e' in this case) is the one with index 1. An important difference between using Strings and characters is that when using literal values, Strings must use double quotes (as above), while characters use single quotes:

            char someCharacter = 'a';

Now, let's create a new project in SharpDevelop (or Visual Studio, if you prefer). Replace the sample code in Main() with the following:

            String str = "The quick brown fox jumps over the lazy dog.";
            Console.WriteLine(str);
   
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);

In the previous articles, we've been using a String containing {0} in Console.WriteLine(). If you're writing a string, you can just pass it directly to Console.WriteLine(), as we're doing above. Result:


Now I'm going to tell you about what is probably the single most important feature of tools such as Visual Studio and SharpDevelop. If you skip a line after Console.WriteLine(str), and then type

             str.

...you'll see a menu come up:


That menu is basically showing you everything you can do with the str variable. This is called Intellisense in Visual Studio. I don't know what it's called in SharpDevelop, but we call it Intellisense anyway. Because when a brand becomes known for a great product, you keep using the name of the brand. Your vacuum cleaner might be Panasonic, but your partner will probably still tell you, "Pass me the hoover" (not convinced? Read "The 22 Immutable Laws of Marketing" by Al Ries and Jack Trout). Intellisense is great because it guides you from within the editor as you try out different things.

[Edit: Andreas Grech points out that the idea of code completion predates Visual Studio and SharpDevelop.  "In SharpDevelop, it's referred to as intelli-sense", he says. "The intelli-sense in Visual Studio is then specifically called IntelliSense."]

The first thing that comes up in Intellisense is the Length. Every String has a length, which is the number of characters in the String. For "Hello!" that would be 6. In our new code, we can add the following to find the length:

            Console.WriteLine("Length: {0}", str.Length);

That gives a length of 44. Length is a property (more about them another time), so we don't need to put brackets such as str.Length(). On the other hand, ToUpper() is a function or method, so it must be done like this:

             Console.WriteLine(str.ToUpper());

What this does is convert the String to uppercase (results below). Similarly, ToLower() converts a String to lowercase. Note that this does not affect str itself; a new String is returned in each case.



Another interesting method is Replace(). You can replace single characters, or entire sections of the String, with something else:

            String cat = str.Replace("dog""cat");
            Console.WriteLine(cat);

This gives you: "The quick brown fox jumps over the lazy cat.". We're replacing "dog" with "cat" within the str variable and placing the result in the cat variable.

That's all for today! We'll use Strings a lot more in the coming articles, so stay tuned for more!