Problem z wejściem typu "String"

0

Poniżej podałem kod programu mającego za zadanie obliczyć pole i obwód koła używając parametrów (długości i jednostki) wprowadzanych z klawiatury. Problem pojawił się w momencie gdy chcę aby użytkownik wprowadził jednostkę długości promienia. Program działa tak jakby ignorował linijkę:

 String jednostkaPromienia = in.nextLine();

Proszę o ewentualne podpowiedzi dotyczące zmiany kodu źródłowego, poprawek czy udogodnień.

import java.util.Scanner;

class koło
{
	private double promień;
	
	public koło(double r,String j)
	{
		promień=r;
		if(j.equals("km"))
		{
			promień=promień*1000;
		}
		else if(j.equals("cm"))
		{
			promień=promień/100;
		}
		else if(j.equals("mm"))
		{
			promień=promień/1000;
		}
	}
	public double obliczObwódKoła()
	{
		return 2*Math.PI*promień;
	}
	public double obliczPoleKoła()
	{
		return Math.PI*promień*promień;
	}
	public double getPromień()
	{
		return promień;
	}
}

public class KlasaKoło
{
	public static void main(String[] args)
	{
	Scanner in = new Scanner(System.in);
	System.out.println("Podaj długość promienia koła");
	double promieńKoła= in.nextDouble();
	System.out.println("Podaj jednoskę długości promienia koła");
	String jednostkaPromienia = in.nextLine();
	
	koło koło = new koło(promieńKoła, jednostkaPromienia);
	System.out.println("Długość promienia to "+koło.getPromień()+" m");
	System.out.println("Pole wyosi "+koło.obliczPoleKoła());
	System.out.println("Obwód wyosi "+koło.obliczObwódKoła());
	}
}
1

Metoda nextDouble czyta tylko liczbę, pozostawia w buforze klawiatury całą resztę wpisaną przez użytkownika. Ta reszta nigdy nie jest pusta - zawiera co najmniej ENTER. Kolejne wywołanie nextLine nie czeka na nowe dane, czyta to co jest w buforze. Musisz ten bufor wyczyścić.

    double promieńKoła= in.nextDouble();
    in.nextLine();
    System.out.println("Podaj jednoskę długości promienia koła");
    String jednostkaPromienia = in.nextLine(); 

Ja bym podpowiedział użytkownikowi jakie jednostki obsługuje program.

 System.out.println("Podaj jednostkę długości promienia koła (cm, mm, km)");
0

I jeszcze jedno pytanie
Dzieje się tak tylko przy wykorzystaniu metody nextDouble. Czy w przypadku innych np : nextInt czy nextFloat też trzeba wyczyścić bufor ?

1

z innymi metodami typu nextInt itp dzieje się tak samo.

ja osobiście wole wczytywać wszystko do String a następnie to konwertować np.

 ...

String data = in.nextLine();

int a = Integer.parseInt(data);
1

Przy każdej różnej od nextLine. Każda z nich czyta tyle ile potrzebuje, resztę (a w niej ENTER) zostawia w buforze.

0

można też wczytać drugą zmienną metodą next() zamiast nextLine() i po kłopocie :) - nie potrzebna Ci cała linia tylko ta jedna wartość, dobrym nawykiem jest też zamykanie zasobów: in.close();

0

Nie ucz złych nawyków. Scannera czytającego z klawiatury nie potrzeba zamykać, co więcej jego zamykanie jest potencjalnie niebezpieczne.

0

no ok, tylko nie bardzo wiem po co mi ten skaner jeszcze w tym wypadku - przecież kończymy program, pobraliśmy dane, wypisaliśmy wynik , finito.

  • nawet IDE będzie krzyczeć "resource leak" , jak go nie zamkniesz
0

IDE krzyczy bo jest głupie i nie rozróżnia co jest "skanowane". Skoro pobrałeś dane i kończysz program, to nie ma znaczenia czy zamkniesz skaner. A jeśli nie kończysz, to możesz próbować odczytać nowe dane i lepiej żeby skaner nie został zamknięty.

0

Myślę, że wszystko sprowadza się do odpowiedzi na pytanie czy dany zasób będzie jeszcze potrzebny czy nie, jeśli nie imo można i należy zamykać, w naszym przypadku faktycznie nie trzeba jawnie - zrobi to VM.
Masz rację , że zamykając scanner zamykasz też stream z którego ten scanner czyta - czasami będzie to ok, czasem nie , wszystko zależy od powyższego.

Jest możliwy sposób obejścia tego problemu dzięki klasie CloseShieldInputStream , która zabezpiecza przed zamknięciem streama, przy np. przypadkowym zamknięciu scannera

https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/input/CloseShieldInputStream.html

Scanner in = new Scanner(new CloseShieldInputStream(System.in));
//operacje 
in.close();
//System.in nadal dostępny

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