Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

c++ - Wyrzucanie wyjątków osobno dla każdego z błędów w odczycie osobno

jowyma 23 Maj 2015 16:25 855 14
  • #1 23 Maj 2015 16:25
    jowyma
    Poziom 22  

    Dzień dobry,
    Chcę poprosić o pomoc w wyrzucaniu wyjątków osobno dla każdego z błędów przy odczycie danych z pliku. Wiem, że przy pierwszym wyjątku wczytywanie się zakończy, ale chodzi o to, aby w zależności od tego który element nie dał się wczytać funkcja wyrzucała inny wyjątek.
    Funkcja działa w ten sposób, że otwiera plik, potem odczytuje pierwszy element z danego wiersza i kierując się wartością tego elementu wie, którą procedurę zczytywania zastosować - w każdym wierszu pliku mogą być bowiem informacje dla obiektu z jednej z czterech klas.

    Nie wiem też skąd mam wiedzieć czy wyjątek będzie typu string czy int. Czy ja to ustalam czy kompilator?
    Poniżej załączam funkcję, do której mam dołożyć wspomnianą obsługę wyjątków. W załączniku zaś całość programu.

    Czy dobrze myślę, że każdą z komend typu "cin" mam opakować osobnym "try" i pod spodem od razu muszę umieścić catch? Czy też mogę obsługę catch zrobić w głównej funkcji? Czy po instrukcji "try" mogę sobie ustawić co będzie wyrzucał wyjątek jak takie "try" się nie powiedzie?

    Czy można napisać obsługę wyjątków w odczycie danych jako metodę danej klasy jeżeli funkcja odczytująca jest w module main przed funkcją main?

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0 14
  • Pomocny post
    #3 23 Maj 2015 19:29
    -psiak-
    Poziom 32  

    Coś w ten deseń:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Ale widzę tu problem, nie przydzielasz tablicy oraz nie kontrolujesz numLines.
    Czyli coś nadal mocno skopano.

    1
  • #4 23 Maj 2015 21:01
    jowyma
    Poziom 22  

    Tablicę przydzielam w main, podobnie jak tam liczę NumLines. To tylko fragment kodu. Całość jest w załączniku (dużo tego jest, trudno wybrać co pokazać a co by tylko utrudniło pokazanie problemu).

    A czy da się wyrzucić wyjątek w funkcji a przechwycić w main? Próbuję to właśnie zrobić i kiepsko mi idzie.
    To znaczy, kompilator protestuje jeżeli stosuję try a potem nie ma catch. Próbuję to obejść i nie stosować try, ale nie umiem sobie poradzić, bo nie wiem jak bez try sprawdzić czy udało się przydzielić pamięć nowemu obiektowi. Wiem, że to błąd bad_alloc ale kiedy daję catch(bad_alloc) {throw "Blad przydzialu pamieci";} to kompilator domaga się pod spodem kolejnego catch, a ja chcę kolejne catch już mieć w main...

    I jeszcze pytanie jak obsłużyć wyjątek, że zczytana z pliku dana niejest typu, który miał być. Czyli np. int c, plik >> c - czyli oczekuję int, a wartość z pliku to string. Jak to obsłużyć. Czy mogę ominąć try? Bo jak dam try to pod spodem musi być catch, a ja chcę to przechwycić dopiero w main.,


    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • #5 23 Maj 2015 21:27
    Dżyszla
    Poziom 42  

    Możesz zrobić obsługę wyjątku wewnątrz, a następnie go ponownie wywołać w celu obsłużenia bardziej na zewnątrz. Ale każdy punkt wywołania wyjątku musisz traktować jak coś w rodzaju "goto" do linii obsługi wyjątku bez możliwości powrotu.

    Dlatego sprawę wyjątków trzeba dobrze przemyśleć, czy aby na pewno ma występować w tym a tym miejscu, i może nieco wbrew logice programu, jednak zaakceptować potrzebę obsługi wewnątrz funkcji lub zrezygnować z wyjątków własnych i tworzyć listę błędów, którą będzie można przekazać do callera funkcji. Wszystko zależy, co tak naprawdę chce się osiągnąć i co kod (funkcja) ma robić - przetwarzać i krzyczeć, jak sie nie uda, czy parsować i zwracać listę problemów ewentualnie na samym końcu wywołując wyjątek z już istniejącą listą błędów.

    0
  • #6 23 Maj 2015 21:29
    jowyma
    Poziom 22  

    Mam wyłapać wszystkie możliwe problemy z funkcji odczyt, wyrzucić je i przechwycić w main. Robię to pierwszy raz w życiu i wiem tyle ile napisał Grębosz w Pasji. Nie wiem nawet jakie tam mogą wystąpić błędy ani jak te błędy się nazywają.

    W Gręboszu określa się warunek i wyrzuca wyjątek. Ewentualnie blok try i potem catch żeby wyświetlić co źle poszło. I tyle wiem.

    Oto moja kolejna próba, co jeszcze należy obsłużyć - jakie błędy i wyjątki?




    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #7 25 Maj 2015 13:04
    szelus
    Specjalista - Mikrokontrolery

    W C++ nie pisze się w ten sposób:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod
    tylko tworzy się typ wyliczeniowy (enum).
    Poza tym, jeżeli nastąpił wyjątek w czytaniu danych, czyli wczytanie się nie udało, to raczej nie ma sensu ich przetwarzanie, nieprawdaż? Jeżeli przejmujesz rzucony wyjątek przez catch, to wykonanie programu będzie kontynuowane, chyba, że sam je przerwiesz.

    1
  • #8 25 Maj 2015 19:59
    jowyma
    Poziom 22  

    Czyli po catch mam zrobić break?

    0
  • #9 25 Maj 2015 22:45
    szelus
    Specjalista - Mikrokontrolery

    To zależy, co chcesz uzyskać. Program można zakończyć w dowolnym momencie wywołując funkcję exit(n). break tylko wychodzi z pętli (albo instrukcji switch).

    0
  • #10 25 Maj 2015 23:58
    p.kaczmarek2
    Poziom 23  

    Ja bym zrobił osobne klasy wyjątków z specyficznymi dla nich parametrami. Potem byś mógł robić osobne catch'e dla rożnych sytuacji.
    Tak jest np. w Javie.
    To z rzucaniem samego stringa przejdzie, ale jest dość słabe i "brudne".
    Do tego mógłbyś zrobić drzewo wyjątków, np. "Blad Odczytu" jest klasa rodzica dla klas "Plik nie istnieje" lub "Zly format pliku".

    1
  • #11 26 Maj 2015 21:41
    jowyma
    Poziom 22  

    A mogę prosić o linka do jakiegoś prostego a przejrzystego przykładu tych klas? Z podkreśleniem "prostego" i "przejrzystego" ? :)

    0
  • #12 26 Maj 2015 21:59
    p.kaczmarek2
    Poziom 23  

    Np. dokumentacja C#/Javy?

    Albo masz, oto przykładowe drzewo klas wyjątków dla obsługi plików w Twoim systemie:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Ciała klas dopisz sam w ramach ćwiczeń.

    0
  • #13 26 Maj 2015 23:46
    jowyma
    Poziom 22  

    Niestety, nie za bardzo rozumiem co te puste klasy dają i po co dziedziczenie.

    0
  • #14 27 Maj 2015 00:06
    p.kaczmarek2
    Poziom 23  

    Dzieki nim można zagnieżdżać catche i w rożnych catchach obsługiwać rożne błędy.

    Tak jest w C#":

    https://msdn.microsoft.com/en-us/library/system.io.ioexception%28v=vs.110%29.aspx
    https://msdn.microsoft.com/en-us/library/system.exception%28v=vs.110%29.aspx
    https://msdn.microsoft.com/en-us/library/system.io.endofstreamexception%28v=vs.110%29.aspx

    Przykład drzewa:

    Code:


    The exception that is thrown when an I/O error occurs.
    Inheritance Hierarchy
    System.Object
      System.Exception
        System.SystemException
          System.IO.IOException
            System.IO.DirectoryNotFoundException
            System.IO.DriveNotFoundException
            System.IO.EndOfStreamException
            System.IO.FileLoadException
            System.IO.FileNotFoundException
            System.IO.PathTooLongException
            System.IO.PipeException

    0
  • Pomocny post
    #15 27 Maj 2015 01:15
    alagner
    Poziom 25  

    To ja teraz wywalę koncepcję o 180 stopni, ale może warto przyjąć, że C++ to nie C z wyjątkami, tylko po coś mamy klasy i enkapsulację.
    I tak z tego potworka:

    Kod: cpp-qt
    Zaloguj się, aby zobaczyć kod


    Zaproponowałbym coś takiego, może dłużej ale czytelniej i łatwiej w utrzymywaniu tego potem:



    Kod: cpp-qt
    Zaloguj się, aby zobaczyć kod

    1