[Java] metodi hasNextLine() e next()

Messaggioda Usernamer » 22/11/2014, 11:28

Buongiorno a tutti, qualcuno sa dirmi come mai eseguendo il seguente codice:

Codice:
import java.util.Scanner;
public class Prova
{public static void main(String[] args)
  {Scanner console = new Scanner(System.in);
   
   while (console.hasNextLine())
     {System.out.println("premi");
      String r = console.next();}
  }
}

come mai quando digito il primo input, restituisce "premi" due volte?
dal secondo input che digito in poi scrive "premi" una volta sola come volevo che facesse.

inoltre quando digito "ctrl+Z" anzichè terminare il ciclo lancia l'eccezione NoSuchElementException quando in teoria dovrebbe restituire false a console.hasNextLine()
Usernamer
Junior Member
Junior Member
 
Messaggio: 18 di 272
Iscritto il: 07/10/2014, 10:18

Re: [Java] metodi hasNextLine() e next()

Messaggioda anonymous_be1147 » 23/11/2014, 00:54

Ciao, c'è una particolare ragione per cui, invece di
console.next()
, non usi
console.nextLine()
, visto che fai dipendere l'esecuzione del ciclo dalla presenza di una riga successiva?.

Testo nascosto, perché contrassegnato dall'autore come fuori tema. Fai click in quest'area per vederlo.
Ti ho editato il post in modo da visualizzare meglio il codice. Se dovesse capitare, la prossima volta puoi farlo direttamente tu selezionando il codice con il mouse e premendo il pulsantino
[ Code ]
nell'editor, prima di inviare il messaggio. :-)
anonymous_be1147
Cannot live without
Cannot live without
 
Messaggio: 1265 di 3226
Iscritto il: 02/03/2006, 20:20

Re: [Java] metodi hasNextLine() e next()

Messaggioda Usernamer » 27/11/2014, 00:42

Non c'è una particolare ragione, stavo solo facendo delle prove perché sto imparando le basi di programmazione e volevo testare il comportamento dei metodi has... nei vari casi
Usernamer
Junior Member
Junior Member
 
Messaggio: 23 di 272
Iscritto il: 07/10/2014, 10:18

Re: [Java] metodi hasNextLine() e next()

Messaggioda anonymous_be1147 » 27/11/2014, 01:47

Capito. Ad ogni modo se sostituisci
next()
con
nextLine()
dovrebbe funzionare come t'aspetti.
anonymous_be1147
Cannot live without
Cannot live without
 
Messaggio: 1271 di 3226
Iscritto il: 02/03/2006, 20:20

Re: [Java] metodi hasNextLine() e next()

Messaggioda Usernamer » 28/11/2014, 16:29

Una cosa non capisco: in teoria hasNextLine() non dovrebbe restituire false se nel flusso d'ingresso non c'è un'altra linea?
e dato che è la condizione del ciclo e che prima di entrare nel ciclo non scrivo nulla nel flusso d'ingresso non dovrebbe essere fin da subito la condizione false e dunque non eseguire per nulla il ciclo?
Usernamer
Junior Member
Junior Member
 
Messaggio: 28 di 272
Iscritto il: 07/10/2014, 10:18

Re: [Java] metodi hasNextLine() e next()

Messaggioda Usernamer » 28/11/2014, 19:03

Un'altra domanda sempre riguardo i metodi has: testando il codice seguente vorrei che dopo aver digitato "d" e vado a capo mi riscrivesse la linea "comando ecc" come fa quando scrivo altre lettere, invece come puoi vedere nello screenshot allegato se digito "d" mi chiede altri valori e poi scrive la linea "comando". (a meno che io non inserisca due volte "d" allora dopo se continuo a inserire "d" chiederà "comando" una sola volta, e lo richiederà due volte quando inserisco un'altra lettera non"d")... come mai? La parte del codice che riguarda "d" l'ho messa in rosso.
Metto il codice 2 volte così in una è impaginato e nell'altra è possibile vedere in rosso la parte riguardante la "d" problematica

Codice:
import java.util.Scanner;

public class BankAccountTester
{public static void main(String[] args)
  {Scanner console = new Scanner(System.in);
   char quit = 's';
   BankAccount bankAccount = new BankAccount();

   while(quit != 'Q')
     {try
        {System.out.println("Comando? (Q. B, D, W, A)");
         String s = console.next();

         if(s.equalsIgnoreCase("q"))
           {String s1=console.nextLine(); if(s1.equals(""))
              {quit = 'Q';
               System.out.println("Arrivederci");
              }
            else
               console.nextLine();
           }

         else if(s.equalsIgnoreCase("b"))
           {String s1=console.nextLine(); if(s1.equals(""))
              System.out.println(bankAccount.getBalance());
           else
              console.nextLine();
           }

         else if(s.equalsIgnoreCase("d"))
           {if(console.hasNextDouble())
              {double x = console.nextDouble();
               String s1 = console.nextLine();
                  if(s1.equals("") && bankAccount.deposit(x))
                    System.out.println("Versamento effettuato: " + x);
                  else if(s1.equals("") && !bankAccount.deposit(x))
                    System.out.println("Versamento non corretto");
              }
            else
               console.nextLine();
           }

         else if(s.equalsIgnoreCase("w"))
           {if(console.hasNextDouble())
              {double x = console.nextDouble();
               String s1 = console.nextLine();
                  if(s1.equals("") && bankAccount.withdraw(x))
                    System.out.println("Prelievo effettuato: " + x);
                  else if(s1.equals("") && !bankAccount.withdraw(x))
                    System.out.println("Prelievo non corretto");
              }
            else
               console.nextLine();
           }

         else if(s.equalsIgnoreCase("a"))
           {if(console.hasNextDouble())
              {double x = console.nextDouble();
               String s1 = console.nextLine();
                  if(s1.equals(""))
                    {bankAccount.addInterest(x);
                     System.out.println("Interessi calcolati e accreditati: " + x);
                    }
              }
            else
               console.nextLine();
           }
         else
           {}
        } /*catch(java.util.InputMismatchException exc)
             {console.nextLine();
             }*/
          catch(java.util.NoSuchElementException ex)
             {System.exit(1);
             }
     }
  }
}


import java.util.Scanner;

public class BankAccountTester
{public static void main(String[] args)
{Scanner console = new Scanner(System.in);
char quit = 's';
BankAccount bankAccount = new BankAccount();

while(quit != 'Q')
{try
{System.out.println("Comando? (Q. B, D, W, A)");
String s = console.next();

if(s.equalsIgnoreCase("q"))
{String s1=console.nextLine(); if(s1.equals(""))
{quit = 'Q';
System.out.println("Arrivederci");
}
else
console.nextLine();
}

else if(s.equalsIgnoreCase("b"))
{String s1=console.nextLine(); if(s1.equals(""))
System.out.println(bankAccount.getBalance());
else
console.nextLine();
}

else if(s.equalsIgnoreCase("d"))
{if(console.hasNextDouble())
{double x = console.nextDouble();
String s1 = console.nextLine();
if(s1.equals("") && bankAccount.deposit(x))
System.out.println("Versamento effettuato: " + x);
else if(s1.equals("") && !bankAccount.deposit(x))
System.out.println("Versamento non corretto");
}
else
console.nextLine();
}


else if(s.equalsIgnoreCase("w"))
{if(console.hasNextDouble())
{double x = console.nextDouble();
String s1 = console.nextLine();
if(s1.equals("") && bankAccount.withdraw(x))
System.out.println("Prelievo effettuato: " + x);
else if(s1.equals("") && !bankAccount.withdraw(x))
System.out.println("Prelievo non corretto");
}
else
console.nextLine();
}

else if(s.equalsIgnoreCase("a"))
{if(console.hasNextDouble())
{double x = console.nextDouble();
String s1 = console.nextLine();
if(s1.equals(""))
{bankAccount.addInterest(x);
System.out.println("Interessi calcolati e accreditati: " + x);
}
}
else
console.nextLine();
}
else
{}
} /*catch(java.util.InputMismatchException exc)
{console.nextLine();
}*/
catch(java.util.NoSuchElementException ex)
{System.exit(1);
}
}
}
}
Allegati
Immagine.jpg
(43.41 KiB) Mai scaricato
Usernamer
Junior Member
Junior Member
 
Messaggio: 29 di 272
Iscritto il: 07/10/2014, 10:18

Re: [Java] metodi hasNextLine() e next()

Messaggioda anonymous_be1147 » 29/11/2014, 03:18

Usernamer ha scritto:Una cosa non capisco: in teoria hasNextLine() non dovrebbe restituire false se nel flusso d'ingresso non c'è un'altra linea?
e dato che è la condizione del ciclo e che prima di entrare nel ciclo non scrivo nulla nel flusso d'ingresso non dovrebbe essere fin da subito la condizione false e dunque non eseguire per nulla il ciclo?

No, perché, se non c'è nulla in input, questa funzione blocca l'esecuzione del programma e si mette in attesa:

public boolean hasNextLine()

Returns true if there is another line in the input of this scanner. This method may block while waiting for input. The scanner does not advance past any input.

https://docs.oracle.com/javase/7/docs/a ... sNextLine()


Usernamer ha scritto:Un'altra domanda sempre riguardo i metodi has: testando il codice seguente vorrei che dopo aver digitato "d" e vado a capo mi riscrivesse la linea "comando ecc" come fa quando scrivo altre lettere

Be', ma non è quello che richiedi nel programma:

Codice:
 10         {try
 11             {System.out.println("Comando? (Q. B, D, W, A)");
 12                 String s = console.next();
 ...
 30              else if(s.equalsIgnoreCase("d"))
 31                 {if(console.hasNextDouble())
 32                     {double x = console.nextDouble();
 33                         String s1 = console.nextLine();
 34                         if(s1.equals("") /*&& bankAccount.deposit(x)*/)
 35                             System.out.println("Versamento effettuato: " + x);
 36                         else if(s1.equals("") /*&& !bankAccount.deposit(x)*/)
 37                             System.out.println("Versamento non corretto");
 38                     }
 39                     else
 40                         console.nextLine();
 41                 }
...
 76         }

Il programma stampa il prompt (riga 11).

Poi inizia a leggere l'input (riga 12). Siccome non c'è ancora nulla, si mette in attesa (anche
scanner.next()
è infatti una funzione bloccante).

A questo punto tu immetti la lettera d seguita da INVIO, e il tuo input è allora
d\n
1.

La funzione
next()
legge allora la lettera d e la "pone" nella variabile s. L'input "contiene" adesso solo un newline
\n
.

Il programma prosegue con i vari controlli del valore della variabile s, e trova una condizione vera alla riga 30.

Il programma esegue allora il controllo alla riga 31. Siccome il tuo input non contiene nessun token, la funzione
scanner.nextDouble()
resta in attesa di ulteriore input. Se immetti un double, allora il programma esegue il blocco relativo e stampa nuovamente il prompt. Supponiamo invece che tu immetta nuovamente d o una qualsiasi altra lettera, che non sia possibilmente uno degli altri comandi. Allora il tuo input conterrà:
\nd\n
. La predetta funzione restituirà
false
e il programma salterà alla riga 40.

Viene eseguita perciò la funzione
scanner.nextLine()
, che leggerà tutti i caratteri fino al successivo newline .Viene perciò di fatto eliminato il primo newline e Il tuo input conterrà ora
d\n
.

A questo punto il programma torna alla riga 11 e stampa di nuovo il prompt. Questa volta la funzione
next()
non attende, ma legge subito la lettera immessa precedentemente e il programma "salta" alla riga 31, ponendosi in attesa, perché non sono disponibili ulteriori token. Il tuo input contiene infatti solo un newline. A questo punto, a meno che non immetti un double, il programma leggerà la successiva riga, e il tuo input conterrà quello che avrai appena immesso.

Viene nuovamente stampato il prompt. La funzione
next()
legge la lettera o il token immesso etc, etc...

Ti pare più chiaro ora perché non stampa subito il prompt dopo la prima lettera d? :)

P.S. A essere sinceri, il programma è piuttosto contorto, ma è normale se sei solo agli inizi della programmazione. Se è così, il mio consiglio è di stamparlo, se non ce l'hai già su carta, e di eseguirlo tu manualmente, inserendo a fianco di ogni istruzione che incontri il contenuto corrente dell'input. Sarà più facile individuare eventuali bug e capire se è quello che effettivamente vuoi ottenere dal programma. :wink:

Note

  1. Sul tuo sistema (Windows) sarà probabilmente
    d\r\n
    , ma è un dettaglio
anonymous_be1147
Cannot live without
Cannot live without
 
Messaggio: 1273 di 3226
Iscritto il: 02/03/2006, 20:20

Re: [Java] metodi hasNextLine() e next()

Messaggioda Usernamer » 29/11/2014, 14:11

Sì grazie mille, ora è più chiaro :D

1)quindi per token si intende una sequenza di caratteri non contenente \n o spazio o tabulazione?

2)Inoltre metodi hasNextInt() e hasNextDouble() se nell'input trovano solo spazi e/o \n pur non essendo qui caratteri degli int/double non restituiscono false e bloccano il programma in attesa che io inserisca un input?
E analogamente hasNextLine() blocca tutto in attesa di input se non c'è un input (anziché dare false) e lo stesso hasNext()?

3) cosa significa metodo bloccante?
Usernamer
Junior Member
Junior Member
 
Messaggio: 31 di 272
Iscritto il: 07/10/2014, 10:18

Re: [Java] metodi hasNextLine() e next()

Messaggioda anonymous_be1147 » 30/11/2014, 02:12

Usernamer ha scritto:1)quindi per token si intende una sequenza di caratteri non contenente \n o spazio o tabulazione?

Detto in modo molto approssimativo, sì.

2)Inoltre metodi hasNextInt() e hasNextDouble() se nell'input trovano solo spazi e/o \n pur non essendo qui caratteri degli int/double non restituiscono false e bloccano il programma in attesa che io inserisca un input?
E analogamente hasNextLine() blocca tutto in attesa di input se non c'è un input (anziché dare false) e lo stesso hasNext()?

Esatto.

3) cosa significa metodo bloccante?

È quello che hai detto tu prima: è un metodo che blocca l'esecuzione del programma (più propriamente di un thread), finché una qualche condizione non si verifica o un'altra operazione non termina.
anonymous_be1147
Cannot live without
Cannot live without
 
Messaggio: 1275 di 3226
Iscritto il: 02/03/2006, 20:20

Re: [Java] metodi hasNextLine() e next()

Messaggioda Usernamer » 30/11/2014, 21:53

grazie mille!
Usernamer
Junior Member
Junior Member
 
Messaggio: 32 di 272
Iscritto il: 07/10/2014, 10:18


Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite