• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Bloki try/catch czy throw

0 głosów
202 wizyt
pytanie zadane 3 lipca 2018 w Java przez periedynek Obywatel (1,320 p.)

Cześć, piszę konwerter zamian liczb rzymskich na arabskie.

Potrzebuję dopisać sytuację, gdy ktoś wpiszę liczby arabskie bądź litery inne niż rzymskie.

Warunek wyglądałby tak:

if(romanNumber.matches("[0-9]") || !romanNumber.matches("[MDCLXVI]")){
        ...
    }

I teraz nie wiem czy mam stworzyć osobną klasę RomanException, czy jakoś to ulokować w blokach try/catch. Nie mam pomysłu, bo się gubię w tym throw.

 

package TrainingApp;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        int current = 0;
        int previous = 0;
        int sum = 0;
        try {

            String romanNumber = input.next();
            input.close();
            romanNumber = romanNumber.toUpperCase();

            char romanArray[] = romanNumber.toCharArray();
            for (int i = 0; i < romanNumber.length(); i++) {
                char letter = romanArray[i];

                switch (letter) {
                    case 'I': {
                        current = 1;
                        break;
                    }
                    case 'V': {
                        current = 5;
                        break;
                    }
                    case 'X': {
                        current = 10;
                        break;
                    }
                    case 'L': {
                        current = 50;
                        break;
                    }
                    case 'C': {
                        current = 100;
                        break;
                    }
                    case 'D': {
                        current = 500;
                        break;
                    }
                    case 'M': {
                        current = 1000;
                        break;
                    }
                }

                if (current > previous) {
                    sum += current - 2 * previous;
                } else {
                    sum += current;
                }
                previous = current;
            }
        } catch (RomanException e) {

        }

        System.out.println(sum);
    }
}

 

komentarz 3 lipca 2018 przez periedynek Obywatel (1,320 p.)

Zrobiłem tak:

package TrainingApp;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) throws RomanException {
        Scanner input = new Scanner(System.in);

        int current = 0;
        int previous = 0;
        int sum = 0;

        String romanNumber = input.next();
        input.close();
        romanNumber = romanNumber.toUpperCase();

        if (romanNumber.matches("[0-9]") || !romanNumber.matches("[MDCLXVI]")) {
            throw new RomanException();
        }

        char romanArray[] = romanNumber.toCharArray();
        for (int i = 0; i < romanNumber.length(); i++) {
            char letter = romanArray[i];

            switch (letter) {
                case 'I': {
                    current = 1;
                    break;
                }
                case 'V': {
                    current = 5;
                    break;
                }
                case 'X': {
                    current = 10;
                    break;
                }
                case 'L': {
                    current = 50;
                    break;
                }
                case 'C': {
                    current = 100;
                    break;
                }
                case 'D': {
                    current = 500;
                    break;
                }
                case 'M': {
                    current = 1000;
                    break;
                }
            }

            if (current > previous) {
                sum += current - 2 * previous;
            } else {
                sum += current;
            }
            previous = current;
        }

        System.out.println(sum);
    }
}

I druga klasa:

RomanException

package TrainingApp;

public class RomanException extends Exception {

    public String toString() {
        return "You've written digits or wrong letters";
    }

}

Nie wiem czy jest to dobra praktyka.

 

Btw. Nie pytajcie dlaczego pakunek nazywa sie TrainingApp. Przy tworzeniu coś kliknąłem i jest to stary pakunek.

2 odpowiedzi

+2 głosów
odpowiedź 3 lipca 2018 przez Tomek Sochacki Mędrzec (190,780 p.)

Nie znam jakoś super Javy ale tak na pierwszy rzut oka to chyba zapomniałeś o paru warunkach dla zbadania poprawności zapisu liczby rzymskiej, np. o fakcie, że litery stojące obok siebie mogą wystąpić max 3 razy, dlatego dla cyfry 4 poprawny jest zapis IV ale IIII nie, ponieważ "I" może być powtórzony max 3 razy. W związku z tym mamy też ograniczenie na maksymalną liczbę w zapisie podstawowym na 3999. Powyżej tej liczby w oryginalnym zapisie rzymskim stosowane są dodatkowe "kreski" pionowe i poziome ale wątpię abyś chciał się w to bawić w tym programie, zresztą w praktyce liczby rzymskie w powszechnym użytku nie przekraczają właśnie 3999.

Dodatkowo jeśli już robisz regexp do tej walidacji to proponowałbym od razu sprawdzić właśnie pełną poprawność liczby, np. wzorcem:

^(?=[MDCLXVI])M{0,3}(?:C[MD]|D?C{0,3})(?:X[CL]|L?X{0,3})(?:I[XV]|V?I{0,3})$/

który zwaliduje nam również wspomniane ponad trzykrotne powtórzenia liczb. Dodatkowo trzeba też pamiętać, że litery w pewnych konfiguracjach dają różnicę, np. CM oznacza 1000-100=900 (M-1000, C-100).

komentarz 4 lipca 2018 przez periedynek Obywatel (1,320 p.)

Nie rozumiem Cie o którą teraz część chodzi i która jest zła. 

[MDCLXVI] - chodzi o wystepowanie tych ltierek
{0,3} - ile minimum i ile maksimum może ich być

Nie używam tego wzorca, ponieważ wydaje mi się on tutaj niepotrzebny i za dużo jest ogólnie myślenia co poszczególne znaki znaczą. A tutaj mam metodę "matches" i wystarczą mi te niby 3 warunki by spełnić cały ten wzorzec.

komentarz 4 lipca 2018 przez periedynek Obywatel (1,320 p.)

Teraz widzę, że gwiazdka oznacza, ze coś występuje więcej albo więcej razy, więc faktycznie to się myiliło.

Teraz nie rozumiem w takim razie drugiego warunku:

!romanNumber.matches("[MDCLXVI]*

Dlaczego po usunięciu gwiazdki już nie działa? Skoro to się odnosi do innych literek niż podane w nawiasach kwadratowych.

Pomijając to, nie wiem tez jak dalej zrobic ten 3 warunek.


 

komentarz 4 lipca 2018 przez Tomek Sochacki Mędrzec (190,780 p.)

Dlaczego po usunięciu gwiazdki już nie działa? Skoro to się odnosi do innych literek niż podane w nawiasach kwadratowych.

A na jakiej podstawie uważasz, że odnosi się do innych liter niż te z nawiasów? Ty negujesz wartość zwracaną przez funkcję matches a nie ingerujesz  regexp. Dopasowanie wszystkiego po za literą A, B lub C to:

[^ABC]

a tak w ogóle to musisz zastanowić się co robią Twoje regexp. Zobaczmy co chcesz dopasować...

  1. Czy wzorzec [MDCLXVI]{0,3} dopasuje się do ciągu "MMM"? Tak dopasuje się, ponieważ znajdzie literę M występującą od 0 do 3 razy. (dokładniej mówiąc dopasuje 3 wystąpienia bo to kwantyfikator zachłanny ale to teraz nieistotne)
  2. Czy wzorzec [MDCLXVI]{0,3} dopasuje się do ciągu "MMMM"? Tak dopasuje się, ponieważ znajdzie literę M występującą od 0 do 3 razy i gdy to osiągnie to kończy działanie i nie interesuje się dalszymi literami czyli czwartą "M" bo nie musi tego robić.
  3. Czy wzorzec [MDCLXVI]{0,3} dopasuje się do ciągu "CMMMM"? Tak dopasuje się, ponieważ znajdzie literę C występującą od 0 do 3 razy i znowu nie interesuje się dalszymi literami.

Otóż wzorzec ten szuka litery M, lub D, lub C ... która wystąpi od 0 do 3 razy. Interesuje go tylko takie fragment ciągu. Nie masz tu żadnych granic dopasowania więc nie analizujesz ciągu jako jednego fragmentu pasującego jako całość.

Z chęcią pomogę w kwestii regexp ale nie będę omawiał tu na forum od podstaw całej składni itp. (od tego napisałem książkę o regexp :P). Poczytaj sobie o podstawach regexp i z chęcią wtedy wrócę do tematu.

Pozdrawiam

komentarz 4 lipca 2018 przez periedynek Obywatel (1,320 p.)

Zgupiałem już szczerze mówiąc.

Potrzebuje 3 warunki

1) W inpucie nie wystąpi żadna liczba, robi to ten warunek: 

romanNumber.matches("[0-9]")

2) Nie będzie żadnej innej litery niż MDCLXVI. 

I ja niby napisałem tak:

!romanNumber.matches("[MDCLXVI]*")

Ale dobrze zwróciłeś uwagę, że neguje wartość, którą zwróci to, czyli zawsze jak będzie poprawnie wpisana liczba to zwróci to fałsz (?)

Więc powinienem zrobić taki warunek?

!romanNumber.matches("[^MDCLXVI]")

Czytam to tak, jeżeli znajdzie jakąś inną liczbę to zwróci true, ale zanegowana zwróci false, czyli chyba dobrze?

3) Każda literka z podanych może wystąpić tylko 3 razy i się właśnie zagmatwałem u góry, bo nie pomyślałem o tym że neguje wyrażenie a nie regexa i tego już nie wiem jak zrobić.

 

komentarz 5 lipca 2018 przez periedynek Obywatel (1,320 p.)

@Tomek Sochacki, wiesz jak to ogarnac, ten 3 warunek? + czy ten 2 jest dobrze 

+1 głos
odpowiedź 3 lipca 2018 przez Wiciorny Maniak (66,480 p.)

 if (romanNumber.matches("[0-9]") || !romanNumber.matches("[MDCLXVI]")) {

            throw new RomanException();

        }

jeśli zrobisz coś takiego to jak wiadomo warunek o ile nie bedzie spełniony, to nie wurzyci nigdy wyjątku.

W  bloku  TRY/CATCH  masz troszke inna sytuacje...  bo jeśli jaka-kolwiek z FUNKCJI lub jakie kolwiek działanie w bloku się nie wykona : np.

    --- np coś  t utaj pójdzie nie tak ... 

String romanNumber = input.next();

            input.close();

            romanNumber = romanNumber.toUpperCase();

;

inicjalizacja obiektu, albo obiekt zwróci   null no - inny błąd niż w  przewidywanym  IF-ie to zostanie  rzucony wyjątek.

"gubie się w tym Throw"

 

To jest to co zostanie wyrzucone, ... więc generalnie możesz wyrzucić swój wyjątek - wcześnniej inmplementując go w osobnej klasie która np rozszerza Exception  klase / lub Throwable , zależy czybardziej mamy na istocie zwrócenie warunku czy po prostu obsługę błędu poprzez wyłapanie 

komentarz 3 lipca 2018 przez periedynek Obywatel (1,320 p.)
W takim razie to w jaki sposób ja to zrobiłem jest dobry?

W takim razie w tym przypadku try/catch odpada? Czy można by było to jakoś analogicznie zrobić.
komentarz 3 lipca 2018 przez Wiciorny Maniak (66,480 p.)
wiesz co to zależy, jeśli " chcesz zwrócić TYLKO SWÓJ BŁĄD " nabazie ... tylko twojego założenia że np liczba  jest niepoprawna  to  jeśli  nie potrafisz tego w JAVA8 stream załatwić,  to IF bedzie  lepszym rozwiązaniem, jednak  jeśli zalezy Ci na całkowitym zabezpieczeniu aplikacji  to try/catch ... wszystko sprowadza się  do SAMEJ IMPLEMENTACJI jak  i tego co masz zamiar zrobić i co dla Ciebie jest istotne
komentarz 3 lipca 2018 przez periedynek Obywatel (1,320 p.)
A na podstawie tego kodu, który wkleiłem? Jest to dobra opcja?

Podobne pytania

0 głosów
1 odpowiedź 110 wizyt
pytanie zadane 16 lutego w Java przez periedynek Obywatel (1,320 p.)
0 głosów
2 odpowiedzi 122 wizyt
pytanie zadane 22 listopada 2018 w PHP, Symfony, Zend przez marcolo Obywatel (1,130 p.)
0 głosów
1 odpowiedź 351 wizyt
pytanie zadane 17 listopada 2017 w C# i .NET przez Sensej Początkujący (490 p.)
Porady nie od parady
Zadając pytanie postaraj się o odpowiedni tytuł, kategorię oraz tagi.Tagi

67,210 zapytań

114,168 odpowiedzi

241,977 komentarzy

45,879 pasjonatów

Przeglądających: 329
Pasjonatów: 6 Gości: 323

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...