RISOLTO Problema Java con Scanner

Stato
Discussione chiusa ad ulteriori risposte.

Akrilix

Nuovo Utente
145
32
Ciao a tutti,
per imparare ad usare l'ereditarietà dei metodi e delle classi ho cominciato a scrivere un semplice programmino/giochino:
Ho due classi figlie, "FiatPanda" e "Porsche911", entrambe ereditano da altre due classi genitori ("Veicolo" e "Auto") i metodi e i vari parametri. Questo programmino deve far scegliere all'utente che auto utilizzare e in base a quella scelta si avranno, oltre alle caratteristiche comuni prese da "Veicolo" e "Auto", anche le proprie dell'auto esclusive. Una volta scelta, l'utente seleziona la direzione (S/D), la marcia (R/1/2/...) e la velocità (0-250 KM/H) e in base ai valori inseriti il programma sorteggia randomicamente se l'utente abbia fatto o no un incidente.

ES:
Fiat Panda 2^ marcia a 70 KM/H direzione destra: incidente non avvenuto.
Porsche 911 5^ marcia a 230 KM/H direzione sinistra: incidente avvenuto.

N.B.: i valori delle marce sono fittizi e con l'unico scopo di rendere lo sviluppo più confortevole.

Ad influenzare il random ci sarebbero (sempre io riesca ad implementarli) dei parametri casuali come ad esempio la pioggia, il motore ingolfato (più probabile per la Fiat), guidatore ubriaco, poco traffico...

Non ho ancora fatto niente però, ho solo cominciato a creare i 3 metodi principali nella classe "Veicolo", ma mi esce questo errore:

/---------------------------------------------------------------------------------------------------------------------\
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at Veicolo.numeroMarcia(
Veicolo.java:67)
at Main.main(
Main.java:8)
\ ---------------------------------------------------------------------------------------------------------------------/

Posto qui il codice della classe "Main" e "Veicolo":

Java:
public class Main {
  
    public static void main (String [] args) {
      
        Veicolo testFunzionare = new Veicolo ();
      
        testFunzionare.sinistraDestra();
        testFunzionare.numeroMarcia();
        testFunzionare.kilometriOrari();
      
    }
  
}

Java:
import java.util.Scanner;

public class Veicolo {
  
    private String direzione = "", marciaStringa = "";
    private int marciaNumero = 0, velocità = 0, controlloMarcia = 0, controlloKilometri = 0;
  
    public Veicolo (/*String direzione, int marcia, int velocità*/) {
      
//        this.direzione = direzione;
//        this.marcia = marcia;
//        this.velocità = velocità;
      
    }
  
    public void sinistraDestra () {
      
        Scanner inputValore = new Scanner (System.in);
      
        System.out.print ("In che direzione vorresti andasse la tua auto? [S/D]: ");
      
        do {
          
            direzione = inputValore.next ();
          
            direzione = direzione.toUpperCase ();
          
            if (!direzione.equals ("S") && !direzione.equals ("D"))
                System.out.print ("Hai inserito una direzione SBAGLIATA. [S/D]: ");
          
        } while (!direzione.equals ("S") && !direzione.equals ("D"));
      
        inputValore.close ();
      
    }
  
    public void numeroMarcia () {
      
        Scanner inputValore = new Scanner (System.in);
      
        System.out.print ("Che marcia vorresti usare? [R/1/2/3/4/5]: ");
      
        boolean controlloValore;
      
        do {
          
            controlloValore = inputValore.hasNextInt ();
          
            if (controlloValore) {
              
                marciaNumero = inputValore.nextInt ();
              
                if (marciaNumero < 1 || marciaNumero > 5) {
                  
                    System.out.print ("Hai inserito una marcia SBAGLIATA. [R/1/2/3/4/5]: ");
                  
                    continue;
                  
                }
              
                controlloMarcia = 1;
              
            }
          
            else {
              
                marciaStringa = inputValore.next ();
              
                marciaStringa = marciaStringa.toUpperCase ();
              
                if (!marciaStringa.equals("R")) {
                  
                    System.out.print ("Hai inserito una marcia SBAGLIATA. [R/1/2/3/4/5]: ");
                  
                    inputValore.nextLine ();
                  
                    continue;
                  
                }
              
                controlloMarcia = 2;
              
            }
          
        } while ((marciaNumero < 1 || marciaNumero > 5) && !marciaStringa.equals("R"));
      
        //inputValore.close ();
      
    }
  
    public void kilometriOrari () {
      
        Scanner inputValore = new Scanner (System.in);
      
        System.out.println ("A quanti KM/H vorresti andare? [0 - 250]. ");
        System.out.println ("Marcia R: 0-25.");
        System.out.println ("Marcia 1: 0-50.");
        System.out.println ("Marcia 2: 50-100.");
        System.out.println ("Marcia 3: 100-150.");
        System.out.println ("Marcia 4: 150-200.");
        System.out.println ("Marcia 5: 200-250.");
        System.out.print ("Inserisci QUI: ");
      
        boolean controlloValore;
      
        do {
          
            controlloValore = inputValore.hasNextInt ();
          
            if (controlloValore) {
              
                velocità = inputValore.nextInt ();
              
                if (velocità < 0 || velocità > 250) {
                  
                    System.out.print ("Hai inserito dei KM/H SBAGLIATI. [0-250]: ");
                  
                    continue;
                  
                }
              
                if (controlloMarcia == 1) {
                  
                    switch (marciaNumero) {
                  
                    case 1:
                      
                        if (velocità > 50) {
                            System.out.print ("KM/H non validi per la marcia. [0-50]: ");
                            continue;
                        }
                      
                        System.out.println ("Hai deciso di andare a " + velocità + " KM/H");
                      
                        controlloKilometri ++;
                      
                        break;
                      
                    case 2:
                      
                        if (velocità < 50 || velocità > 100) {
                            System.out.print ("KM/H non validi per la marcia. [50-100]: ");
                            continue;
                        }
                      
                        System.out.println ("Hai deciso di andare a " + velocità + " KM/H");
                      
                        controlloKilometri ++;
                      
                        break;
                  
                    case 3:
                      
                        if (velocità < 100 || velocità > 150) {
                            System.out.print ("KM/H non validi per la marcia. [100-150]: ");
                            continue;
                        }
                      
                        System.out.println ("Hai deciso di andare a " + velocità + " KM/H");
                      
                        controlloKilometri ++;
                      
                        break;
              
                    case 4:
                      
                        if (velocità < 150 || velocità > 200) {
                            System.out.print ("KM/H non validi per la marcia. [150-200]: ");
                            continue;
                        }
                      
                        System.out.println ("Hai deciso di andare a " + velocità + " KM/H");
                      
                        controlloKilometri ++;
                      
                        break;
                      
                    case 5:
                      
                        if (velocità < 200 || velocità > 250) {
                            System.out.print ("KM/H non validi per la marcia. [200-250]: ");
                            continue;
                        }
                      
                        System.out.println ("Hai deciso di andare a " + velocità + " KM/H");
                      
                        controlloKilometri ++;
                      
                        break;
                  
                    }
                  
                }
              
                else {
                  
                    if (velocità > 25) {
                        System.out.print ("KM/H non validi per la marcia. [200-250]: ");
                        continue;
                    }
                  
                    System.out.println ("Hai deciso di andare a " + velocità + " KM/H");
                  
                    controlloKilometri ++;
                  
                }
              
            }
          
            else {
              
                System.out.print ("Hai inserito una LETTERA nel valore. Reinserisci: ");
              
                inputValore.nextLine ();
              
            }
          
        } while ((velocità < 0 || velocità > 250) && controlloKilometri != 1);
      
        inputValore.close ();
      
    }
  
}

Scusate per la mancanza di commenti ma non ho fatto in tempo a metterli.

P.S.: il metodo kilometriOrari non l'ho ancora testato, se ci fossero errori di sintassi è per quello.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Non l'ho eseguito ma ad occhio - anche se sono arrugginito con Java - penso proprio che il problema sia nell'utilizzo che fai di Scanner. Bene il controllo su hasNextInt() prima della lettura, ma quando non è un int (posto che dovresti verificare se esiste il token), tu usi next(). Questo metodo, se non è cambiato nelle ultime release, restituisce il token: questo token però termina sullo spazio. Quindi se vuoi leggere una stringa dovresti richiamare nextLine().

Cito la doc:
A simple text scanner which can parse primitive types and strings using regular expressions.
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.

quindi o leggi una stringa, o puoi anche settare un altro token. Se vuoi usare l'Invio (CRLF), puoi fare:
Java:
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\r\n");



Mi permetti alcune osservazioni?
Le inizializzazioni: usa sempre i costruttori. Se non ti serve dare valori specifici, allora non usarle, ma evita di inizializzarle; avranno i valori di default. Le String saranno a null (in quanto oggetti), mentre gli interi saranno a 0.

L'unico appunto, che è il più importante, è un consiglio per il futuro: tieni sempre presente che i metodi che svolgono un qualche compito, di solito si limitano a quello, e non stampano del testo a video.
Inoltre, quello che è di fatto un menu di scelta, sarebbe meglio inserirlo in un ciclo (magari un do/while) così da gestire anche inserimenti errati, e ripetere nuovamente il menu di scelta.
 

Skills07

Head of Development
Staff Forum
Utente Èlite
35,429
11,501
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
ciao un appunto importante per quando scrivi codice, scrivilo in inglese e non in italiano tipo (classe veicolo falla diventare classe
vehicle). Questo perchè nel momento in cui utilizzerai forum di supporto di alcuni prodotti o librerie e ti chiedono degli esempi vorranno il codice inglessizzato.
 

Akrilix

Nuovo Utente
145
32
@DispatchCode,
innanzitutto grazie per la risposta. Quando apro il computer provo a sistemare e vedere se la soluzione da te indicata funziona. Per quanto riguarda la dichiarazione dei costruttori, purtroppo è un problema grave di abitudine: anche il nostro professore oggi ci ha fatto un enorme cazziatone in quanto nella verifica, oltre a non usare i costruttori, compiliamo più codice nel Main anziché nelle apposite classi con i metodi, perdendo così uno dei punti fondamentali di Java, ovvero gli oggetti, continuando a stilare il codice con uno sviluppo top-down in quanto abituati così con C++. A dire la verità non ho ben capito anch’io come usarli, soprattutto quando è l’utente a inserire i valori. Dovrei fare così?

Java:
public class Main {
  
    public static void main (String [] args) {
        
        testFunzionare.sinistraDestra();
        testFunzionare.numeroMarcia();
        testFunzionare.kilometriOrari();

        Veicolo testFunzionare = new Veicolo (direzione, marciaStringa, marciaNumero, velocità);

    }
  
}

Nella classe “Veicolo” invece dovrei togliere le dichiarazioni all’inizio e de-commentare il costruttore aggiungendo marciStringa e marciaNumero?

Per il menù a scelta penso di farlo in un’altra classe ereditando i metodi.
————————————————
@Skills07
Provvederò a tradurre tutti i nomi in inglese. Sai se esiste un metodo per rinominare tutte le variabili con lo stesso nome in un colpo?
 

Skills07

Head of Development
Staff Forum
Utente Èlite
35,429
11,501
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
quello dipende molto dall'editor che usi
 

Skills07

Head of Development
Staff Forum
Utente Èlite
35,429
11,501
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
dovrebbe essere possibile farlo
 

Akrilix

Nuovo Utente
145
32
Sisi, appena fatto. Grazie del consiglio.
Post unito automaticamente:

@DispatchCode,
ho fatto così, va bene?

Java:
public class Main {
    
    public static void main (String [] args) {
        
        Veicolo testFunzionare = new Veicolo (null, null, 0, 0);
        
        testFunzionare.sinistraDestra();
        testFunzionare.numeroMarcia();
        testFunzionare.kilometriOrari();
        
        System.out.println (testFunzionare.getDirection ());
        //Mi ritorna effettivamente il valore, quindi lo ha salvato.
        
    }
    
}

Java:
import java.util.Scanner;

public class Veicolo {
    
    private String direction, stringTransmission;
    private int numberTransmission, speed, checkTransmission, checkKilometers;
    
    public Veicolo (String direction, String stringTransmission, int numberTransmission, int speed) {
        
        this.direction = direction;
        this.stringTransmission = stringTransmission;
        this.numberTransmission = numberTransmission;
        this.speed = speed;
        
    }

    ...

}

Funzionano così i costruttori?
 
Ultima modifica:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Per quanto riguarda la dichiarazione dei costruttori, purtroppo è un problema grave di abitudine: anche il nostro professore oggi ci ha fatto un enorme cazziatone in quanto nella verifica, oltre a non usare i costruttori, compiliamo più codice nel Main anziché nelle apposite classi con i metodi, perdendo così uno dei punti fondamentali di Java, ovvero gli oggetti, continuando a stilare il codice con uno sviluppo top-down in quanto abituati così con C++. A dire la verità non ho ben capito anch’io come usarli, soprattutto quando è l’utente a inserire i valori.

Nella classe “Veicolo” invece dovrei togliere le dichiarazioni all’inizio e de-commentare il costruttore aggiungendo marciStringa e marciaNumero?

Per il menù a scelta penso di farlo in un’altra classe ereditando i metodi.

Non ha tutti i torti il tuo docente. Anche in C++ è comunque la stessa cosa; solo che purtroppo a scuola viene sempre affrontato dando un'idea sbagliata. Si prende in pratica il C++, gli si toglie la OOP, si tiene "iostream" e lo si trasforma in un misto tra C e C++.

Sisi, appena fatto. Grazie del consiglio.
Post unito automaticamente:

@DispatchCode,
ho fatto così, va bene?

Java:
public class Main {
  
    public static void main (String [] args) {
      
        Veicolo testFunzionare = new Veicolo (null, null, 0, 0);
      
        testFunzionare.sinistraDestra();
        testFunzionare.numeroMarcia();
        testFunzionare.kilometriOrari();
      
        System.out.println (testFunzionare.getDirection ());
        //Mi ritorna effettivamente il valore, quindi lo ha salvato.
      
    }
  
}

Java:
import java.util.Scanner;

public class Veicolo {
  
    private String direction, stringTransmission;
    private int numberTransmission, speed, checkTransmission, checkKilometers;
  
    public Veicolo (String direction, String stringTransmission, int numberTransmission, int speed) {
      
        this.direction = direction;
        this.stringTransmission = stringTransmission;
        this.numberTransmission = numberTransmission;
        this.speed = speed;
      
    }

    ...

}

Funzionano così i costruttori?

Riguardo ai costruttori, vedila così: ha senso passare loro dei parametri quando devi dare un valore iniziale, diverso da quello di default. Nel tuo caso è inutile richiamare il costruttore con quei parametri, in quanto il valore di default è quello che gli passi.
Sarebbe meglio creare un Veicolo senza parametri.

A parte questo, non stai sbagliando. Considera che con le applicazioni testuali è tutta un'altra cosa rispetto alla GUI: ai tempi in cui Swing era la libreria consigliata ed utilizzata maggiormente (ora c'è JavaFx), il main() serviva solo a lanciare il thread della GUI, il quale creava un oggetto per inizializzare la finestra.

Piccolo esempio.
Immagina di avere una classe che gestisce dei Veicoli: questa classe usa un array per memorizzare tutti i veicoli, ma ha una capienza massima: il costruttore di questa classe potrebbe proprio passare questo valore.

Java:
class Veicoli {
    private Veicolo []veicoli;

    Veicoli(int capacity) {
        veicoli = new Veicolo[capacity];
    }
....

comunqe vedendo gli altri aspetti della OOP (ereditarietà e polimorfismo) e facendo pratica, tutto sarà più chiaro in futuro.;)
 

Akrilix

Nuovo Utente
145
32
Ciao, scusa se ti rispondo solo ora ma ho fatto una grande decisione oggi: mi sono preso il libro "Java 11" della Apogeo da affiancare al mio studio. Credo di sfruttare questi giorni prima delle vacanze per dare un mega ripassatone e poi riprendere lo studio verso il 27-28. Sono contento della mia decisione, mi farò vivo presto comunque in caso di altri dubbi.

Buona serata.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Bene, mi fa piacere la tua decisione (non è così frequente notare dell'interesse).
In caso di dubbi durante la lettura, siamo qui.
 
Stato
Discussione chiusa ad ulteriori risposte.

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili