PROGRAMOWANIE – PRZYKŁADY
IDE C++ WinBGI C# Wpadki

Przykład C#

Zapis liczby w notacji rzymskiej Algorytm Program w Visual C# Komunikat dostarczany przez wyjątek Program w Visual C# (wersja 2) Poprzedni przykład Następny przykład Program w Visual C++ Kontakt

Zapis liczby w notacji rzymskiej

Zadaniem programu konsolowego w języku C# jest wczytanie dodatniej liczby całko­witej i wygenerowanie jej notacji rzymskiej. Przypo­mnijmy (por. analo­giczny program w C++), że w systemie rzymskim zapisu liczb używa się siedmiu podsta­wowych symboli jednoli­terowych i dodatkowych sześciu dwulite­rowych, którym przypisane są wybrane liczby całkowite, zwane wagami:

    I     1         IV     4
    V     5         IX     9
    X     10        XL     40
    L     50        XC     90
    C     100       CD     400
    D     500       CM     900
    M     1000

Ciąg takich symboli reprezentuje liczbę równą sumie odpowiada­jących im wag. Na przykład zapis MCMLXXXIII określa liczbę 1983 (1000 + 900 + 50 + 10 + 10 + 10 + 1 + 1 + 1). Zestaw symboli dwulite­rowych został przyjęty, by uniknąć kłopo­tliwych wyjątków od ogólnej reguły, że w zapisie liczby symbol o wadze niższej nie może wystąpić przed symbolem o wadze wyższej. Obowią­zuje również reguła, że zapis powinien składać się możliwie z jak najmniejszej liczby znaków. Na przykład liczba 9 powinna być zapisana jako IX, nie zaś jako VIIII czy VIV.

Algorytm

Powyższe symbole i ich wagi mogą być reprezen­towane przez dwie tablice jednowy­miarowe o 13 elemen­tach, łańcu­chów i liczb całko­witych, uporządko­wane w kolejności od najwię­kszej do najmniej­szej wagi:

string[] Symbol = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

int[] Waga = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

Podobnie jak w języku C++ można łatwo, korzystając z tego uporządko­wania, wygene­rować zapis rzymski dodatniej liczby całkowitej n. Algorytm polega na przebie­ganiu w pętli for kolejnych symboli, poczy­nając od M, i spraw­dzaniu, czy rozpatry­wany symbol ma być uwzglę­dniony w zapisie liczby:

for (int r = 0; n > 0; )
    if (n >= Waga[r])   // Symbol uwzględniany w zapisie n
    {
        Console.Write(Symbol[r]);
        n -= Waga[r];
    }
    else                // Przejście do następnego symbolu
        r++;

Jeżeli waga symbolu nie przekracza wartości n, należy go wysłać na wyjście i zmniejszyć wartość n o tę wagę, w przeciwnym razie należy przejść do nastę­pnego symbolu. Zerowa wartość n oznacza, że genero­wanie notacji rzym­skiej liczby zostało zakończone.

Program w Visual C#

Rozbudowę szablonowego kodu źródłowego aplikacji konsolowej C# rozpoczy­namy od umie­szczenia w klasie Program dwóch powyż­szych defi­nicji tablic SymbolWaga, poprze­dzając je modyfi­katorem static. Tym samym obie tablice będą polami staty­cznymi tej klasy, podobnie jak metoda Main, od której rozpo­czyna się wykonanie apli­kacji. Następnie uzupeł­niamy pustą metodę Main o instrukcje czytania liczby n i zaprezen­towany algorytm, co prowadzi do kodu źródłowego:

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

namespace Lrzym1
{
    class Program
    {
        static string[] Symbol = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X",
                                  "IX", "V", "IV", "I"};

        static int[] Waga = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

        static void Main(string[] args)
        {
            Console.Write("Liczba całkowita dodatnia: ");
            int n = Convert.ToInt32(Console.ReadLine());
            Console.Write("Postać rzymska liczby {0}: ", n);
            for (int r = 0; n > 0;)
                if (n >= Waga[r])
                {
                    Console.Write(Symbol[r]);
                    n -= Waga[r];
                }
                else
                    r++;
            Console.WriteLine();
        }
    }
}

Komunikat dostarczany przez wyjątek

Niewątpliwym ulepszeniem programu będzie poinformo­wanie użytko­wnika, gdy wprowadzi on liczbę ujemną lub zero, że powinna być ona dodatnia (Rzymianie nie znali liczb ujemnych i zera). Aby odróżnić tę sytuację od innych zdarzeń wyjątkowych, jak np. niepra­widłowy format ciągu wejścio­wego przy wprowa­dzaniu liczby całko­witej, należy podać stosowny komunikat (łańcuch) w instru­kcji zgło­szenia wyjątku, np.:

if (n <= 0)
    throw new Exception("Wymagana dodatnia liczba całkowita.");

Łańcuch będący argumentem konstruktora jest wyświe­tlany (wraz z innymi informa­cjami) przez mecha­nizm obsługi wyją­tków, gdy progra­mista nie użyje instru­kcji try—catch (gdyby argu­ment nie wystą­pił, łańcu­chem domyśl­nym byłby "Zgło­szono wyjątek typu 'System.Exception'").

Klasa Exception ma kilka właściwości, z których najważ­niejszą wydaje się Message. Udostępnia ona komunikat błędu. Poniższa wersja instru­kcji try—catch z rozbudowanym blokiem catch prezen­tuje obsługę wyjątku polega­jącą na wyświe­tleniu komuni­katu o błędzie dostar­czonym w obiekcie klasy Exception:

try
{
    ...    // Kod, który może spowodować wyjątek
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

Program w Visual C# (wersja 2)

Ulepszona wersja programu o obsługę wyjątków znajdująca notację rzymską wczyty­wanej z klawia­tury doda­tniej liczby całko­witej może wyglą­dać następująco:

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

namespace Lcyfr2
{
    class Program
    {
        static string[] Symbol = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X",
                                  "IX", "V", "IV", "I"};

        static int[] Waga = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

        static void Main(string[] args)
        {
            Console.Write("Liczba całkowita dodatnia: ");
            try
            {
                int n = Convert.ToInt32(Console.ReadLine());
                if (n <= 0)
                    throw new Exception("Wymagana dodatnia liczba całkowita.");
                Console.Write("Postać rzymska liczby {0}: ", n);
                for (int r = 0; n > 0;)
                    if (n >= Waga[r])
                    {
                        Console.Write(Symbol[r]);
                        n -= Waga[r];
                    }
                    else
                        r++;
                Console.WriteLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

W zależności od wprowadzonego z klawiatury ciągu znaków program wypisuje w oknie konsoli (rys.):

Opracowanie przykładu: lipiec 2018