문제: 숫자와 사칙연산을 사용하지 않고 변수 a와 b의 값을 서로 뒤바꾸기.
class Main {
public static void main(String[] args) {
int a = 5;
int b = 10;
// 임시 보관함 c를 생성하여 값 교환
int c = a;
a = b;
b = c;
System.out.println("a : " + a);
System.out.println("b : " + b);
}
}
핵심 개념 및 주의사항:
대입 연산자(=): 프로그래밍에서 =은 "똑같다"는 뜻이 아니라 "오른쪽의 값을 왼쪽 공간에 집어넣는다(대입한다)"는 뜻이다.
이동 방향: 무조건 오른쪽에서 왼쪽으로만 움직인다.
덮어쓰기: 변수에 새로운 값이 들어오면 기존에 있던 값은 흔적도 없이 사라진다. 따라서 두 변수의 값을 교환할 때는 기존 값을 잠시 담아둘 c와 같은 임시 보관함(변수)이 반드시 필요하다.
문제: 1부터 100까지 숫자 중 4의 배수이면서 6의 배수인 숫자 출력하기.
class Main {
public static void main(String[] args) {
int count = 0;
for (int i = 1; i <= 100; i++) {
// 4의 배수이면서 동시에 6의 배수인 조건
if (i % 4 == 0 && i % 6 == 0) {
System.out.println("4와 6의 공배수 : " + i);
count++;
}
}
}
}
오답 노트:
조건의 중첩 (AND 연산자 미사용): 4의 배수를 찾는 if문 안에 6의 배수를 찾는 반복문을 다시 넣으면 중복 출력이 발생한다. "4의 배수이면서 6의 배수"는 하나의 변수 i가 두 조건을 동시에 만족하는지 확인해야 하므로 && (AND) 연산자를 사용해야 한다.
불필요한 이중 반복문: 변수 두 개(i, l)를 각각 100번씩 돌리면 총 10,000번의 연산이 발생한다. 1부터 100까지 한 번만 훑으며 조건(4로 나누어 떨어지고 6으로도 나누어 떨어지는가)을 검사하는 단일 for문이면 충분하다.
문제: 가로로 별 5개, 세로로 5줄이 나오는 정사각형 만들기.
class Main {
public static void main(String[] args) {
int i = 1;
while (i <= 5) { // 세로로 5줄을 만드는 바깥쪽 반복문
int l = 1;
while (l <= 5) { // i 대신 5를 넣어 매 줄마다 별이 5개씩 고정으로 찍히게 한다.
System.out.print("*"); // println 대신 print를 써야 줄바꿈 없이 가로로 출력된다.
l++;
}
System.out.println(); // 안쪽 반복문이 끝나면 줄바꿈을 해준다.
i++;
}
}
}
핵심 개념:
안쪽 반복문의 조건을 l <= i로 설정하면 줄이 바뀔 때마다 별의 개수가 증가하여 직각 삼각형이 된다. 정사각형을 만들려면 안쪽 반복문이 무조건 5번씩 실행되도록 숫자 5로 고정해야 한다.
출력 메서드 차이:
print: 텍스트 출력 후 줄바꿈을 하지 않는다.
println: 텍스트 출력 후 줄바꿈(Enter)을 수행한다.
printf: 변수를 양식에 맞게 포맷팅하여 출력한다. (자동 줄바꿈이 없으므로 직접 \n을 넣어야 한다.)
문제: 정수 10개를 저장할 수 있는 배열에 10부터 100까지 저장하고 총합과 평균 출력하기.
class Main {
public static void main(String[] args) {
int[] arr = new int[10];
// 총합을 누적해서 담아둘 변수 준비 (반복문 시작 전 선언 필수)
int sum = 0;
for(int i = 0; i < arr.length; i++) {
arr[i] = (i + 1) * 10;
sum = sum + arr[i]; // 배열에 넣은 값을 sum에 누적
}
System.out.println("총합 = " + sum);
System.out.println("평균 = " + (sum / 10));
}
}
class Main {
public static void main(String[] args) {
int[] numbers = {20, 10, 35, 30, 7};
// 첫 번째 방의 값을 초기 기준으로 설정한다.
int max = numbers[0];
int min = numbers[0];
// 에러 방지: <= 가 아니라 < 를 사용해야 배열의 범위(0~4)를 벗어나지 않는다.
for (int i = 0; i < numbers.length; i++) {
if (max < numbers[i]) {
max = numbers[i];
}
if (min > numbers[i]) {
min = numbers[i];
}
}
System.out.println("MAX = " + max);
System.out.println("MIN = " + min);
}
}
문제: 사용자에게 숫자를 입력받아 랜덤 숫자와 비교하고, 정답을 맞출 때까지 반복하기.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int sum = 0;
int rs = (int) (Math.random() * 100) + 1;
while (true) {
System.out.print("숫자를 입력하세요 : ");
int num = sc.nextInt();
sum = sum + 1;
if (rs > num) {
System.out.println("UP");
} else if (rs < num) {
System.out.println("DOWN");
} else {
System.out.println("정답입니다");
break; // 정답을 맞췄을 때 무한 루프 탈출
}
}
System.out.println(sum + "번 만에 맞았습니다");
}
}
Scanner 클래스 이해하기:
Scanner sc = new Scanner(System.in);: 키보드(System.in) 입력을 받을 스캐너 객체를 생성하고 sc라는 변수에 저장한다.int num = sc.nextInt();: 사용자가 정수를 입력하고 엔터를 칠 때까지 대기한 후, 입력받은 숫자를 num 변수에 저장한다.카운팅/총합 변수의 위치는 반복문 밖이다.
count나 sum 변수를 반복문 안에 선언하면, 반복될 때마다 값이 0으로 초기화된다. 무언가를 누적해야 할 때는 반드시 반복문이 시작되기 전에 변수를 선언해야 한다.배열의 인덱스는 무조건 0부터 시작한다.
new int[5]로 배열을 만들면 인덱스는 0부터 4까지만 존재한다. 반복문에서 i <= arr.length를 사용하면 존재하지 않는 인덱스에 접근하여 ArrayIndexOutOfBoundsException 에러가 발생한다. 조건식은 <를 사용해야 안전하다.print와 println의 용도를 구분해야 한다.
println을 쓰면 값이 아래로 길게 나열된다. 상황에 맞게 줄바꿈 유무를 결정하여 사용해야 한다.무한 루프에는 비상 탈출구가 필수이다.
while (true)로 무한 반복을 만들었다면, 특정 조건을 만족했을 때 루프를 종료시키는 break; 명령어가 반드시 있어야 한다. 그렇지 않으면 코드가 무한히 실행되며 프로그램이 종료되지 않는다.