Book Image

C# Data Structures and Algorithms

By : Marcin Jamro
Book Image

C# Data Structures and Algorithms

By: Marcin Jamro

Overview of this book

Data structures allow organizing data efficiently. They are critical to various problems and their suitable implementation can provide a complete solution that acts like reusable code. In this book, you will learn how to use various data structures while developing in the C# language as well as how to implement some of the most common algorithms used with such data structures. At the beginning, you will get to know arrays, lists, dictionaries, and sets together with real-world examples of your application. Then, you will learn how to create and use stacks and queues. In the following part of the book, the more complex data structures will be introduced, namely trees and graphs, together with some algorithms for searching the shortest path in a graph. We will also discuss how to organize the code in a manageable, consistent, and extendable way. By the end of the book,you will learn how to build components that are easy to understand, debug, and use in different applications.
Table of Contents (14 chapters)

Input and output


Many examples shown in the following part of the book will require interaction with the user, especially by reading input data and showing output. You can easily add such features to the application, as explained in this section.

Reading from input

The application can read data from the standard input stream using a few methods from the Console static class from the System namespace, such as ReadLine and ReadKey. Both are presented in the examples in this section.

Let's take a look at the following line of code:

string fullName = Console.ReadLine(); 

Here, you use the ReadLine method. It waits until the user presses the Enter key. Then, the entered text is stored as a value of the fullName string variable.

In a similar way, you can read data of other types, such as int, as shown as follows:

string numberString = Console.ReadLine(); 
int.TryParse(numberString, out int number); 

In this case, the same ReadLine method is called and the entered text is stored as a value of the numberString variable. Then, you just need to parse it to int and store it as a value of the int variable. How can you do that? The solution is very simple—use the TryParse static method of the Int32 struct. It is worth mentioning that such a method returns a Boolean value, indicating whether the parsing process has finished successfully. Thus, you can perform some additional actions when the provided string representation is incorrect.

A similar scenario, regarding the DateTime structure and the TryParseExact static method, is shown in the following example:

string dateTimeString = Console.ReadLine(); 
if (!DateTime.TryParseExact( 
    dateTimeString, 
    "M/d/yyyy HH:mm", 
    new CultureInfo("en-US"), 
    DateTimeStyles.None, 
    out DateTime dateTime)) 
{ 
    dateTime = DateTime.Now; 
} 

This example is more complicated than the previous one, so let's explain it in detail. First of all, the string representation of the date and time is stored as a value of the dateTimeString variable. Then, the TryParseExact static method of the DateTime struct is called, passing five parameters, namely the string representation of the date and time (dateTimeString), the expected format of the date and time (M/d/yyyy HH:mm), the supported culture (en-US), the additional styles (None), as well as the output variable (dateTime) passed by reference using the out parameter modifier.

If the parsing is not completed successfully, the current date and time (DateTime.Now) is assigned to the dateTime variable. Otherwise, the dateTime variable contains the DateTime instance consistent with the string representation provided by the user.

Note

While writing the part of code involving the CultureInfo class name, you could see the following error: CS0246 The type or namespace name 'CultureInfo' could not be found (are you missing a using directive or an assembly reference?). This means that you do not have a suitable using statement at the top of the file. You can easily add one by clicking on the bulb icon shown in the left-hand margin of the line with the error and choosing the using System.Globalization; option. The IDE will automatically add the missing using statement and the error will disappear.

Apart from reading the whole line, you can also get to know which character or function key has been pressed by the user. To do so, you can use the ReadKey method, as shown in the following part of code:

ConsoleKeyInfo key = Console.ReadKey(); 
switch (key.Key) 
{ 
    case ConsoleKey.S: /* Pressed S */ break; 
    case ConsoleKey.F1: /* Pressed F1 */ break; 
    case ConsoleKey.Escape: /* Pressed Escape */ break; 
} 

After calling the ReadKey static method and once any key has been pressed by a user, information about the pressed key is stored as the ConsoleKeyInfo instance (that is, key, in the current example). Then, you use the Key property to get an enumeration value (of ConsoleKey) representing a particular key. At the end, the switch statement is used to perform operations depending on the key that has been pressed. In the example shown, three keys are supported, namely S, F1, and Esc.

Writing to output

Now, you know how to read input data, but how can you ask questions to the user or present results on the screen? The answer, together with examples, is shown in this section.

Similarly as in the case of reading data, operations related to the standard output stream are performed using methods of the Console static class from the System namespace, namely Write and WriteLine. Let's see them in action!

To write some text, you can just call the Write method, passing the text as a parameter. An example of code is as follows:

Console.Write("Enter a name: "); 

The preceding line causes the following output to be shown:

Enter a name:

What's important here is that the written text is not followed by the line terminator. If you want to write some text and move to the next line, you can use the WriteLine method, as shown in the following code snippet:

Console.WriteLine("Hello!"); 

After executing this line of code, the following output is presented:

Hello!

Of course, you can also use Write and WriteLine methods in more complex scenarios. For example, you can pass many parameters to the WriteLine method, namely the format and additional arguments, as shown in the following part of the code:

string name = "Marcin"; 
Console.WriteLine("Hello, {0}!", name); 

In this case, the line will contain Hello, a comma, a space, a value of the name variable (that is, Marcin), as well as the exclamation mark. The output is shown as follows:

Hello, Marcin!

The next example presents a significantly more complex scenario of writing the line regarding the confirmation of a table reservation at a restaurant. The output should have the format Table [number] has been booked for [count] people on [date] at [time]. You can achieve this goal by using the WriteLine method, as shown as follows:

string tableNumber = "A100"; 
int peopleCount = 4; 
DateTime reservationDateTime = new DateTime( 
    2017, 10, 28, 11, 0, 0); 
CultureInfo cultureInfo = new CultureInfo("en-US"); 
Console.WriteLine( 
    "Table {0} has been booked for {1} people on {2} at {3}", 
    tableNumber, 
    peopleCount, 
    reservationDateTime.ToString("M/d/yyyy", cultureInfo), 
    reservationDateTime.ToString("HH:mm", cultureInfo)); 

The example starts with a declaration of four variables, namely tableNumber (A100), peopleCount (4), and reservationDateTime (10/28/2017 at 11:00 AM), as well as cultureInfo (en-US). Then, the WriteLine method is called passing five parameters, namely the format string followed by arguments that should be shown in the places marked with {0}, {1}, {2}, and {3}. It is worth mentioning the last two lines, where the string presenting date (or time) is created, based on the current value of the reservationDateTime variable.

After executing this code, the following line is shown in the output:

Table A100 has been booked for 4 people on 10/28/2017 at 11:00

Of course, in real-world scenarios, you will use read- and write-related methods in the same code. For example, you can ask a user to provide a value (using the Write method) and then read the text entered (using the ReadLine method).

This simple example, which is also useful in the next section of this chapter, is shown as follows. It allows the user to enter data relating to the table reservation, namely the table number and the number of people, as well as the reservation date. When all of the data is entered, the confirmation is presented. Of course, the user will see information about the data that should be provided:

using System; 
using System.Globalization; 
 
namespace GettingStarted 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            CultureInfo cultureInfo = new CultureInfo("en-US"); 
 
            Console.Write("The table number: "); 
            string table = Console.ReadLine(); 
 
            Console.Write("The number of people: "); 
            string countString = Console.ReadLine(); 
            int.TryParse(countString, out int count); 
 
            Console.Write("The reservation date (MM/dd/yyyy): "); 
            string dateTimeString = Console.ReadLine(); 
            if (!DateTime.TryParseExact( 
                dateTimeString, 
                "M/d/yyyy HH:mm", 
                cultureInfo, 
                DateTimeStyles.None, 
                out DateTime dateTime)) 
            { 
                dateTime = DateTime.Now; 
            } 
 
            Console.WriteLine( 
                "Table {0} has been booked for {1} people on {2}  
                 at {3}", 
                table, 
                count, 
                dateTime.ToString("M/d/yyyy", cultureInfo), 
                dateTime.ToString("HH:mm", cultureInfo)); 
        } 
    } 
} 

The preceding code snippet is based on the parts of code shown and described previously. After launching the program and entering the necessary data, the output could look as follows:

The table number: A100The number of people: 4The reservation date (MM/dd/yyyy): 10/28/2017 11:00Table A100 has been booked for 4 people on 10/28/2017 at 11:00Press any key to continue . . . 

When the code is created, it is a good idea to improve its quality. One of the interesting possibilities associated with the IDE is related to removing unused using statements, together with sorting the remaining ones. You can easily perform such an operation by choosing the Remove and Sort Usings option from the context menu in the text editor.