Po użyciu wyjątku pętla uruchamia się cały czas.

0

Cześć,

Mam mały problem z kodem. Może ktoś by mi był to w stanie jakoś wyjaśnić.
Miałem problem że przy wprowadzaniu czegoś innego niż dostępne opcje aplikacja przestała działać. Postanowiłem dodać try catch i generalnie działa z jednym małym ale... jeżeli użyje "break;" to wiadomo aplikacja kończy działanie ale w momencie jak nie użyję break; to pętla uruchamia się cały czas i użytkownik nie ma już możliwości ponownego wybrania opcji.

Może ktoś pomoże mi to zrozumieć. 😉

package com.company;

import java.util.InputMismatchException;
import java.util.Scanner;


public class Main{

        public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        Party party = new Party();
        boolean exit = true;


        while (exit){
            System.out.println("Wybierz opcję:");
             System.out.println("1 - Wyświetl gośći");
             System.out.println("2 - Dodaj gości");
             System.out.println("3 - Pokaż posiłki");
             System.out.println("4 - Znajdź po numerze telefonu");
             System.out.println("5 - Usuń gościa");
             System.out.println("6 - Wyjście");


      try {
          int userChoice = scanner.nextInt();
          if (userChoice >= 7) {
          System.out.println("Wybrałeś nieistniejącą opcję!");
        } else


      switch (userChoice) {
            case (1): party.displayGuest();
            break;

            case (2): party.addGuest();
            break;

            case (3): party.showMeals();
            break;

            case (4): party.displayGuestByPhoneNumber();
            break;

            case (5): party.removeGuest();
            break;

            case (6): exit = !exit;
            break;
        }
       } catch (InputMismatchException e){
         System.out.println("Wybrano opcję w nieprawidłowym formacie!");
         break;
      }
    }
  }
}

2

A dlaczego ma kończyć działanie, skoro nie zmieniasz wartości zmiennej exit ?
Poszukaj też słowa kluczowego default przy switch'u.

2

W bloku catch(){}, jeżeli nie masz linijki break; jedyne co się dzieje to wypisanie komunikatu, po czym pętla wykonuje się od nowa. Klasa Scanner w przypadku rzucania wyjątku InputMismatchException nie pomija błędnych danych, zgodnie z dokumentacją

When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.

W kolejnym obiegu pętli następuje ponowna próba parsowania tych samych błędnych danych do wartości liczbowych, co znowu powoduje wyrzucenie wyjątku i tak w kółko. Jeżeli chcesz pominąć wadliwe dane możesz np. wywołać scanner.next() w bloku catch.

2

Z jakiej racji oszukujesz sam siebie? Czyżby autosabotaż?

        boolean exit = true;
        while (exit)
        {
          if(...) exit=!exit;
        } 

Porównaj do:

        boolean active=true; //active, more, good
        while(active)
        {
          if(...) active=false;
        } 

Lub do:

        boolean stop=false; //stop, bad, exit, quit
        while(!stop)
        {
          if(...) stop=true;
        } 
0

Dziękuję wszystkim za podpowiedzi i rady.
Rozwiązałem problem w trochę inny sposób i chciałbym się dowiedzieć czy to co zrobiłem ma sens. (Bo działać działa ale to nie tylko chyba o to chodzi :P)

Po wprowadzonych zmianach klasa main wygląda tak:

package com.company;

import java.util.Scanner;

public class Main{

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

        boolean active = true;


        while (active){
            System.out.println("Wybierz opcję:");
            System.out.println("1 - Wyświetl gośći");
            System.out.println("2 - Dodaj gości");
            System.out.println("3 - Pokaż posiłki");
            System.out.println("4 - Znajdź po numerze telefonu");
            System.out.println("5 - Usuń gościa");
            System.out.println("6 - Wyjście");

                    switch (party.selectOption()) {
                        case (1): party.displayGuest();
                            break;

                        case (2): party.addGuest();
                            break;

                        case (3): party.showMeals();
                            break;

                        case (4): party.displayGuestByPhoneNumber();
                            break;

                        case (5): party.removeGuest();
                            break;

                        case (6): active = false;
                            break;
                    }
        }
        
    }
}

a metoda "selectOption" tak:

        try {
            Integer option = Integer.valueOf(scanner.nextLine());
            if (option >= 7) {
                System.out.println("Brak opcji o takim numerze");
            }return option;
        } catch (NumberFormatException e) {
            System.out.println("Wprowadź właściwy format wyboru");
        } return 0;
    }

1
Atsin napisał(a):

Rozwiązałem problem w trochę inny sposób i chciałbym się dowiedzieć czy to co zrobiłem ma sens.

  1. Zapominasz o option <= 0
0

Racja. Wprowadziłem poprawkę:

if (option >= 7 || option <= 0) {
                System.out.println("[Brak opcji o takim numerze]");

A rozwiązanie żeby złapać NumberFormatException w metodzie jest akceptowalne czy nie powinno się tak robić?

1
Atsin napisał(a):

W jakim sensie „zautomatyzować”

Coś w ten deseń:

import java.util.Scanner;
public class SMenu
{
   public static void main(String[] args)
   {
      Party party=new Party();
      MenuItem.Run("Menu główne",Party.menu,party);
   }
}

class Party
{
   public void displayGuest() { System.out.println("displayGuest\n"); }
   public void addGuest() { System.out.println("addGuest\n"); }
   public void showMeals() { System.out.println("showMeals\n"); }
   public void displayGuestBySurname() { System.out.println("displayGuestBySurname\n"); }
   public void displayGuestByPhoneNumber() { System.out.println("displayGuestByPhoneNumber\n"); }
   public void removeGuest() { System.out.println("removeGuest\n"); }

   public static MenuItem[] menu=new MenuItem[]
   {
      new MenuItem("Wyświetl gośći",(party) -> party.displayGuest()),
      new MenuItem("Dodaj gości",(party) -> party.addGuest()),
      new MenuItem("Pokaż posiłki",(party) -> party.showMeals()),
      new MenuItem
      (
         "Znajdź gościa",
         new MenuItem[]
         {
             new MenuItem("Wg nazwiska",(party) -> party.displayGuestBySurname()),
             new MenuItem("Wg telefonu",(party) -> party.displayGuestByPhoneNumber()),
             new MenuItem("Powrót"),
         }
      ),
      new MenuItem("Usuń gościa",(party) -> party.removeGuest()),
      new MenuItem("Wyjście"),
   };
}

class MenuItem
{
   public static interface MenuExecuter { public void execute(Party party); }

   private static Scanner scanner = new Scanner(System.in);
   private String name;
   private MenuExecuter executer;
   private MenuItem[] submenu;

   private MenuItem(String name,MenuExecuter executer,MenuItem[] submenu)
   {
      this.name=name;
      this.executer=executer;
      this.submenu=submenu;
   }

   public MenuItem(String name,MenuExecuter executer) { this(name,executer,null); }
   public MenuItem(String name,MenuItem[] submenu) { this(name,null,submenu); }
   public MenuItem(String name) { this(name,null,null); }

   public static void Run(String name,MenuItem[] submenu,Party party)
   {
      while(true)
      {
         System.out.println("-- "+name+":");
         for(int i=0;i<submenu.length;++i) System.out.println((i+1)+". "+submenu[i].name);
         System.out.print("Wybierz opcję: ");
         try
         {
            int pos=Integer.valueOf(scanner.nextLine());
            if((1<=pos)&&(pos<=submenu.length))
            {
               MenuItem sub=submenu[pos-1];
               if(sub.submenu!=null)
               {
                  String subname=name+" -> "+sub.name;
                  Run(name,sub.submenu,party);
               }
               else if(sub.executer!=null)
               {
                  sub.executer.execute(party);
               }
               else break;
            }
            else System.out.println("Nie ma takiej opcji");
         }
         catch(Exception e)
         {
            System.out.println("Wprowadź właściwy format opcji");
         }
         System.out.println();
     }
   }
}

Uwaga pisano na kolanie.

Zauważ że rozwinięcie na kolejne submenu - bezproblemowo -> wystarczy dodać tabelkę.
Jakieś inne menu w tej samej aplikacji - bezproblemowo -> wystarczy zrobić z MenuItem generic'a.
Przejście na GUI - bezproblemowo -> wystarczy napisać funkcję tworzącą menu wg tabelki i spinającą słownikiem menu z MenuItem

1

Problem masz z tym, że jak Scanner dostanie na wejście coś co nie jest intem, to będzie próbował to przetworzyć za każdym razem, kiedy wywołujesz np. nextInt().

package com.sandbox;

import java.util.InputMismatchException;
import java.util.Scanner;


public class Main {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        Party party = new Party();
        boolean run = true;


        while (run) {
            System.out.println("Wybierz opcję:");
            System.out.println("1 - Wyświetl gośći");
            System.out.println("2 - Dodaj gości");
            System.out.println("3 - Pokaż posiłki");
            System.out.println("4 - Znajdź po numerze telefonu");
            System.out.println("5 - Usuń gościa");
            System.out.println("6 - Wyjście");


            try {
                switch (scanner.nextInt()) {
                    case (1):
                        party.displayGuest();
                        break;

                    case (2):
                        party.addGuest();
                        break;

                    case (3):
                        party.showMeals();
                        break;

                    case (4):
                        party.displayGuestByPhoneNumber();
                        break;

                    case (5):
                        party.removeGuest();
                        break;

                    case (6):
                        run = false;
                        break;
                    default:
                        System.out.println("Wybrałeś nieistniejącą opcję!");//pozbyłem się if'a - to też był błąd np. można było wprowadzić -1
                }
            } catch (InputMismatchException e) {
                System.out.println("Wybrano opcję w nieprawidłowym formacie!");
                scanner.nextLine(); //tego brakowało
            }
        }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1