Blog Dla Młodszych Programistów C#/.NET

wtorek, 9 lutego 2021
Najwyższa pora napisać pierwszą taką powiedzmy bardziej rozszerzoną i kompletną aplikację. Myślę, że warto zacząć od takiego prostego kalkulatora. Często właśnie na studiach również studenci piszą takie proste aplikacje na początek. Także pokaże Ci krok po kroku jak podejść do napisania takiej aplikacji w C#, na tą chwilę będzie to jeszcze aplikacja konsolowa. Oczywiście będziemy pisać w visual studio, które mam nadzieję, że zainstalowałeś już sobie zgodnie z instrukcją przedstawioną w poprzednich moich artykułach.

Pierwsza Aplikacja w C# – Programujemy Kalkulator

Oczywiście taki kalkulator możemy napisać na różne sposoby. W tym artykule pokaże Ci jedno z dobrych podejść do pisania takiej aplikacji. Na początek uruchom proszę visual studio i utworzymy nowy projekt konsolowy w C#.

Aplikacja konsolowa kalkulator visual studio typ projektu

Kliknij Create a new project.

Aplikacja konsolowa kalkulator visual studio typ projektu

Wybierz Console App (.NET Core) i kliknij Next.

Aplikacja konsolowa kalkulator visual studio nazwa

Wpisz nazwę projektu. Może to być Calculator.ConsoleApp, z kolei nazwa solucji niech będzie Calculator. W kolejnych artykułach pokaże Ci jak stworzyć taki kalkulator jako aplikacja desktopowa, webowa i mobilna, dlatego do nazwy projektu dodałem przyrostek ConsoleApp tak, aby było wiadomo, że ten konkretny projekt to aplikacja konsolowa. Wszystkie te projekty będziemy tworzyć w solucji o nazwie Calculator. Kliknij create.

Po chwili zostanie utworzony nowy projekt konsolowy.

Aplikacja konsolowa kalkulator visual studio solution explorer

Zgodnie z wpisanymi wcześniej nazwami, została utworzona solucja Calculator oraz projekt Calculator.ConsoleApp. Kliknij 2 krotnie na plik Program.cs i usuń kod w metodzie Main. Tak wygląda w ten sposób kod naszej aplikacji:

namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Zanim zaczniemy pisać kod, warto zastanowić się dokładnie nad tym, jak powinna działać nasza aplikacja. Zróbmy proste notatki, komentarze, gdzie napiszemy krok po kroku, jak nasza aplikacja będzie działać.
  • Pierwszy krok to będzie wyświetlenie jakiegoś nagłówka, czyli opis aplikacji.
  • Następnie wyświetlimy komunikat z prośbą o podanie 1 liczby.
  • Pobierzemy liczbę od użytkownika.
  • Użytkownik będzie musiał wybrać działanie/operację, jaką chce wykonać. To znaczy dodawanie, odejmowanie, mnożenie lub dzieleniem, dlatego musimy w tym miejscu wyświetlić stosowny komunikat.
  • To działanie przypiszemy sobie do jakiejś zmiennej.
  • Prośba o podanie 2 liczby.
  • Pobranie 2 liczby od użytkownika.
  • Na podstawie tych danych wykonamy obliczenia.
  • I na koniec wyświetlimy użytkownikowi wynik działania.
Czyli tak będzie działać nasza aplikacja.

namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            //2. Prośba o podanie 1 liczby
            //3. Pobranie liczby od użytkownika
            //4. Prośba o podanie działania
            //5. Pobranie wybranego działania od użytkownika
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Mam wszystko ładnie rozpisane, wiemy krok po kroku, jak aplikacja ma działać. To są takie nasze minimalne wymagania, zatem możemy przejść do implementacji powyższych punktów.

Na początek wyświetlenie nagłówka, użyjemy do tego statycznej metody WriteLine z klasy Console.

using System;

namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            //3. Pobranie liczby od użytkownika
            //4. Prośba o podanie działania
            //5. Pobranie wybranego działania od użytkownika
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Kolejny krok to wyświetlenie komunikatu użytkownikowi z prośbą o podanie 1 liczby:

using System;

namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            //4. Prośba o podanie działania
            //5. Pobranie wybranego działania od użytkownika
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Pobranie liczby od użytkownika. Tym razem skorzystamy ze statycznej metody ReadLine klasy Console i przypiszemy wartość do zmiennej o nazwie number1.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = Console.ReadLine();
 
            //4. Prośba o podanie działania
            //5. Pobranie wybranego działania od użytkownika
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Musimy w tym miejscu uważać na 1 rzecz, ponieważ użytkownik w konsoli może wpisać dowolną wartość, ponieważ metoda ReadLine zwraca wartość tekstową – string'a. W związku z tym w tym miejscu musimy rzutować wartość wpisaną przez użytkownika na wartość liczbową, niech to będzie int. Możemy do tego użyć metody statycznej Parse:

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = int.Parse(Console.ReadLine());
 
            //4. Prośba o podanie działania
            //5. Pobranie wybranego działania od użytkownika
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

To rzutowanie można zapisać lepiej, jednak na tą chwilę spróbujmy tylko zaimplementować wymagania minimum, a później wrócimy jeszcze do tego kodu.

Kolejny etap to wyświetlenie komunikatu z prośbą o podanie przez użytkownika działania, które będziemy wykonywać. To już wiesz jak zrobić. Możemy tutaj również wyświetlić dostępne operacje, które może wybrać:

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = int.Parse(Console.ReadLine());
 
            //4. Prośba o podanie działania
            Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
 
            //5. Pobranie wybranego działania od użytkownika
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Będziemy w tym miejscu oczekiwać działania. Wybrane działanie zgodnie z kolejnym krokiem przypiszemy do zmiennej.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = int.Parse(Console.ReadLine());
 
            //4. Prośba o podanie działania
            Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
 
            //5. Pobranie wybranego działania od użytkownika
            var operation = Console.ReadLine();
 
            //6. Prośba o podanie 2 liczby
            //7. Pobranie liczby od użytkownika
            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Kolejny krok to ponownie pobranie liczby od użytkownika, tym razem 2.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = int.Parse(Console.ReadLine());
 
            //4. Prośba o podanie działania
            Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
 
            //5. Pobranie wybranego działania od użytkownika
            var operation = Console.ReadLine();
 
            //6. Prośba o podanie 2 liczby
            Console.WriteLine("Podaj proszę 2 liczbę:");
 
            //7. Pobranie liczby od użytkownika
            var number2 = int.Parse(Console.ReadLine());

            //8. Wykonanie obliczeń
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Pozostaje nam teraz wykonanie obliczeń. W tej sytuacji najlepiej będziesz skorzystać z instrukcji switch, przekazując wybraną operację, czyli zmienną operation:

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = int.Parse(Console.ReadLine());
 
            //4. Prośba o podanie działania
            Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
 
            //5. Pobranie wybranego działania od użytkownika
            var operation = Console.ReadLine();
 
            //6. Prośba o podanie 2 liczby
            Console.WriteLine("Podaj proszę 2 liczbę:");
 
            //7. Pobranie liczby od użytkownika
            var number2 = int.Parse(Console.ReadLine());
 
            //8. Wykonanie obliczeń
            var result = 0;
 
            switch (operation)
            {
                case "+":
                    result = number1 + number2;
                    break;
                case "-":
                    result = number1 - number2;
                    break;
                case "*":
                    result = number1 * number2;
                    break;
                case "/":
                    result = number1 / number2;
                    break;
                default:
                    throw new Exception("Wybrałeś złą operację!");
            }
 
            //9. Wyświetlenie wyniku użytkownikowi
        }
    }
}

Jeżeli użytkownik wybierze +, to wartość dodawania przypiszemy do nowej zmiennej result. Analogicznie zrobimy z pozostałymi operacjami. Jeżeli użytkownik wpisze inny znak, to wtedy zostanie rzucony wyjątek z odpowiednią wiadomością. Czyli tak może wyglądać cała instrukcja switch. Na podstawie wybranej operacji zostaną wykonane odpowiednie obliczenia. Wynik zostanie przypisany do zmiennej result. Na koniec wystarczy ten wynik za pomocą interpolacji stringów wyświetlić w konsoli użytkownikowi.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //1. Wyświetlenie nagłowka - opis aplikacji
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            //2. Prośba o podanie 1 liczby
            Console.WriteLine("Podaj proszę 1 liczbę:");
 
            //3. Pobranie liczby od użytkownika
            var number1 = int.Parse(Console.ReadLine());
 
            //4. Prośba o podanie działania
            Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
 
            //5. Pobranie wybranego działania od użytkownika
            var operation = Console.ReadLine();
 
            //6. Prośba o podanie 2 liczby
            Console.WriteLine("Podaj proszę 2 liczbę:");
 
            //7. Pobranie liczby od użytkownika
            var number2 = int.Parse(Console.ReadLine());
 
            //8. Wykonanie obliczeń
            var result = 0;
 
            switch (operation)
            {
                case "+":
                    result = number1 + number2;
                    break;
                case "-":
                    result = number1 - number2;
                    break;
                case "*":
                    result = number1 * number2;
                    break;
                case "/":
                    result = number1 / number2;
                    break;
                default:
                    throw new Exception("Wybrałeś złą operację!");
            }
 
            //9. Wyświetlenie wyniku użytkownikowi
            Console.WriteLine($"Wynik Twojego działania to: {result}.");
        }
    }
}

Tak może wyglądać nasza aplikacja. Wszystkie wymagania minimum, które wcześniej sobie rozpisaliśmy, zostały spełnione. Możemy teraz uruchomić aplikację (CTRL + F5) i przeprowadzić kilka testów w celu upewnienia się, że wszystko działa zgodnie z oczekiwaniami.

Aplikacja konsolowa kalkulator wymagania minimum

Jak widzisz, wszystko działa. Jednak, mimo to naszą aplikację nie jest jeszcze kompletna. Zauważ, że jeżeli użytkownik nie będzie stosował się do komunikatów i np. zamiast wybrania 1 z 4 dostępnych operacji wpisze dowolne ciąg znaków, to zostanie rzucony nieobsłużony w żaden sposób wyjątek. Przez to nasza aplikacji w takiej sytuacji co prawda wyświetli komunikat, ale zakończy działanie.

Aplikacja konsolowa kalkulator wyjątek operacja

Aby to poprawić, wystarczy cały kod, w którym spodziewamy się, że może wystąpić wyjątek wywołać wewnątrz instrukcji try catch. Jeżeli jakiś wyjątek w takiej sytuacji wystąpi, to obsłużymy go w klauzuli catch.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //1. Wyświetlenie nagłowka - opis aplikacji
                Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
                //2. Prośba o podanie 1 liczby
                Console.WriteLine("Podaj proszę 1 liczbę:");
 
                //3. Pobranie liczby od użytkownika
                var number1 = int.Parse(Console.ReadLine());
 
                //4. Prośba o podanie działania
                Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
 
                //5. Pobranie wybranego działania od użytkownika
                var operation = Console.ReadLine();
 
                //6. Prośba o podanie 2 liczby
                Console.WriteLine("Podaj proszę 2 liczbę:");
 
                //7. Pobranie liczby od użytkownika
                var number2 = int.Parse(Console.ReadLine());
 
                //8. Wykonanie obliczeń
                var result = 0;
 
                switch (operation)
                {
                    case "+":
                        result = number1 + number2;
                        break;
                    case "-":
                        result = number1 - number2;
                        break;
                    case "*":
                        result = number1 * number2;
                        break;
                    case "/":
                        result = number1 / number2;
                        break;
                    default:
                        throw new Exception("Wybrałeś złą operację!");
                }
 
                //9. Wyświetlenie wyniku użytkownikowi
                Console.WriteLine($"Wynik Twojego działania to: {result}.");
            }
            catch (Exception ex)
            {
                //logowanie do pliku
                Console.WriteLine(ex.Message);
            }
            
        }
    }
}

Dobrą praktyką jest zapisywanie wszystkich wyjątków do pliku, ale nie będziemy się na tym skupiać w tym artykule. Jeżeli nie wiesz, jak możesz to zrobić, to koniecznie zapoznaj się z tym artykułem na temat NLog'a. Oprócz tego wyświetlimy użytkownikowi ładny komunikat na temat błędu, który wystąpił bez zbędnych informacji. Nasza aplikacja nie przerwie działania, mimo błędu będzie można dalej z niej korzystać.

Aplikacja konsolowa kalkulator wyjątek try catch

Jak widzisz tym razem, został wyświetlony komunikat bez zbędnych informacji, aplikacja nie przerwała działania.

Wszystkie założenia zostały spełnione, dlatego dobrą praktyką jest również usunięcie tych zbędnych komentarzy, tak żeby sam kod był bardziej przejrzysty i czytelny.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
                Console.WriteLine("Podaj proszę 1 liczbę:");
                var number1 = int.Parse(Console.ReadLine());
 
                Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
                var operation = Console.ReadLine();
 
                Console.WriteLine("Podaj proszę 2 liczbę:");
                var number2 = int.Parse(Console.ReadLine());
 
                var result = 0;
 
                switch (operation)
                {
                    case "+":
                        result = number1 + number2;
                        break;
                    case "-":
                        result = number1 - number2;
                        break;
                    case "*":
                        result = number1 * number2;
                        break;
                    case "/":
                        result = number1 / number2;
                        break;
                    default:
                        throw new Exception("Wybrałeś złą operację!");
                }
 
                Console.WriteLine($"Wynik Twojego działania to: {result}.");
            }
            catch (Exception ex)
            {
                //logowanie do pliku
                Console.WriteLine(ex.Message);
            }
            
        }
    }
}

Zauważ, że w kilku miejscach używamy tego samego kodu. Np.

var number1 = int.Parse(Console.ReadLine());
var number2 = int.Parse(Console.ReadLine());

Czyli pobieramy wartość od użytkownika i rzutujemy ją na int'a. Warto trochę taki kod zrefaktoryzować. Najlepiej w takim przypadku utworzyć nową prywatną metodę, która zostanie użyta w 2 miejscach.

private static int GetInput()
{
    return int.Parse(Console.ReadLine());
}

Musi to być metoda statyczna, ponieważ będziemy ją wywoływać w metodzie statycznej Main. Będzie ona zwracać już przekonwertowaną na int'a wartość wpisaną przez użytkownika. Następnie możemy zamienić wywołania w metodzie Main i kod będzie wyglądał tak:

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
                Console.WriteLine("Podaj proszę 1 liczbę:");
                var number1 = GetInput();
 
                Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
                var operation = Console.ReadLine();
 
                Console.WriteLine("Podaj proszę 2 liczbę:");
                var number2 = GetInput();
 
                var result = 0;
 
                switch (operation)
                {
                    case "+":
                        result = number1 + number2;
                        break;
                    case "-":
                        result = number1 - number2;
                        break;
                    case "*":
                        result = number1 * number2;
                        break;
                    case "/":
                        result = number1 / number2;
                        break;
                    default:
                        throw new Exception("Wybrałeś złą operację!");
                }
 
                Console.WriteLine($"Wynik Twojego działania to: {result}.");
            }
            catch (Exception ex)
            {
                //logowanie do pliku
                Console.WriteLine(ex.Message);
            }
            
        }
 
        private static int GetInput()
        {
            return int.Parse(Console.ReadLine());
        }
    }
}

Aby jeszcze zwiększyć czytelność naszego kodu, możemy sobie nasze obliczenia, czyli całą instrukcję switch wywołać w osobnej metodzie.

private static double Calculate(double number1, double number2, string operation)
{
    switch (operation)
    {
        case "+":
            return number1 + number2;
        case "-":
            return number1 - number2;
        case "*":
            return number1 * number2;
        case "/":
            return number1 / number2;
        default:
            throw new Exception("Wybrałeś złą operację!\n");
    }
}

Czyli dodaliśmy nową prywatną statyczną metodę o nazwie Calculate, która na podstawie przekazanych parametrów zwraca wynik obliczeń. Nie potrzebujemy też tutaj tymczasowej zmiennej result, tylko od razu ze switcha'a zwrócimy wartość obliczeń. Jeżeli używamy return, to break jest również zbędny. Pozostaje tylko wywołać nową metodę w metodzie Main.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
                Console.WriteLine("Podaj proszę 1 liczbę:");
                var number1 = GetInput();
 
                Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
                var operation = Console.ReadLine();
 
                Console.WriteLine("Podaj proszę 2 liczbę:");
                var number2 = GetInput();
 
                var result = Calculate(number1, number2, operation);
                
                Console.WriteLine($"Wynik Twojego działania to: {result}.");
            }
            catch (Exception ex)
            {
                //logowanie do pliku
                Console.WriteLine(ex.Message);
            }
            
        }
 
        private static int GetInput()
        {
            return int.Parse(Console.ReadLine());
        }
 
        private static int Calculate(int number1, int number2, string operation)
        {
            switch (operation)
            {
                case "+":
                    return number1 + number2;
                case "-":
                    return number1 - number2;
                case "*":
                    return number1 * number2;
                case "/":
                    return number1 / number2;
                default:
                    throw new Exception("Wybrałeś złą operację!");
            }
        }
    }
}

Dzięki takim zabiegom zmniejszył się kod w metodzie Main. Dodaliśmy 2 nowe metody, które są bardziej czytelne i każda z nich odpowiada za 1 konkretną rzecz. Co również bardzo ważne, zostały odpowiednio nazwane, dzięki czemu nawet bez patrzenia do ciała tych metod, po samej nazwie możemy domyślić się, co każda z nich robi.

Nasza aplikacja dalej działa tak samo, jak wcześniej, ale możemy ją jeszcze trochę udoskonalić. Zauważ teraz, że jeżeli przy próbie podania 1 liczby, użytkownik wpiszę jakąś wartość tekstową, która nie jest liczbą, to zostanie rzucony wyjątek. Co prawda mamy taką sytuację obsłużoną, wyświetlamy wtedy odpowiedni komunikat w konsoli, ale możemy to jeszcze rozwiązać w inny sposób.

Aplikacja konsolowa kalkulator wyjątek string nie jest liczbą

W takiej sytuacji do konwertowania tekstu na liczbę zamiast int.Parse, lepiej użyć int.TryParse.

private static int GetInput()
{
    if (!int.TryParse(Console.ReadLine(), out int input))
        throw new Exception("Podana wartość nie jest liczbą");
 
    return input;
}

Czyli jeżeli nie uda się przekonwertować wartości wpisanej przez użytkownika na liczbę całkowitą typu int, to zostanie rzucony wyjątek z odpowiednim komunikatem, w tym przypadku "Podana wartość nie jest liczbą." Jeżeli wpisaną wartość uda się przekonwertować na liczbę, to ta liczba zostanie zwrócona. Do metody TryParse przekazałem zmienną input z parametrem out, jeżeli nie wiesz, co oznacza słowo kluczowe out, to zajrzyj do tego artykułu – out. Zobaczmy, jak teraz zachowa się aplikacja. Zauważ, że dzięki temu, że wprowadziliśmy prywatną metodę GetInput, te zmiany wystarczyło zrobić tylko w 1 miejscu.

Aplikacja konsolowa kalkulator wyjątek string nie jest liczbą tryparse

Czyli wszystko zadziała według oczekiwań. Tylko dalej można usprawnić jej działanie. Zauważ, że teraz, jeżeli użytkownik chce wykonać jakieś obliczenia, to może to zrobić tylko 1 raz. W sytuacji, gdy chce ponownie wykonać obliczenia, to za każdym razem musi uruchamiać ponownie aplikację. Nie jest to dobre rozwiązanie. Fajnie jakby użytkownik mógł wykonać dowolną ilość obliczeń i w każdej chwili mógł z niej wyjść. Aby to zrobić, wystarczy takie obliczenia wykonywać w pętli, w naszym przypadku możemy skorzystać z pętli nieskończonej np. while:

while (true)
{ 
}

Cały kod wykonamy w takiej pętli. Użytkownik będzie mógł wykonać wiele obliczeń i wyjść z aplikacji w dowolnym momencie.

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            while (true)
            {
 
                try
                {
                    Console.WriteLine("Podaj proszę 1 liczbę:");
                    var number1 = GetInput();
 
                    Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
                    var operation = Console.ReadLine();
 
                    Console.WriteLine("Podaj proszę 2 liczbę:");
                    var number2 = GetInput();
 
                    var result = Calculate(number1, number2, operation);
 
                    Console.WriteLine($"Wynik Twojego działania to: {result}.\n");
 
                }
                catch (Exception ex)
                {
                    //logowanie do pliku
                    Console.WriteLine(ex.Message);
                }
            }
        }
 
        private static int GetInput()
        {
            if (!int.TryParse(Console.ReadLine(), out int input))
                throw new Exception("Podana wartość nie jest liczbą.\n");
 
            return input;
        }
 
        private static int Calculate(int number1, int number2, string operation)
        {
            switch (operation)
            {
                case "+":
                    return number1 + number2;
                case "-":
                    return number1 - number2;
                case "*":
                    return number1 * number2;
                case "/":
                    return number1 / number2;
                default:
                    throw new Exception("Wybrałeś złą operację!\n");
            }
        }
    }
}

Dodatkowo po zakończeniu pętli dodałem do komunikatu znak \n, aby następny komunikat w konsoli był wyświetlany od nowej linii. Zwiększy to trochę przejrzystość aplikacji.

Aplikacja konsolowa kalkulator start int

Na koniec jeszcze 1 usprawnienie, które koniecznie musimy zrobić. Zauważ, że teraz nasz kalkulator działa na int'ach, czyli liczbach całkowitych. Warto byłoby to zmienić i obsłużyć tak, aby kalkulator robił obliczenia również liczb rzeczywistych. W tym celu możemy zamiast int'a użyć double'a. Także, musimy we wszystkich miejscach zmienić te wywołania. Dodatkowo jak będziemy wyświetlać wynik, to możemy dzięki statycznej metodzie Round z klasy Math zaokrąglić go do 2 miejsc po przecinku. Tak ostatecznie będzie wyglądała nasza aplikacja Kalkulator:

using System;
 
namespace Calculator.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Witaj w aplikacji KALKULATOR!");
 
            while (true)
            {
 
                try
                {
                    Console.WriteLine("Podaj proszę 1 liczbę:");
                    var number1 = GetInput();
 
                    Console.WriteLine("Jaką operację chcesz wykonać? Możliwe operacje to: '+', '-', '*', '/'.");
                    var operation = Console.ReadLine();
 
                    Console.WriteLine("Podaj proszę 2 liczbę:");
                    var number2 = GetInput();
 
                    var result = Calculate(number1, number2, operation);
 
                    Console.WriteLine($"Wynik Twojego działania to: {Math.Round(result, 2)}.\n");
 
                }
                catch (Exception ex)	
                {
                    //logowanie do pliku
                    Console.WriteLine(ex.Message);
                }
            }
        }
 
        private static double GetInput()
        {
            if (!double.TryParse(Console.ReadLine(), out double input))
                throw new Exception("Podana wartość nie jest liczbą.\n");
 
            return input;
        }
 
        private static double Calculate(double number1, double number2, string operation)
        {
            switch (operation)
            {
                case "+":
                    return number1 + number2;
                case "-":
                    return number1 - number2;
                case "*":
                    return number1 * number2;
                case "/":
                    return number1 / number2;
                default:
                    throw new Exception("Wybrałeś złą operację!\n");
            }
        }
    }
}

Pozostaje nam teraz tylko uruchomienie aplikacji i przetestowania kilka przypadków, tak aby upewnić się, że wszystko dobrze działa.

Aplikacja konsolowa kalkulator finalna


PODSUMOWANIE


Jak widzisz, udało nam się napisać Twoją pierwszą kompletną aplikację w języku C#. Najpierw rozpisaliśmy wszystkie założenia, jakie musi spełniać ta aplikacja. Następnie je zaimplementowaliśmy i udało nam się również wprowadzić kilka nowych funkcjonalności, dzięki którym aplikacja jest jeszcze lepsza. Jeżeli chcesz, to taką aplikację możesz spokojnie jeszcze rozwijać, wprowadzać dodatkowe operacje i ćwiczyć, dzięki czemu będziesz podnosił swoje umiejętności. Pamiętaj, że jeżeli chcesz się rozwijać, musisz praktykować, musisz programować, także najlepiej pisać różne aplikacje.

Jeżeli masz jakieś pytania, co do tego artykułu to zostaw komentarz poniżej 🙂

Poprzedni artykuł - Jak Zacząć Programować? Pierwsza Aplikacja w C#.
Następny artykuł - Jak Zostać Programistą .NET - Szkolenie Online Zostań Programistą .NET
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
Programista C#/.NET. Specjalizuje się w ASP.NET Core, ASP.NET MVC, ASP.NET Web API, Blazor, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Dodaj komentarz
© Copyright 2024 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Regulamin. Polityka prywatności. Design by Kazimierz Szpin