Problema array e linea in più data dallo Scanner nextLine()

di il
6 risposte

Problema array e linea in più data dallo Scanner nextLine()

Questo è l'esercizio in questione:
Calcolare prezzo di vendita di mazzi di fiori. Ci sono cinque tipi di fiori(petunie, viole del pensiero, rose, violette e garofani) che vengono venduti rispettivamente a euro 0,50 - 0,75 - 1,50 - 0,50 - 0,80 per fiore. Creare un array di stringhe che memorizzi il nome di questi fiori. Creare un altro array che memorizzi i prezzi per ogni tipo di fiore. Il programma dovrebbe leggere il nome del fiore e la quantità desiderata dal cliente. Localizzare il nome del fiore nell'array ed utilizzare l'indice per trovare il suo prezzo nell'array dei prezzi. Calcolare e visualizzare il prezzo totale del mazzo di fiori.

Questo è il programma che ho scritto

public static void main(String[] args) {
		double prezzoTotale= 0;
		String risposta = null;
		Scanner tastiera = new Scanner(System.in);
		String[] fiore = {"petunie", "viole", "rose", "violette", "garofani"};
		double[] prezzo = {0.50, 0.75, 1.50, 0.50, 0.80};
		do{
			System.out.println("Quale fiore desidera?");
			System.out.println("Scegliere tra petunie, viole, rose, violette o garofani.");
			String ordine = tastiera.next();
			System.out.println("Quante " + ordine + " vuole?");
			int quantita = tastiera.nextInt();
			for (int i= 0; i<fiore.length; i++) {
				if (fiore[i].equalsIgnoreCase(ordine)) {
					prezzoTotale = prezzoTotale + quantita*prezzo[i];
				}
			}
			System.out.println("Desidera altri fiori?");
			risposta = tastiera.next();
		} while (risposta.equalsIgnoreCase("Si"));	
		System.out.println("Il prezzo totale è di €" + prezzoTotale);
		tastiera.close();
	}
Il fatto è che ho dovuto cambiare viole del pensiero con viole, poiché utilizzando tastiera.nextLine per la string ordine avrei il problema al secondo ciclo della linea in più nel buffer.
Come posso ovviare a questo problema?
Grazie.

6 Risposte

  • Re: Problema array e linea in più data dallo Scanner nextLine()

    SrJustEasy ha scritto:


    Il fatto è che ho dovuto cambiare viole del pensiero con viole, poiché utilizzando tastiera.nextLine per la string ordine avrei il problema al secondo ciclo della linea in più nel buffer.
    Come posso ovviare a questo problema?
    Grazie.
    Così come è scritto adesso il codice vai comunque incontro a InputMismatchException se al posto di interi un utente inserisce ad esempio stringhe.
    Io ti consiglierei di leggere sempre da scanner con nextLine(). In questo modo leggerai sempre l'input completo inserito dall'utente, che sia una parola, un numero, una frase etc.
    Se per una particolare operazione hai bisogno che il valore inserito sia un intero, un double o altro, ti basta usare metodi come Integer.parseInt(String s), Double.parseDouble(String s) etc.

    Questi metodi ricevono una stringa e tentano di restituire il valore numerico inserito all'interno di essa. Ovviamente i metodi "falliscono" (lanciano un'eccezione) se la stringa contiene caratteri illegali per il tipo desiderato.
    Ma questo ti succede anche per come è scritto il codice al momento.
    Non so se hai già visto/puoi utilizzare nell'esercizio un blocco try catch per gestire la possibile eccezione, questa sarebbe la normale prassi: se l'utente inserisce una stringa quando tu ti aspetteresti un intero, ha senso catturare l'eccezione per non far crashare il programma, poi puoi scegliere se terminare il programma mandando un messaggio d'errore, richiedere un nuovo intero o altro...
  • Re: Problema array e linea in più data dallo Scanner nextLine()

    Ansharja ha scritto:


    SrJustEasy ha scritto:


    Il fatto è che ho dovuto cambiare viole del pensiero con viole, poiché utilizzando tastiera.nextLine per la string ordine avrei il problema al secondo ciclo della linea in più nel buffer.
    Come posso ovviare a questo problema?
    Grazie.
    Così come è scritto adesso il codice vai comunque incontro a InputMismatchException se al posto di interi un utente inserisce ad esempio stringhe.
    Io ti consiglierei di leggere sempre da scanner con nextLine(). In questo modo leggerai sempre l'input completo inserito dall'utente, che sia una parola, un numero, una frase etc.
    Se per una particolare operazione hai bisogno che il valore inserito sia un intero, un double o altro, ti basta usare metodi come Integer.parseInt(String s), Double.parseDouble(String s) etc.

    Questi metodi ricevono una stringa e tentano di restituire il valore numerico inserito all'interno di essa. Ovviamente i metodi "falliscono" (lanciano un'eccezione) se la stringa contiene caratteri illegali per il tipo desiderato.
    Ma questo ti succede anche per come è scritto il codice al momento.
    Non so se hai già visto/puoi utilizzare nell'esercizio un blocco try catch per gestire la possibile eccezione, questa sarebbe la normale prassi: se l'utente inserisce una stringa quando tu ti aspetteresti un intero, ha senso catturare l'eccezione per non far crashare il programma, poi puoi scegliere se terminare il programma mandando un messaggio d'errore, richiedere un nuovo intero o altro...
    Capisco il tuo punto di vista, ma in ogni caso se usassi lo scanner nextLine per non incorrere in un InputMismatchException, avrei un errore al passaggio dopo, trasformando la stringa inserita in un intero. No?

    Il blocco try catch ancora non mi è stato presentato nel libro da cui sto studiando, come funziona?

    Ma ricapitolando, come posso ovviare all'errore della linea in più nel buffer utilizzando nextLine()? Non trovo una soluzione
  • Re: Problema array e linea in più data dallo Scanner nextLine()

    SrJustEasy ha scritto:


    se usassi lo scanner nextLine per non incorrere in un InputMismatchException, avrei un errore al passaggio dopo, trasformando la stringa inserita in un intero. No?
    Un "parsing" della stringa c'è comunque, che lo faccia nextInt() o che lo faccia tu con Integer.parseInt. Non puoi, per forza, evitarlo. E se l'input è "malformato" c'è una eccezione (differente a seconda del caso).

    SrJustEasy ha scritto:


    Il blocco try catch ancora non mi è stato presentato nel libro da cui sto studiando, come funziona?
    Allora forse potresti "sorvolare" su questo aspetto e assicurarti di scrivere input non malformato.

    SrJustEasy ha scritto:


    Ma ricapitolando, come posso ovviare all'errore della linea in più nel buffer utilizzando nextLine()? Non trovo una soluzione
    Il problema è un nextInt() seguito da un nextLine(). Se digiti 123<invio>, il nextInt fornisce il valore 123 ma il <invio> resta da analizzare e "consumare" per Scanner. Ad un seguente nextLine(), esso "vede" una riga vuota.
    Quindi: o presti attenzione a questo mix, magari "buttando via" una riga dopo nextInt(), oppure bisognerebbe evitare di mescolare nextLine con gli altri nextXXX. Tutto qui.
  • Re: Problema array e linea in più data dallo Scanner nextLine()

    Il problema è un nextInt() seguito da un nextLine(). Se digiti 123<invio>, il nextInt fornisce il valore 123 ma il <invio> resta da analizzare e "consumare" per Scanner. Ad un seguente nextLine(), esso "vede" una riga vuota.
    Quindi: o presti attenzione a questo mix, magari "buttando via" una riga dopo nextInt(), oppure bisognerebbe evitare di mescolare nextLine con gli altri nextXXX. Tutto qui.
    Come posso buttare via una riga dopo il nextInt()?
    E se invece utilizzassi due Scanner? Uno tastiera, ed uno tastiera2... Potrebbe funzionare?
  • Re: Problema array e linea in più data dallo Scanner nextLine()

    SrJustEasy ha scritto:


    Come posso buttare via una riga dopo il nextInt()?
    E se invece utilizzassi due Scanner? Uno tastiera, ed uno tastiera2... Potrebbe funzionare?
    Ti basta usare un altro next() senza assegnarlo a nulla.
    Evita di utilizzare due Scanner, tecnicamente la cosa funzionerebbe ma non è buona prassi creare più di un oggetto Scanner su System.in, usa sempre lo stesso.
    In ogni caso ti stai complicando la vita per niente, ti abbiamo già detto che il parsing da stringa a intero DEVE essere fatto.

    Se tu usi nextInt() il parsing verrà fatto in automatico, ma se ciò che hai inserito non è un intero il programma crasha. In più hai sempre il problema con il buffer, e sei costretto a ricorrere a un trucchetto per risolvere.

    Se usi nextLine() ti basta convertire la stringa in intero chiamando Integer.parseInt(). In questo modo :

    - Risolvi il problema con il buffer, in quanto leggi la riga intera inserita dall'utente, qualunque cosa lui inserisca prima di digitare invio.
    - Puoi scegliere se risolvere o meno l'errore causato da un inserimento errato. Se scegli di farlo (con il blocco try-catch, o con metodi più "artigiani") eviti di incorrere in errori di inserimento.
    Ma se NON vuoi ancora farlo, il programma NON si complica rispetto a quanto stai facendo ora, ti basta una riga per fare il parsing ed è finita lì, in caso di errore in inserimento il programma crasherà proprio come fa ora.

    Quindi come vedi non ci sono svantaggi nella soluzione consigliata, se non il dover scrivere una trentina di caratteri in più, per il resto risolvi il problema col buffer e volendo puoi anche gestire gli errori
  • Re: Problema array e linea in più data dallo Scanner nextLine()

    Ansharja ha scritto:


    SrJustEasy ha scritto:


    Come posso buttare via una riga dopo il nextInt()?
    E se invece utilizzassi due Scanner? Uno tastiera, ed uno tastiera2... Potrebbe funzionare?
    Ti basta usare un altro next() senza assegnarlo a nulla.
    Evita di utilizzare due Scanner, tecnicamente la cosa funzionerebbe ma non è buona prassi creare più di un oggetto Scanner su System.in, usa sempre lo stesso.
    In ogni caso ti stai complicando la vita per niente, ti abbiamo già detto che il parsing da stringa a intero DEVE essere fatto.

    Se tu usi nextInt() il parsing verrà fatto in automatico, ma se ciò che hai inserito non è un intero il programma crasha. In più hai sempre il problema con il buffer, e sei costretto a ricorrere a un trucchetto per risolvere.

    Se usi nextLine() ti basta convertire la stringa in intero chiamando Integer.parseInt(). In questo modo :

    - Risolvi il problema con il buffer, in quanto leggi la riga intera inserita dall'utente, qualunque cosa lui inserisca prima di digitare invio.
    - Puoi scegliere se risolvere o meno l'errore causato da un inserimento errato. Se scegli di farlo (con il blocco try-catch, o con metodi più "artigiani") eviti di incorrere in errori di inserimento.
    Ma se NON vuoi ancora farlo, il programma NON si complica rispetto a quanto stai facendo ora, ti basta una riga per fare il parsing ed è finita lì, in caso di errore in inserimento il programma crasherà proprio come fa ora.

    Quindi come vedi non ci sono svantaggi nella soluzione consigliata, se non il dover scrivere una trentina di caratteri in più, per il resto risolvi il problema col buffer e volendo puoi anche gestire gli errori
    Perfetto allora, utilizzerò questo metodo. Grazie mille
Devi accedere o registrarti per scrivere nel forum
6 risposte