요리의 레시피 메모장을 만들어 보려 합니다. 좋아하는 요리의 제목을 입력하고, 요리의 별점을 1~5 사이의 소수점으로 입력합니다. 그리고 요리의 레시피를 10 문장 입력하면 요리의 제목을 괄호로 감싸서 출력해 주고, 요리의 별점을 소수점을 제외한 정수로 출력하여 5점 만점의 퍼센트로 출력해주고자 합니다. 그리고 입력한 레시피 10 문장 앞에 번호를 붙여서 출력해 주는 프로그램을 만들어 보고자 합니다.
반복문이나 자료구조를 사용하지않고 단순한 입력을 통해서 출력해 주는 간단한 프로그램을 구상해 보았습니다. `Scanner`를 사용하여 문장을 입력받고, 입력받은 문장을 `String`변수에 저장해 주고 출력해 주는 단순한 로직을 구상하였습니다.
요리의 별점은 `double`형 변수에 넣어주어 퍼센테이지 계산을 위해 `int`형으로 형 변환을 해주는 과정을 거쳐야겠다고 생각한 후 코드를 작성해 보았습니다.
발생한 문제점
//문제가 발생한 코드
String title = sc.nextLine();
Double rate = sc.nextDouble();
String recipe1 = sc.nextLine();
레시피를 입력받을 때 위의 코드와 같이 `sc.nextDouble()`형으로 받게 되면 출력할때 레시피 첫 번째가 공백으로 출력되는 오류가 발생하였습니다.
찾아보니 `nextDouble()`는 버퍼의 내용을 가져올 때 분리자인 개행문자('\n')을 제외하고 가져오기 때문에 분리자를 포함시켜서 가져오는 `nextLine()`이 버퍼에 남아있는 개행문자('\n')를 가져오며 문자열을 읽어오기 때문에 발생한 오류였습니다.
이러한 차이는 `next()`와 `nextLine()`의 차이점과 같았습니다.
next(), nextLine() 차이점
next(), nextLine()은 Scanner 클래스의 주요 메소드로 둘 다 문자열을 반환시켜 주는 공통점이 있습니다. 하지만 두 메서드의 차이점은 분리자를 포함하느냐 포함하지 않느냐의 차이점이 있습니다.
- next()
- 공백(' ', '\t', '\n') 전까지의 문자열을 입력받아 반환한다.
- 콤마(','), 공백(' '), 개행문자('\n', 엔터)를 기준으로 문자열을 반환한다.
- 문자열을 반환받을때 위의 분리자 전까지만 입력받기 때문에 공백등이 입력되지 않는다.
- nextLine()
- 버퍼에서 개행문자('\n', 엔터)를 포함하는 문자열을 읽어와서 개행문자('\n', 엔터)를 버린 나머지를 반환한다.
즉, 공백과 개행문자인 분리자를 포함시켜서 문자열을 들고 온다. - 공백이 낀 문자열을 읽어올 수 없는 next()와 달리 공백이 낀 문자열을 읽어올 수 있다.
→ 개행문자(\n, 엔터)까지의 문자열 전체를 받아 올 수 있다.
- 버퍼에서 개행문자('\n', 엔터)를 포함하는 문자열을 읽어와서 개행문자('\n', 엔터)를 버린 나머지를 반환한다.
그렇기 때문에 nextLine()은 <Enter> 키의 입력을 기다리는 용도로 사용할 수 있다. nextLine()은 다른 입력 없이 <Enter> 키만 입력될 때, 빈 문자열("")을 반환할 수 있지만, next()는 <Enter> 키를 계속 입력하여도 문자열이나 숫자 등 다른 키가 입력될 때까지 기다린다. 즉, next()는 결코 빈 문자열("")을 반환할 수 없다.
`nextByte()`, `nextShort()`, `nextInt()`, `nextLong()`, `nextFloat()`, `nextDouble()`, `nextBoolean()`등의 메서드들이 `next()`와 같은 원리로 공백(" ")과 개행문자('\n', 엔터)를 포함하지 않기 때문에 이러한 메소드 뒤에 `nextLine()` 메서드를 사용하게 되면 빈 문자열을 반환하게 된다.
문제점을 해결하여 작성한 코드
/*요리 레시피 메모장 만들기
입력값
내가 좋아하는 요리 제목을 먼저 입력합니다.
요리 별점을 1~5 사이의 소수점이 있는 실수로 입력해 주세요. (ex. 3.5)
이어서 내가 좋아하는 요리 레시피를 한 문장씩 10문장을 입력합니다.
출력값
입력이 종료되면 요리 제목을 괄호로 감싸서 먼저 출력해 줍니다.
이어서, 요리 별점을 소수점을 제외한 정수로만 출력해 줍니다. (ex. 3)
바로 뒤에 정수 별점을 5점 만점 퍼센트로 표현했을 때 값을 실수로 출력해 줍니다. (ex. 60.0%)
이어서, 입력한 모든 문장 앞에 번호를 붙여서 모두 출력해 줍니다.*/
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//입력받을 스캐너 생성
Scanner sc = new Scanner(System.in);
//입력
String title = sc.nextLine();
String rate = sc.nextLine();
String recipe1 = sc.nextLine();
String recipe2 = sc.nextLine();
String recipe3 = sc.nextLine();
String recipe4 = sc.nextLine();
String recipe5 = sc.nextLine();
String recipe6 = sc.nextLine();
String recipe7 = sc.nextLine();
String recipe8 = sc.nextLine();
String recipe9 = sc.nextLine();
String recipe10 = sc.nextLine();
//별점
double tempNumber = Double.parseDouble(rate);
int starNumber = (int)tempNumber;
//퍼센트
double percent = starNumber * 100/5;
//출력
System.out.println("[ " + title + "]");
System.out.println("별점 : "+ starNumber + "("+percent+"%)");
System.out.println("1. "+recipe1);
System.out.println("2. "+recipe2);
System.out.println("3. "+recipe3);
System.out.println("4. "+recipe4);
System.out.println("5. "+recipe5);
System.out.println("6. "+recipe6);
System.out.println("7. "+recipe7);
System.out.println("8. "+recipe8);
System.out.println("9. "+recipe9);
System.out.println("10. "+recipe10);
}
}
실수의 점수를 입력받을 때 `nextLine()`을 이용하여 문자열로 입력을 받아 저장한 후 Wrapper 클래스 메서드 `parseDouble()`을 이용하여 문자열을 `double`형으로 형변환을 해준 후 `int`형으로 한차례 더 형변환을 해주어서 별점과 퍼센트를 구하는 방식으로 문제 점을 해결할 수 있었습니다.
입력값
출력값
위와 같이 잘 출력되는 것을 확인할 수 있습니다.
'수수한 코딩세상 > Java' 카테고리의 다른 글
[Java] 문자열(String)로 알아보는 == 연산자와 equals() 메서드 차이 (0) | 2024.07.29 |
---|---|
[Java] 자바에서 입력 받는 방법 System.in & Scanner 클래스 (0) | 2024.07.26 |
[Java] 랜덤 닉네임 생성기 (1) | 2024.06.19 |
[Java] Java 란? (0) | 2024.06.18 |
[Java] IntelliJ 설치방법 (0) | 2024.04.24 |