[Java] 훈련 (입출력 등)

Java 입문 — 훈련

김영한의 자바 입문 강의 내용을 정리한 글이다.

1. Scanner — 사용자 입력

변수, 연산자, 조건문, 반복문은 프로그래밍의 가장 기본이 되는 기능이다. 그런데 지금까지 작성한 프로그램들은 한 가지 한계가 있었다. 코드 안에 값이 고정돼 있어서 실행할 때마다 결과가 같다. 사용자가 어떤 값을 넣느냐에 따라 다르게 동작하는 프로그램을 만들려면 사용자 입력을 받는 방법이 필요하다.

자바에서 출력은 System.out을 사용한다. 입력은 System.in을 사용할 수 있는데, System.in을 직접 다루는 것은 복잡하다. 자바는 이 문제를 해결하기 위해 Scanner 클래스를 제공한다.

Scanner 기본 사용법

package scanner; import java.util.Scanner; public class Scanner1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("문자열을 입력하세요:"); String str = scanner.nextLine(); System.out.println("입력한 문자열: " + str); System.out.print("정수를 입력하세요:"); int intValue = scanner.nextInt(); System.out.println("입력한 정수: " + intValue); System.out.print("실수를 입력하세요:"); double doubleValue = scanner.nextDouble(); System.out.println("입력한 실수: " + doubleValue); } }

Scanner scanner = new Scanner(System.in);Scanner 객체를 생성하는 코드다. 객체와 클래스 개념은 뒤에서 자세히 다루지만, 지금은 "Scanner의 기능을 사용하기 위해 new로 Scanner를 만든다" 정도로 이해하면 된다. 이렇게 만든 scanner 변수를 통해 이후 입력을 받는다.

메서드반환 타입설명
scanner.nextLine()String엔터(\n)를 입력할 때까지 문자열을 읽는다
scanner.nextInt()int정수를 읽는다
scanner.nextDouble()double실수를 읽는다

타입 불일치 시 예외 발생

nextInt()를 호출했을 때 사용자가 숫자가 아닌 값을 입력하면 InputMismatchException이 발생하며 프로그램이 종료된다. 입력 타입을 정확히 맞춰야 한다.

print()와 println()의 차이

입력 안내 메시지를 출력할 때 println() 대신 print()를 사용하는 이유가 있다.

  • print(): 출력 후 줄을 바꾸지 않는다. 커서가 같은 줄에 머무른다.
  • println(): 출력 후 다음 줄로 넘긴다. 내부적으로 문자열 끝에 \n을 추가한다.

"문자열을 입력하세요:" 출력 후 사용자가 같은 줄에 값을 입력하도록 하려면 print()를 사용해야 한다. println()을 쓰면 안내 메시지와 입력 커서가 다른 줄에 놓여 어색해진다.


2. Scanner 기본 예제

예제 1 — 두 수의 합

두 정수를 입력받아 합계를 출력한다.

package scanner; import java.util.Scanner; public class Scanner2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("첫 번째 숫자를 입력하세요:"); int num1 = scanner.nextInt(); System.out.print("두 번째 숫자를 입력하세요:"); int num2 = scanner.nextInt(); int sum = num1 + num2; System.out.println("두 숫자의 합: " + sum); } }

실행 흐름을 따라가면 아래와 같다.

  1. Scanner를 생성해 System.in에 연결한다.
  2. 안내 메시지를 출력하고, nextInt()로 첫 번째 정수를 읽어 num1에 저장한다.
  3. 같은 방식으로 두 번째 정수를 읽어 num2에 저장한다.
  4. num1 + num2를 계산해 sum에 저장하고 출력한다.

예제 2 — 더 큰 수 출력

두 정수를 입력받아 더 큰 수를 출력한다. 두 수가 같으면 "두 숫자는 같습니다."를 출력한다.

package scanner; import java.util.Scanner; public class Scanner3 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("첫 번째 숫자를 입력하세요:"); int num1 = scanner.nextInt(); System.out.print("두 번째 숫자를 입력하세요:"); int num2 = scanner.nextInt(); if (num1 > num2) { System.out.println("더 큰 숫자: " + num1); } else if (num2 > num1) { System.out.println("더 큰 숫자: " + num2); } else { System.out.println("두 숫자는 같습니다."); } } }

if-else if-else 구조로 세 가지 경우를 모두 처리한다. num1 > num2도 아니고 num2 > num1도 아닌 경우는 반드시 두 수가 같은 경우이므로 else에서 처리할 수 있다.


3. Scanner 반복 예제

지금까지 작성한 프로그램은 한 번 실행하고 종료되는 일회성 프로그램이었다. 실제 프로그램은 사용자가 종료를 요청할 때까지 계속 동작한다. while (true)Scanner를 조합하면 반복 입력을 처리하는 프로그램을 만들 수 있다.

반복 예제 1 — 문자열 에코

사용자가 입력한 문자열을 그대로 출력하고, "exit"을 입력하면 종료한다.

package scanner; import java.util.Scanner; public class ScannerWhile1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (true) { System.out.print("문자열을 입력하세요(exit: 종료):"); String str = scanner.nextLine(); if (str.equals("exit")) { System.out.println("프로그램을 종료합니다."); break; } System.out.println("입력한 문자열: " + str); } } }

while (true)는 조건이 항상 참이므로 break를 만나기 전까지 무한 반복한다. 입력받은 문자열이 "exit"와 같은지 비교할 때 ==가 아닌 .equals()를 사용한다. String은 참조 타입이므로 ==로 비교하면 값이 같아도 다른 객체로 인식할 수 있다. 문자열 내용을 비교할 때는 항상 .equals()를 사용해야 한다.

반복 예제 2 — 두 수의 합 반복

두 수를 반복해서 더하는 프로그램이다. 두 수 모두 0을 입력하면 종료한다.

package scanner; import java.util.Scanner; public class ScannerWhile2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("첫 번째 숫자와 두 번째 숫자 모두 0을 입력하면 프로그램을 종료합니다."); while (true) { System.out.print("첫 번째 숫자를 입력하세요:"); int num1 = scanner.nextInt(); System.out.print("두 번째 숫자를 입력하세요:"); int num2 = scanner.nextInt(); if (num1 == 0 && num2 == 0) { System.out.println("프로그램 종료"); break; } int sum = num1 + num2; System.out.println("두 숫자의 합: " + sum); } } }

종료 조건인 num1 == 0 && num2 == 0은 두 조건이 모두 참일 때만 참이 된다. &&는 AND 연산자로, true && truetrue를 반환한다. 하나라도 0이 아니면 반복이 계속된다.

반복 예제 3 — 누적 합계

사용자가 0을 입력할 때까지 정수를 반복해서 입력받고, 입력한 모든 정수의 합계를 출력한다.

package scanner; import java.util.Scanner; public class ScannerWhile3 { public static void main(String[] args) { Scanner input = new Scanner(System.in); int sum = 0; while (true) { System.out.print("정수를 입력하세요 (0을 입력하면 종료): "); int number = input.nextInt(); if (number == 0) { break; } sum += number; } System.out.println("입력한 모든 정수의 합: " + sum); } }

핵심은 sum 변수를 반복문 밖에서 선언하는 것이다. 반복문 안에서 선언하면 루프가 돌 때마다 새로 만들어지므로 이전 값이 사라진다. 누적 합계처럼 반복 사이에 값을 유지해야 하는 경우에는 반복문 바깥에서 변수를 선언하고 초기화해야 한다.

sum += numbersum = sum + number의 단축 표현이다.


4. 문제와 풀이 1

문제 1 — 이름과 나이 입력받고 출력하기

사용자로부터 이름과 나이를 입력받아 "당신의 이름은 [이름]이고, 나이는 [나이]살입니다." 형식으로 출력한다.

학습 포인트: 문자열은 nextLine(), 정수는 nextInt()로 타입에 맞는 메서드를 선택해야 한다. 문자열 연결 연산자 +를 사용해 여러 값을 하나의 출력으로 조합한다.

package scanner.ex; import java.util.Scanner; public class ScannerEx1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("당신의 이름을 입력하세요:"); String name = scanner.nextLine(); System.out.print("당신의 나이를 입력하세요:"); int age = scanner.nextInt(); System.out.println("당신의 이름은 " + name + "이고, 나이는 " + age + "살입니다."); } }

실행 흐름은 다음과 같다.

  1. nextLine()으로 이름을 String 타입으로 읽는다.
  2. nextInt()로 나이를 int 타입으로 읽는다.
  3. + 연산자로 문자열과 정수를 연결해 출력한다. 정수가 +로 문자열과 연결될 때 자바는 자동으로 정수를 문자열로 변환한다.

문제 2 — 홀수 짝수 판별

사용자로부터 정수를 입력받아 홀수인지 짝수인지 판별한다.

학습 포인트: 나머지 연산자 %를 활용해 2로 나눈 나머지가 0이면 짝수, 아니면 홀수로 판별한다.

package scanner.ex; import java.util.Scanner; public class ScannerEx2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("하나의 정수를 입력하세요:"); int number = scanner.nextInt(); if (number % 2 == 0) { System.out.println("입력한 숫자 " + number + "는 짝수입니다."); } else { System.out.println("입력한 숫자 " + number + "는 홀수입니다."); } } }

number % 2number를 2로 나눈 나머지다. 짝수는 2로 나눠 나머지가 0이고, 홀수는 나머지가 1이다. % 2 == 0 조건 하나로 홀수와 짝수 두 경우를 모두 처리할 수 있다.

문제 3 — 음식점 주문

음식 이름, 가격, 수량을 입력받아 총 가격을 계산하고 출력한다.

학습 포인트: 여러 타입의 입력을 순서에 맞게 받고, 산술 연산으로 총 가격을 계산한다. 변수 이름에 의미를 담아 코드의 가독성을 높인다.

package scanner.ex; import java.util.Scanner; public class ScannerEx3 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("음식 이름을 입력해주세요: "); String foodName = input.nextLine(); System.out.print("음식의 가격을 입력해주세요: "); int foodPrice = input.nextInt(); System.out.print("음식의 수량을 입력해주세요: "); int foodQuantity = input.nextInt(); int totalPrice = foodPrice * foodQuantity; System.out.println(foodName + " " + foodQuantity + "개를 주문하셨습니다. 총 가격은 " + totalPrice + "원입니다."); } }

totalPrice는 단가와 수량을 곱한 값이다. int * intint를 반환하므로 총 가격도 int로 받는다. 단, 단가와 수량의 곱이 약 21억을 넘을 가능성이 있다면 long을 사용하는 것이 안전하다.

문제 4 — 구구단 출력

사용자가 입력한 단의 구구단을 1부터 9까지 출력한다.

학습 포인트: 입력받은 값을 for 반복문의 연산에 활용한다. 반복 변수 i와 입력값 n을 곱해 구구단 각 항을 계산한다.

package scanner.ex; import java.util.Scanner; public class ScannerEx4 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("구구단의 단 수를 입력해주세요: "); int n = input.nextInt(); System.out.println(n + "단의 구구단:"); for (int i = 1; i <= 9; i++) { System.out.println(n + " x " + i + " = " + n * i); } } }

for 반복문에서 i는 1부터 9까지 증가한다. 각 반복에서 n * i를 계산해 출력한다. n은 반복 내내 변하지 않고 i만 1씩 증가하므로, 입력한 단의 1배부터 9배까지 순서대로 출력된다.


5. 문제와 풀이 2

문제 1 — 변수 값 교환

a = 10, b = 20이 들어 있을 때, 두 변수의 값을 서로 바꾼다.

학습 포인트: 두 변수의 값을 직접 교환하는 것은 불가능하다. a = b를 먼저 실행하면 a의 원래 값인 10이 사라지기 때문이다. 임시 변수 temp를 사용해 한쪽 값을 먼저 보관한 뒤 교환한다.

package scanner.ex; public class ChangeVarEx { public static void main(String[] args) { int a = 10; int b = 20; int temp; temp = a; a = b; b = temp; System.out.println("a = " + a); System.out.println("b = " + b); } }

교환 과정을 단계별로 따라가면 아래와 같다.

단계코드atempb
초기 상태10(미초기화)20
1단계temp = a101020
2단계a = b201020
3단계b = temp201010

temp가 10을 보관하고 있었기 때문에 마지막 단계에서 b에 원래 a의 값을 정확히 전달할 수 있다. 물리적으로 컵 두 개의 음료를 바꾸려면 빈 컵이 하나 더 필요한 것과 같은 원리다.

10 a 20 b 10 temp 1. temp = a → 2. a = b → 3. b = temp 20 a 10 b

temp를 중간 저장소로 사용해 두 변수의 값을 교환하는 과정

문제 2 — 사이 숫자 출력

두 정수를 입력받아 그 사이의 모든 정수를 쉼표로 구분해 출력한다. 첫 번째 숫자가 두 번째 숫자보다 크면 두 수를 교환해 작은 수부터 출력한다.

학습 포인트: 입력 순서에 관계없이 올바르게 동작하려면 크기 비교 후 교환 로직이 필요하다. 마지막 숫자 뒤에는 쉼표를 출력하지 않도록 조건을 추가한다.

package scanner.ex; import java.util.Scanner; public class ScannerEx5 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("첫 번째 숫자를 입력하세요:"); int num1 = scanner.nextInt(); System.out.print("두 번째 숫자를 입력하세요:"); int num2 = scanner.nextInt(); if (num1 > num2) { int temp = num1; num1 = num2; num2 = temp; } System.out.print("두 숫자 사이의 모든 정수:"); for (int i = num1; i <= num2; i++) { System.out.print(i); if (i != num2) { System.out.print(","); } } } }

출력 형식을 맞추는 부분이 핵심이다. 숫자 출력 후 마지막 숫자(i == num2)가 아닐 때만 쉼표를 출력한다. print()를 사용해 줄바꿈 없이 이어 출력한다.

num1 > num2일 때 교환하면, 이후 for 반복문에서 항상 작은 수(num1)부터 큰 수(num2)까지 순서대로 순회할 수 있다.


6. 문제와 풀이 3

문제 — 이름과 나이 반복 입력

사용자로부터 이름과 나이를 반복해서 입력받아 출력한다. 이름에 "종료"를 입력하면 프로그램을 종료한다.

학습 포인트: nextInt() 이후 nextLine()을 호출하면 버퍼에 남은 줄바꿈 문자를 빈 문자열로 읽어버리는 문제가 발생한다. nextInt() 직후 nextLine()을 한 번 더 호출해 버퍼를 비워야 한다.

package scanner.ex; import java.util.Scanner; public class ScannerWhileEx1 { public static void main(String[] args) { Scanner input = new Scanner(System.in); while (true) { System.out.print("이름을 입력하세요 (종료를 입력하면 종료): "); String name = input.nextLine(); if (name.equals("종료")) { System.out.println("프로그램을 종료합니다."); break; } System.out.print("나이를 입력하세요: "); int age = input.nextInt(); input.nextLine(); System.out.println("입력한 이름: " + name + ", 나이: " + age); } } }

nextInt() 이후 input.nextLine()을 추가로 호출하는 이유를 이해하는 것이 중요하다. nextInt()는 숫자만 읽고 엔터 키(\n)를 버퍼에 남긴다. 다음 루프에서 nextLine()을 호출하면 이 남은 \n을 빈 문자열로 읽어버려 이름 입력이 건너뛰어진다. nextInt() 직후 nextLine()을 한 번 호출해 버퍼에 남은 줄바꿈을 소비하면 다음 루프에서 정상적으로 이름을 입력받을 수 있다.

상황버퍼 상태결과
nextInt() 호출 후\n 남아 있음다음 nextLine()이 빈 문자열을 읽음
nextInt()nextLine() 추가버퍼 비워짐다음 nextLine()이 정상적으로 입력을 기다림

7. 정리

개념핵심 내용
Scanner 생성new Scanner(System.in)으로 생성, import java.util.Scanner 필요
문자열 입력nextLine() — 엔터까지 한 줄 전체를 읽는다
정수 입력nextInt()int 타입으로 읽는다
실수 입력nextDouble()double 타입으로 읽는다
문자열 비교== 대신 .equals() 사용
무한 반복 + 탈출while (true) + break
버퍼 비우기nextInt()nextLine() 한 번 추가
변수 교환임시 변수 temp 필요
누적 합계누적 변수를 반복문 밖에서 선언

'Study > Java' 카테고리의 다른 글

[Java] 메소드(method)  (0) 2026.04.05
[Java] 배열  (0) 2026.04.05
[Java] 스코프, 형변환  (0) 2026.04.04
[Java] 반복문  (0) 2026.04.04
[Java] 조건문  (0) 2026.04.04