본문 바로가기

Study/Java

반복문과 제어자

안녕하세요. 오늘 포스팅은 자바 튜토리얼 세번째 이야기입니다.

우선 지난 포스팅에서 Caster(강제 자료형 변환)가 무엇인지, 그리고 연산자와 배열에 대해 살펴보았고 if조건문과 switch case순환문에 대해 살펴보았습니다.

각각의 형식에 대해 잠깐 짚어보겠습니다.

지난 포스팅 복습하기


// Caster(강제 자료형 변환)
int num = 23456;
short sh = 12345;
sh = num;        // error
sh = (short)num        // int로 선언된 num을 강제로 short형으로 바꿔줌

// 자동 자료형 변환
int num;
short sh = 12345;
num = short;        // short는 int 자리에 들어갈 수 있다!!

// 연산자
int num1, num2, result;
result = num1 + num2;        // 더하기
result = num1 - num2;        // 빼기
result = num1 * num2;        // 곱하기
result = num1 / num2;        // 몫
result = num1 % num2;        // 나머지

num1 += 1            // 자기 자신을 갱신 num1 = num1 + 1

// increment와 decrement
int number = 0;
number++;            // 1 증가
number--;            // 1 감소

// 배열을 선언하는 방법
자료형 배열명[] = new 자료형[배열 원소 개수]
int myArray[] = new int[5];    // 동적 할당이 가능한 배열
int myArray[] = { 11, 22, 33, 44, 55 };    // 애초부터 값 고정

// 2차원 배열 : 1차원 배열이 행으로만 이루어진 데이터라면 2차원 배열은 행과 열을 가지고 있음.
int myArr[][] = new int[3][4];
int myArr[][] = {
  {1, 2, 3, 4},
  {5, 6, 7, 8},
  {9, 10, 11, 12}
};

// if 조건문: 조건에 맞으면 처리.
// 조건을 분기할 수도 있고 주어진 조건에서 아예 벗어나는 경우 else를 써서 false인 경우의 처리까지 가능
int score = 97;

if (score == 100) {
  System.out.println("A+");
} else if (score >= 95) {
  System.out.println("A");
} else if (score >= 90) {
  System.out.println("B+");
} else {
  System.out.println("B");
}

// switch...case문 : 주어진 조건과 값을 비교하여 결과를 출력.
// if else if문과 유사하고 명확히 지정된 값만 비교값으로 제시할 수 있음.
int number = 2;

switch (number) {
  case 1:
    System.out.println("number is 1");
    break;
  case 2:
    System.out.println("number is 2");
    break;
  case 3:
    System.out.println("number is 3");
    break;
  /*
  범위 사용 불가
  case number > 8:
    System.out.println("number is 9");
    break;
  */
  // default는 생략이 가능하다!!
  default:
    System.out.println("number is " + number);
    break;

// switch문에서 쓰인 break는 제어자라고 하며 continue도 제어자에 해당됩니다.
// 이들은 순환문 안에서 루프를 그만 돌게 하거나 다음으로 진행하라는 의미이며 단독으로 사용할 수 없습니다.

자 여기까지 어제 살펴본 내용이었습니다.

그러면 오늘은 순환문 전반에 대해 보겠습니다.


반복문 for


주요 개념

반복문은 loop문, 순환문이라고도 불리며 흔히 반복문이라고 알고 있습니다.
종류는 for문, while문, do while문이 있으며 이들은 어떤 조건이 참일 때 계속적으로 반복작업을 실시해주고, 조건이 false가 될 때 반복문을 탈출하게 되어있습니다.

for

기본적인 형식

우선 for문은 지정 횟수에 따라서 반복하는 제어문입니다.

형식은 다음과 같습니다.

for( 변수의(선언)초기화; 조건식; 연산식 ) {

  처리

}

소괄호쪽을 보시면 변수의(선언) 초기화라는 게 있는데 꼭 이 안에서만 변수를 초기화할 필요는 없습니다. 바깥에서도 변수를 초기화할 수 있지만 "변수의 유효 범위(스코프)"를 고려했을 때 소괄호 안에서 변수를 초기화해주는 것이 좋습니다. 초기화할 변수를 바깥에 선언해주는 것은 틀린 방식이라고 말할 수는 없지만 나중을 생각했을 때 그닥 좋은 방법은 아닙니다.

예를 들어

for (int i = 0; i < 10; i++) {

  System.out.println("이게 반복문이야~~");

}

라는 반복문을 작성해준다면 i라는 변수가 0으로 초기화되었고 i가 10보다 작을때까지 i에 1씩 더해주며 반복할겁니다.

Run을 해보면 "이게 반복문이야~~"라는 문장이 10번 출력될겁니다. 0부터 9까지만 반복하기 때문이죠!!

연습하기

마찬가지로

for(int i = 1; i <= 100; i++) {

  System.out.println(i);

}

해주게 되면 i가 1부터 100까지 출력되겠죠?

위의 예제들에서는 increment를 연산식으로 사용해주었는데요, decrement도 사용할 수 있습니다!!

for (int i = 10; i > 0; i--) {
  System.out.print(i + " ");
}

이렇게 써주시면 10부터 1까지 1씩 뺀 값을 출력해주겠지요?

그럼 0부터 10미만의 짝수들만 출력하려면 어떻게 할까요?

for (int i = 0; i < 10; i+=2) {

  System.out.print(i + " ");

}

이렇게 자기 자신을 갱신하는 연산자를 사용해주면 i가 0부터 10미만까지 2씩 증가하는 형태를 볼 수 있습니다!!

for문을 사용하면서 조건을 누락하거나 잘못 쓰시면 무한루프에 빠질 수 있으니 주의하세요!!

for문을 사용해서 1부터 10까지 더한 결과값을 출력해봅시다!

int sum = 0;    // 더한 값을 더해줄 변수 초기화
for (int i = 1; i <= 10; i++) {

  sum += i;

}
System.out.println(sum);

이렇게 i를 1로 초기화해주고 10보다 작거나 같을 때까지 i에 1씩 더해준 값을 변수 sum에 담아서 출력해주면 되겠습니다!!

다음 예제를 해결해봅시다.

/*
 * 학생 6명의 국어 성적의 합계와 평균을 구하는 프로그램을 작성해주세요.
 * 각각의 점수는 90점, 85점, 95점, 100점, 85점, 75점입니다.
*/

// 우선 점수를 배열에 담아줍시다!
int scoreArr[] = new int[6];
scoreArr[0] = 90;
scoreArr[1] = 85;
scoreArr[2] = 95;
scoreArr[3] = 100;
scoreArr[4] = 85;
scoreArr[5] = 75;

// 점수 초기값을 지정해줍니다.
int score = 0;

// i를 지정해주고 i가 점수배열의 길이보다 작을때까지만 i++를 반복합니다.
for (int i = 0; i < scoreArr.length; i++) {

  // score에 점수배열의 i번째에 있는 것을 score와 더해서 저장해줍니다.
  score += scoreArr[i];

}

// 출력합니다.
System.out.println(score);

// 평균은 소수점이 나올 수 있기 때문에 double로 선언해주고 점수의 합을 담은
// score변수로 부동소수점 형태로 바꿔서 배열의 길이만큼 나눠줍니다.
double avg = (double)score / scoreArr.length;

// 출력해줍니다.
System.out.println(avg);

for문 + if

for문과 섞어서 많이 사용하는것이 if문이라고 할 수 있겠습니다.

// names 배열 안에 있는 요소 중에 "성춘향"을 찾으면 찾았다는 메시지와 몇번째에 있는지 알려주는 메시지를 출력해봅시다!

String names[] = { "홍길동", "일지매", "성춘향", "홍두깨" };

int number = 0;        // 몇번째에 있음을 알려주기 위해 선언한 변수
for (int i = 0; i < names.length; i++) {
  number++;            // 배열 첫번째 요소를 1로 정의해서 보여줄겁니다.

  // names의 i번째 요소가 "성춘향"이라면
  if (names[i].equals("성춘향")) {

    // 배열 첫번째 요소 1번 기준 몇번째에 있는지, 찾았다는 메시지를 출력해줍니다.
    System.out.println("찾았습니다! " + number + "번째");
  }
}

앞전에 사용했던 점수 배열을 활용하여 점수 배열 중 최대점수를 출력하는 예시를 만들어봅시다!

int scoreArr[] = new int[6];
scoreArr[0] = 90;
scoreArr[1] = 85;
scoreArr[2] = 95;
scoreArr[3] = 100;
scoreArr[4] = 85;
scoreArr[5] = 75;

int maxScore = scoreArr[0];        // 최고 점수를 담을 변수 선언하고 배열의 인덱스 0 참조
for (int i = 0; i < scoreArr.length; i++) {
  if(scoreArr[i] > maxScore) {
    maxScore = scoreArr[i];        // 0번째 값부터 scoreArr.length까지 반복하며 가장 높은 값을 담아줍니다.
  }
}
System.out.println(maxScore);

for each

기존에 배열에서 요소를 뽑아올 때 우리는 배열 변수명[i]처럼 각 주소를 직접 붙이거나 반복문을 통해 i번째 까지 출력해달라는 명령을 입력했었습니다.

그렇지만 for each문을 사용하면 0번째부터 n번째까지 한번에 다 가져올 수 있습니다.

int scoreArr[] = new int[6];
scoreArr[0] = 90;
scoreArr[1] = 85;
scoreArr[2] = 95;
scoreArr[3] = 100;
scoreArr[4] = 85;
scoreArr[5] = 75;

for (int num : scoreArr) {
  System.out.println(num + " ");
}

// 결과는 90 85 95 100 85 75

자바스크립트의 for...in과 유사한 성질을 갖습니다.

// JavaScript의 for in 사용 예시
// JS에서는 객체에 사용한다는 특징이 있습니다.

const myObj = {
  name: "Hong Gildong",
  age: 25,
  area: "Seoul"
};

for(key in myObj) {
  console.log(`${key}: ${myObj[key]}`);
};    // -> name: 홍길동    age: 25    area: Seoul

또한 자바스크립트의 for...of와 유사한 속성을 갖지만, for...of[Symbol.iterator] 속성을 갖는 컬렉션에만 사용할 수 있습니다.

const myArr = ["Hong Gildong", 25, "Seoul"];

for(value in myArr) {
  console.log(value);
};    // -> Hong Gildong    25    Seoul 

for문 중첩

for문도 if문과 마찬가지로 중첩해서 사용할 수 있습니다. 구구단을 표현하는 예제를 보고 이해해보겠습니다.

for(int i = 1; i < 10; i++) {
  for(int j = 1; j < 10; j++) {
    System.out.println(i + " x " + j + " = " + (i*j));
  }
  // 하나의 단이 끝나면 개행을 하기 위해 넣어줬습니다.
  System.out.println();
}

우선 i가 1부터 10미만일 때 i에 1씩 증가시키는 형태입니다.
즉 1, 2, 3, 4, ..., 9의 형태를 보여줍니다.
i가 1부터 10미만일 때에 한해 중첩된 조건문을 실행하는데, 마찬가지로 j가 1부터 10미만일 때 j에 1씩 더해나갑니다.
그러니까 반복 순서는 i가 2라면 j가 1부터 10미만까지 반복하고 다시 i가 3이 되면 j가 1부터 10미만까지 반복하는 형태를 계속해서 취하는데 i가 9일때까지 반복합니다.

그래서 출력은 아래와 같은 형태가 나오게 됩니다.

// console
1 x 1 = 1 1 x 2 = 2 1 x 3 = 3 1 x 4 = 4 1 x 5 = 5 1 x 6 = 6 1 x 7 = 7 1 x 8 = 8 1 x 9 = 9 
2 x 1 = 2 2 x 2 = 4 2 x 3 = 6 2 x 4 = 8 2 x 5 = 10 2 x 6 = 12 2 x 7 = 14 2 x 8 = 16 2 x 9 = 18 
3 x 1 = 3 3 x 2 = 6 3 x 3 = 9 3 x 4 = 12 3 x 5 = 15 3 x 6 = 18 3 x 7 = 21 3 x 8 = 24 3 x 9 = 27 
4 x 1 = 4 4 x 2 = 8 4 x 3 = 12 4 x 4 = 16 4 x 5 = 20 4 x 6 = 24 4 x 7 = 28 4 x 8 = 32 4 x 9 = 36 
5 x 1 = 5 5 x 2 = 10 5 x 3 = 15 5 x 4 = 20 5 x 5 = 25 5 x 6 = 30 5 x 7 = 35 5 x 8 = 40 5 x 9 = 45 
6 x 1 = 6 6 x 2 = 12 6 x 3 = 18 6 x 4 = 24 6 x 5 = 30 6 x 6 = 36 6 x 7 = 42 6 x 8 = 48 6 x 9 = 54 
7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 
8 x 1 = 8 8 x 2 = 16 8 x 3 = 24 8 x 4 = 32 8 x 5 = 40 8 x 6 = 48 8 x 7 = 56 8 x 8 = 64 8 x 9 = 72 
9 x 1 = 9 9 x 2 = 18 9 x 3 = 27 9 x 4 = 36 9 x 5 = 45 9 x 6 = 54 9 x 7 = 63 9 x 8 = 72 9 x 9 = 81

2차원 배열에서 for문 사용하기

어제 살펴보았던 2차원 배열에서도 for문을 사용할 수 있습니다.

2차원 배열이 무엇이었나요? array2라는 변수에 할당해줘 보겠습니다.

int array2[][] = {
  { 11, 12, 13, 14 },
  { 21, 22, 23, 24 },
  { 31, 32, 33, 34 }
}

for (int i = 0; i < array2.length; i++) {
  for (int j = 0; j < array2[i].length; j++) {
    System.out.println(array2[i][j] + " ");
  }
  // 개행을 위해 넣어줌
  System.out.println();
}

우선 array2.length를 해주게 되면 배열의 길이로 3이 반환됩니다.
그 이유는 array2는 2차원 배열이기 때문에 배열안의 원소({}로 묶인) 개수가 우선 3이기 때문입니다.
배열의 i번째 인덱스의 j번째 인덱스가 배열의 원소 하나하나의 값이 되기 때문에 각각을 출력해 주기 위해서는 i번째 인덱스의 j번째 인덱스를 찾아달라고 입력해야 합니다.

그래서 각각을 구분하여 i와 j로 선언해주었고, 이들의 값을 각각 조회하기 위해 array2[i][j] 형식으로 써준 것입니다.


반복문 whiledo while


whlie loop와 do while loop가 있습니다. loop는 반복문을 뜻합니다.

각각 다음과 같은 형식을 갖습니다.

// while
변수 초기화;
while(조건식) {
  처리;
  연산식;
}

// do while
변수 초기화;
do {
  처리;
  연산식;
} while(조건식);

while

while문을 쓸 때 주의할 사항은 연산식이 내부에 있기 때문에 연산식을 정상적으로 처리해주지 않으면 무한 루프에 빠질 확률이 높아집니다!

예제를 보겠습니다.

// 변수 w를 지정해주고 0으로 초기화합니다.
int w;

w = 0;

// w가 10보다 작을 때 w에 1씩 증가하여 출력해줍니다.
while(w < 10) {
  System.out.println("while loop " + w);
  w++;
}

// 위의 예시를 for문으로도 구현할 수 있습니다. 그러나 추천하는 방법은 아닙니다!
int i = 0;
for ( ; i < 10; ) {
  System.out.println("for loop " + i);
  i++;
}

가령 이렇게 조건을 true로 건다면 무한 루프에 빠질 수 있습니다.

int count = 0;

while (true) {
  System.out.println(count);
}

do while

while문과 do while문의 확연한 차이는 while문은 조건이 참일 때만 루프를 도는 것이고, do whiledo 안에 있는 것을 우선 실행한 다음에 참/거짓 여부를 비교하여 while 루프를 순환합니다.

int dw;
dw = 0;

do {
  System.out.println("do while loop: " + dw);
  dw++;
} while(dw < 10);

do while문은 이렇게 작성할 수 있는데요, 만약 변수 dw를 110으로 바꾸고 Run하더라도 System.out.println("do while loop: " + dw);의 결과로 do while loop: 110이 한번 나오고 반복문을 순회하여 거짓이기 때문에 멈춥니다.

이처럼 원치 않는 결과를 보여줄 수도 있기 때문에 많이 사용하진 않습니다.

그러면 앞에서 정리한 내용을 바탕으로 while 문을 사용하여 구구단을 구현해보겠습니다.

// 변수 선언 및 초기화
int p, q;
p = q = 1;

// for문 중첩처럼 while문도 중첩할 수 있습니다!
while (p < 10) {
  while (q < 10) {

    // q에 대한 while루프를 빠져나왔을 때 q를 다시 한 번 더 초기화 해줍니다.
    q = 1;

    // 연산 결과를 출력하고 q에 1을 증가시킵니다.
    System.out.println( p + "x" + q + " = " + (p*q) );
    q++;
  }
  // 개행을 위해 써줍니다.
  System.out.println();
  // p에 1을 증가시켜 다시 순회합니다.
  p++;
}

제어자 break

break가 무엇일까?

어제 포스팅에서 맛을 보긴 했지만 제어자라는 녀석도 있습니다.
우선 break가 있는데, 루프를 멈출 지 여부를 알려줍니다.
물론 단독으로 사용할 수 없으며 switch, for, while, do while문과 같이 사용해줍니다.

사용 예시입니다.

// switch문 사용 예시
switch(variable) {
  case value:
      processing;
      break;
  ...
}

// for문 사용 예시
for (int i = 0; i < 100; i++) {
  if(조건) {
      break;    // 일정 조건을 할당하고 break를 주면 loop를 멈추고 그 loop를 빠져나온다.
  }
}

// while문 사용 예시
int w = 0;
while(w < 100) {
  if (조건) {
    break;
  }
  w++;
}

극단적인 예로 변수 i가 0부터 10미만까지 순회할 때 5까지만 보여주고 멈추기 위해서는 어떻게 프로그램을 작성하면 좋을까요?

for(int i = 0; i < 10; i++) {
  System.out.println("for loop " + i);
    if (i == 5) {
      break;
  }
}

이런 경우에는 애초에 i를 6미만 또는 5보다 작거나 같은 경우로 잡아주면 되겠죠...?

그러면 배열에서 어떤 원소가 0미만인 경우 멈추게 하는 프로그램을 작성해보겠습니다!

int array[] = { 1, 4, -7, 3, 8 };

for(int i = 0; i < array.length; i++) {
  System.out.println("array[" + i + "] = " + array[i]);
  if (array[i] < 0) {
    break;
  }
}

// array[0] = 1
// array[1] = 4
// array[2] = -7

for문 안에 조건문을 넣어서 배열의 i번째가 0보다 작으면 멈추도록 지정해주었습니다.
결과는 소스코드 아래 표시해둔대로 입니다.

그러면 while문에서 break를 사용하는 예시를 보겠습니다!

// Scanner를 사용하기 위해서는 소스코드 최상단에 import 해줘야합니다!
import java.util.*;

Scanner sc = new Scanner(System.in);
int number;
  while(true) {
    // 숫자를 입력받아서 다음 토큰으로 넘겨줍니다.
    System.out.print("숫자를 입력해주세요(>0): ");
    number = sc.nextInt();

    // number가 0보다 크다면 멈추고
    if (number > 0) {
      break;
    }

    // break 조건이 아니라면 양수를 입력하라는 메시지를 반복출력합니다.
    System.out.println("양수를 입력해 주세요!");
}

이중 for문 탈출하기

우리가 for문을 중첩해서 쓰고 어떤 조건이 참일 때 break를 한다고 하면 아마 다음과 같이 쓸 수 있을겁니다.

for(int i = 0; i < 10; i++) {
  System.out.println("i = " + i);
  for(int j = 0; j < 8; j++) {
    System.out.println("\tj = " + j);

    if (i == 5 && j == 3) {
      break;
    }
  }
}

이렇게 작성하고 Run을 해보면 아마 i가 5인 구간에서만 j가 3까지 나오고 그 다음인 i가 6일때부터는 또 j가 9인 경우까지 모두 출력될 것입니다...

// 출력예시
i = 0
    j = 0
    j = 1
    j = 2
    j = 3
    j = 4
    j = 5
    j = 6
    j = 7
      .
      .
      .
i = 5
    j = 0
    j = 1
    j = 2
    j = 3
i = 6
    j = 0
    j = 1
    j = 2
    j = 3
    j = 4
    j = 5
    j = 6
    j = 7
      .
      .
      .

왜 이런 문제가 발생할까요? 바로 break문은 한개당 하나의 반복문만 멈춰주기 때문입니다. 우리는 j에 대한 반복문에만 i가 5이고 j가 3일때 멈추라는 조건을 걸어주었기 때문에 i에 대한 반복문에도 break를 잡아주지 않으면 i = 6일 때는 정상적으로 또 실행되게 되는 것입니다.

그래서 지금부터는 이중 loop문을 한번에 탈출하는 방법을 살펴보려고 합니다.

예를 들어서 어떤 boolean 값을 false로 지정해주고 이게 true가 되면 멈추라고 해주겠습니다.

boolean b = false;

for (int i = 0; i < 10; i++) {
  System.out.println("i = " + i);
  for (int j = 0; j < 8; j++) {
    System.out.println("\tj = " + j);

    // i ==5 && j == 3일 때, boolean을 true로 지정
    if (i == 5 && j == 3) {
      b = true;
    }

    // 위의 조건을 만족해서 b가 true가 되면 j에 대한 반복문을 멈춰줌
    if (b == true) {
      break;
    }
  // 마찬가지로 b가 true가 되면 i에 대한 반복문을 멈춰줌.
  if (b == true) {
    break;
  }
}

이렇게 loop문의 개수에 맞게 break를 설정해주는 방법이 첫번째 방법이라고 할 수 있겠습니다. 이 방법을 주로 사용하면 좋을 것 같습니다.

또 다른 방법으로는 goto문을 사용하는 것입니다. for 앞에 임의의 문자열을 붙여주고 break 뒤에 똑같이 붙여주면 한번에 반복문을 빠져 나올 수 있습니다.

getOut:for(int i = 0; i < 10; i++) {
  System.out.println("i = " + i);
  for(int j = 0; j < 8; j++) {
    System.out.println("\tj = " + j);
    if (i == 5 && j == 3) {
      break getOut;
    }
  }
}

임의의 문자열:for...break 임의의 문자열과 같은 방식을 취합니다.


제어자 continue

continue는 skip의 의미를 갖습니다. break와 마찬가지로 단독적으로 쓰일 수 없으며, 반복문에 같이 사용해줍니다. 기본적인 형식은 이렇습니다.

while(조건) {

  처리1;
  처리2;

  if(조건) {
    continue;
  }

  처리3;        <--- if 조건이 true면 처리3은 실행되지 않습니다.

}

예를 들어서 다음과 같은 코드가 있다고 가정해봅시다.

for (int i = 0; i < 10; i++) {
  System.out.println("i = " + i);

  System.out.println("for Start");

  if (i > 3) {
    continue;
  }

  System.out.println("for End");
}

우선 i가 0부터 시작해서 9가 될때까지 반복합니다.
이 때 i의 값과 "for Start"라는 말을 반복해서 출력해줄겁니다.

앗!! 그런데 밑에 조건이 붙어있습니다. i가 3보다 크다면 아래 작업을 패스라하는 continue가 붙어있군요..!!

그래서 결과적으로 0부터 3까지만 i와 for Start, for End의 쌍으로 계속 출력되고 i = 4부터 i와 for Start만 쌍으로 나올 것입니다.

결과를 같이 살펴볼까요?

// 실행결과
i = 0
for Start
for End
i = 1
for Start
for End
i = 2
for Start
for End
i = 3
for Start
for End
i = 4
for Start
i = 5
for Start
    .
    .
    .
i = 9
for Start

결과를 확인하셨나요? 이 예제를 그대로 while문에 적용해보면 어떻게 될까요?

int i = 0;
while (i < 10) {
  System.out.println("i = " + i);

  System.out.println("for Start");

  if (i > 3) {
    continue;
  }

  i++;
}

이 때는 i = 4가 되었을 때 continue에 의해 i++이 수행되지 않으므로 i = 4인채로 다시 System.out.println("i = " + i); 구문에 돌아가게 됩니다. 이 때도 다시 i = 4이기 때문에 계속적으로 반복되는 무한루프에 빠지게 됩니다.

오늘 정리할 내용은 여기까지입니다.

그러면 정리한 내용을 바탕으로 과제를 해결해봅시다.

과제

문제 1

학생 수만큼 점수를 입력받아 점수의 통계를 내려고 합니다.
이 때, 총점, 평균, 그리고 최고점수를 구하고 입력 받은 점수 중에 90점 이상은 몇 명인지 출력해주는 프로그램을 작성해주세요. 그리고 90점 이상을 맞은 점수를 새로운 배열에 넣어주세요.

우선 프로그램을 작성하기 전에 각각의 기능들을 잘라서 나열해 놓겠습니다!

public class MainClass {

    public static void main(String[] args) {

        /*
            학생 수만큼 점수를 입력받아 점수의 통계를 내려고 합니다.
      이 때, 총점, 평균, 그리고 최고점수를 구하고 입력 받은 점수 중에 90점 이상은 몇 명인지 출력해주는 프로그램을 작성해주세요. 그리고 90점 이상을 맞은 점수를 새로운 배열에 넣어주세요.
        */



        // 필요한 변수 선언


        // 학생 수 입력 받기


        // 학생 수만큼 점수 입력받기


        // 총점 산출하기


        // 평균 산출하기


        // 최고점수 구하기(최댓값)


        // 90점이상 득점자 몇명인지


        // 90이상 숫자를 새로운 배열에 넣기


        // 모두 출력해주기

    }

}

자, 그러면 우선 필요한 변수부터 선언해줍시다!

// Scanner 모듈을 사용할 것이기 때문에 상단에서 java.util.*을 import해주세요.
import java.util.*;

...

// 필요한 변수 선언
  // 입력을 받기 위한 모듈
Scanner input = new Scanner(System.in);
int count;

// 학생 수 입력 받기
System.out.print("학생 수를 입력해주세요 : ");
count = input.nextInt();

우선 Scanner 모듈 사용을 위해 java.util.*import 해주었습니다.
그 다음으로 input이라는 이름을 가진 Scanner 객체를 생성해줍니다.

학생 수를 입력받기 위해서 count라는 변수를 선언해주고, 입력 받은 값을 저장해줍니다.

// 필요한 변수 선언
...
int scoreArr[] = null;

// 학생 수만큼 점수 입력받기
scoreArr = new int[count];

for (int i = 0; i < count; i++) {
  System.out.print((i+1) + "번째 학생의 점수를 입력해주세요 : ");
  scoreArr[i] = input.nextInt();
}

우선 학생 수만큼 점수를 입력받아야 하기 때문에 for 반복문을 사용해야 한다는 사실을 인지하였고, 점수를 담아서 보관해주기 위해 배열을 사용해야 한다는 사실도 인지했습니다.

그러면 우리는 빈 배열을 하나 만들어주는데 동적 할당이 가능해야 할 것이고 배열 안에는 입력받은 학생 수만큼 채워지게 될 것입니다.

scoreArr[]라는 빈 배열을 우선 선언해주고 초기값을 null로 지정해 줄 것입니다. 이 배열안에는 count 즉 앞에서 입력받은 학생 수만큼 배열이 채워질 것임을 알려줍니다.

동적 할당을 해줘야하는 객체의 초기화는 null로 한다는 사실 잊지 마세요!

그 다음은 반복문을 써서 학생 수만큼 점수를 입력받아야 하기 때문에 반복문은 학생 수만큼 반복을 해주어야 하고, 반복할 작업으로는 i번째 학생의 점수를 입력하도록 해줍니다.

단, 여기에서 (i+1) + "번째 학생의 점수를 입력해주세요 : "라고 작성한 이유는 그냥 i번째 라고 했을 때는 0번째로 출력되기 때문에 사용자가 위화감을 느낄 수도 있다는 판단이 들어서 i+1번째, 즉 1번째부터 출력되도록 작성을 한 것입니다.

이렇게 i번을 반복적으로 입력 받은 값들을 배열 scoreArri번째마다 저장해줍니다.

// 필요한 변수 선언하기
...
int score;

// 총점 산출하기
score = 0;
for (int i = 0; i < scoreArr.length; i++) {
  score += scoreArr[i];
}

총점을 산출하기 위해서는 어떻게 해야 할까요? 배열 안에 있는 숫자들을 다 참조해서 더해줘야겠죠?
그러면 반복문을 역시 사용해줘야 하겠습니다.
제가 사용한 로직은 어떤 변수에 점수들의 합을 담아주는 것인데, 어떻게 구현되고 있는지 살펴보겠습니다.

우선 필요 변수로 score라는 변수를 선언해줬고, 초기값을 0으로 지정해주었습니다.

그 다음으로 i가 0부터 배열의 길이까지 반복작업하도록 하는 반복문을 작성했고 점수에는 점수 + 배열의 i번째를 넣도록 했습니다. 이렇게하면 배열 안에 있는 모든 숫자들의 합을 구할 수가 있습니다.

그 다음으로는 평균을 구해주겠습니다.

// 필요한 변수 선언
...
double avg;

// 평균값 구하기
avg = score / scoreArr.length;

평균값은 총점을 학생수로 나눠주면 되기때문에 위와 같이 연산할 수 있습니다. 그러나 이대로만 쓰게 되면 score가 정수형이기 때문에 소수점까지 나타나지는 않습니다.

그래서 자료형을 변환해줘야 하는데, scoredouble이라는 자료형으로 변환해주게 되면 소수점 평균치까지 구할수 있게됩니다.

그래서 다음과 같이 작성해줍시다.

// 평균값 구하기
avg = (double)score / scoreArr.length;

그 다음으로는 최댓값을 구해주겠습니다.

// 필요한 변수 선언
int max;

// 최고 점수 구하기(최댓값)
max = scoreArr[0];
for (int i = 0; i < scoreArr.length; i++) {
  if (scoreArr[i] > max) {
    max = scoreArr[i];
  }
}

우선 비교군을 먼저 지정해주기 위해서 max라는 변수를 선언해주고, 배열의 첫번째 요소를 담아서 고정시켜줍니다.

그 다음은 반복문을 사용해서 점수들을 각각 비교해줍니다. 0번째 인덱스부터 i번째 인덱스까지 하나하나 살펴줄겁니다.
이 때 i번째 인덱스가 max보다 크다면 max에는 i번째 인덱스를 담아줄 것입니다.

예를 들어, 입력받은 학생수가 4명이고 점수 배열이 [90, 100, 95, 90]이라면, 다음과 같이 비교하겠죠?

우선 i가 0일 때, 인덱스를 참조하면 90이라는 숫자가 나옵니다.
그리고 이것을 max와 비교했을 때 조건이 성립되지 않아서 max는 그대로 90점이 됩니다.

그리고 i가 1일 때, 인덱스를 참조하면 100이라는 숫자가 나오게 되고, 이를 max와 비교 했을 때 조건이 참이므로 max에는 100이 할당됩니다.

i가 2일 때, 인덱스를 참조하면 95라는 숫자가 나오게 되고 max는 100이므로 조건이 성립되지 않습니다. 그래서 max는 여전히 100입니다.

i가 3일때도 마찬가지입니다.

그래서 max는 최종적으로 100임이 자명해집니다.

최댓값에 100이 저장됩니다.

// 필요한 변수 선언
int high;

// 90점 이상 득점자가 몇명인지 구하기
high = 0;
for (int i = 0; i < scoreArr.length; i++) {
  if (scoreArr[i] >= 90) {
    high++;
  }
}

우리는 배열을 다 뒤져서 90점 이상이 몇개인지 판별해야 하기 때문에 조건문을 사용할 것이고, 배열에서 90이상의 숫자가 n개라면 어떤 변수에 n을 차곡차곡 채워 나갈 것입니다.

이 때 어떤 변수는 여기에서 high가 될것이고, 빈 상태 즉 초기값을 0으로 만들어줍니다.

그 다음으로 scoreArr 배열의 i번째 있는 수가 90 이상이라면 high를 하나씩 늘려갈 것입니다.

이렇게 90점 이상 득점자의 수도 구했습니다.

// 90이상의 수를 새로운 숫자 배열에 넣기

int highScore[] = new int [high];
int n = 0;

for (int i = 0; i < scoreArr.length; i++) {
  if (scoreArr[i] >= 90) {
    highScore[n] = scoreArr[i];
  }
}

우선 새로운 숫자 배열에 넣으라고 했으니, 새로운 빈 배열을 만들어줍시다. 우리는 highScore라는 빈 배열을 반들고 배열 안에는 90점 이상 득점자의 수만큼 채워줄 것이라고 명시했습니다.

그 다음으로는 반복문을 돌려주는데, 0부터 점수 배열의 길이만큼 반복할 것입니다. 만약에 점수 배열의 i번째 있는 원소가 90이상이라면, 점수 배열의 i번째 원소를 새로운 배열인 highScore의 어딘가에 넣어주어야 합니다.

그런데, 점수배열의 i번째에 90이상의 숫자가 있다고 해서 highScore도 똑같이 i번째에 넣으라고 한다면 에러가 발생할 것입니다.

점수 배열에 100이라는 숫자가 3번째에 있다고 가정했을 때, highScore 안에 아무것도 들어있지 않다면, 0번째부터 채워넣어야지 3번째부터 채워 넣을수는 없으니까요!

그래서 우리는 n이라는 변수에 0을 할당해주고, highScore의 0번째부터 채워 넣어달라고 명시해 준 것입니다!

그래서 최종 결과물은 아래와 같습니다.

import java.util.Arrays;
import java.util.Scanner;

public class MainClass {

  public static void main(String[] args) {

    /*
    학생 수만큼 점수를 입력받아 점수의 통계를 내려고 합니다.
    이 때, 총점, 평균, 그리고 최고점수를 구하고 입력 받은 점수 중에 
    90점 이상은 몇 명인지 출력해주는 프로그램을 작성해주세요. 
    그리고 90점 이상을 맞은 점수를 새로운 배열에 넣어주세요.
    */

    // 필요한 변수 선언
    Scanner input = new Scanner(System.in);
    int count;
    int scoreArr[] = null;
    int score;
    double avg;
    int max;
    int high;

    // 학생 수 입력 받기
    System.out.print("학생 수를 입력해주세요 : ");
    count = input.nextInt();


    // 학생 수만큼 점수 입력 받기
    scoreArr = new int [count];    // 배열에 학생수만큼 원소를 갖겠다고 명시
    for (int i = 0; i < count; i++) {
      System.out.print((i+1) + "번 째 학생의 점수를 입력해주세요 : ");
      scoreArr[i] = input.nextInt();
    }

    // 총점 산출하기
    score = 0;
    for (int i = 0; i < scoreArr.length; i++) {
      score += scoreArr[i];
    }

    // 평균 산출하기
    // 주의사항!!! 부동소수점!!
    avg = (double)score / scoreArr.length;

    // 최고 점수 구하기(최댓값)
    max = scoreArr[0];
    for (int i = 0; i < scoreArr.length; i++) {
      if (scoreArr[i] > max) {
        max = scoreArr[i];
      }
    }

    // 90점이상 득점자 몇명인지
    high = 0;
    for (int i = 0; i < scoreArr.length; i++) {
      if (scoreArr[i] >= 90) {
        high++;
      }
    }

    // 90이상의 수를 새로운 숫자 배열에 넣기
    int highScore[] = new int[high];
    int n = 0;
    for (int i = 0; i < scoreArr.length; i++) {
      if (scoreArr[i] >= 90) {
        highScore[n] = scoreArr[i];
      }
    }

    // 모두 출력하기
    System.out.println("입력 받은 점수는 " + Arrays.toString(scoreArr) + "입니다.");
    System.out.println("입력한 점수의 총점은 " + score + "점 입니다.");
    System.out.println("입력한 점수의 평균은 " + avg + "점 입니다.");
    System.out.println("입력한 점수 중 최고점수는 " + max + "점 입니다.");
    System.out.println("90점 이상 득점자는 " + high + "명 입니다.");
    System.out.println(Arrays.toString(highScore));

  }

}

문제 2

다섯개의 숫자를 입력받아 저장하고 음수가 입력되면 다시 입력받는 프로그램을 작성해주세요.

우선 문제를 파악해보면 5개의 숫자를 입력 받는데, 음수가 입력되면 프로그램을 다시 실행해야 하는 경우라고 볼 수 있겠습니다.

5개의 숫자를 보관해 줄 장소를 만들어주고, 음수가 입력되면 프로그램을 처음으로 돌려주는 즉 초기화 시켜주는 로직을 작성하면 될 것 같습니다.

비교적 간단하기 때문에 주석으로 설명을 첨부하겠습니다.

import java.util.*;
public class MainClass {

  public static void main(String[] args) {

    /*
      다섯개의 숫자를 입력받아 저장하고 
      음수가 입력되면 다시 입력받는 프로그램을 작성해주세요.
    */

    // 값을 입력받기 위해 Scanner 객체 생성
    Scanner input = new Scanner(System.in);


    // 다섯개의 숫자를 담을 배열 만들기
    int numArray[] = new int[5];

    // while문으로 반복작업 시키기
    int i = 0;        // i의 초기값을 0으로 지정
    while (i < 5) {
      // 여기에서 i번째라고만 하면 최초 0번째라고 출력되어
      // 사용자에게 위화감을 줄 수 있음. 그래서 i+1
      System.out.print((i+1) + "번째 숫자 : ");
      int num = input.nextInt();

      // 음수를 입력했을 때 0보다 큰 숫자를 입력하라는 메시지를
      // 띄워주고 i++는 실행하지 않음.
      if (num < 0) {
        System.out.print("0보다 큰 숫자를 입력해주세요.");
        continue;
      }

      i++;
    }

    // 배열을 출력
    System.out.println(Arrays.toString(numArray));

  }

}

오늘 정리할 내용은 여기까지입니다!

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

Java : 오버로드, 예외처리, 파일입출력  (0) 2022.02.16
Java : 함수  (0) 2022.02.16
Java : Wrapper Class와 정렬 기본  (0) 2022.02.16
Java : cast변환, 연산, 조건문과 반복문  (0) 2022.02.16
Java를 시작하기 전에  (0) 2022.02.16