티스토리 뷰

Java/Java Study 기록 일지

JSON 백엔드 자바 3회차

응애~ 개발자 2023. 2. 9. 23:11
728x90
반응형

연습 문제

구구단 프로그램

[구구단] 몇 단을 출력하실건가요?
13
1단에서 9단까지만 출력이 가능합니다.
[구구단] 몇 단을 출력하실건가요?
8
8 * 1 = 8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
8 * 5 = 40
8 * 6 = 46
8 * 7 = 56
8 * 8 = 64
8 * 9 = 72
[구구단] 몇 단을 출력하실건가요?
exit
프로그램을 성공적으로 종료했습니다.
  • 구구단 출력은 1단에서 9단까지만 가능하다.
  • 입력값이 1~9를 벗어난 경우 1단에서 9단까지만 출력이 가능합니다.라고 출력하고, 다시 [구구단] 몇 단을 출력하실건가요?라고 묻는다.
  • 구구단을 출력한 뒤에도 [구구단] 몇 단을 출력하실건가요?라고 묻는다.
  • exit라고 입력한 경우 프로그램을 성공적으로 종료했습니다.라고 출력되고, 더 이상 입력값을 받지 않는다.

필요한 문법

  1. 정수
  2. 문자열
  3. 입출력
  4. for문
  5. while문
  6. continue
  7. break
  8. 문자열 포맷
  9. 리스트

이번 문제에서는 8,9 번 빼고는 풀수 있다고 생각한다. 8번 9번을 넣은 이유는 코드나 조건문을 더 추가해야 하는 번거로움 때문에 8번 9번을 추가한것이다.

문제 풀이

 이 문제에서 요구한 조건을 보면 아래와 같이 정리 할수 있다.

  • exit 입력 되기 전까지 무한 루프
  • 1 ~9 입력시 구구단 출력
  • 1 ~9 외에는 오류메세지를 출력하고 다시 입력

위 3가지만 풀어 내면 쉽다고 생각한다.

1.  준비 단계

 조건중 무한 루프를 하기 위해서 먼저 작업 해야 하는것이 있다. 그것은 입력 객체와 입력받을 변수, 구구단의 변수, 1 ~ 9까지 포함할 리스트를 먼저 만드는것이다. 1 ~ 9 까지 리스트 만드는 것은 나중에 비교할 때 사용할 예정이미로 지금 설명은 안하겠다.

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
int n;

List<String> check_number = new ArrayList<String>();
for(int i = 1; i <=9; i++) {
    check_number.add(String.valueOf(i));
}

List<String> check_number = new ArrayList<String>();

위 코드가   먼저 작업 해야 할 적업인데 여기서 중요하게 볼것은 List이다. List는 설명하면 긴데 간단하게 설명한다면 Collection 모듈중 하나이고 자바에서 많이 쓰는 객체라고 보면 된다. List는 배열이랑 비슷하게 여러개의 같은 타입의 데이터를 담은 객체라고 보지만 배열은 크기 한번 선언 하면 그 크기를 바꿀수 없고 데이의 값만 변경이 가능하다 하지만 List는 각 데이터 크기가 가변이고 데이터의 추가와 삭제가 용이 하다. 아래의 표를 보면 배열과 리스트의 차이를 간단하게 알수 가 있다.

  배열 리스트
선언 방법 타입[] 변수 = new 타입[]; List<타입> 변수 = new ArrayList<타입>();
크기 선언시 고정 가변
데이터 변경 범위 배열의 안에 있는 값만 변경 리스트 안에 있는 값 변경, 추가, 삭제
장점 메모리 적게 사용할수 있음 배열보다 데이터 조작하는데 용이하다.
단점 한 번 선언후 데이터 조작하는 범위가 한정되어 있다. 배열보다 사용하는 메모리가 크다.

check_number.add(String.valueOf(i));

 리스트 데이터 추가할때 add라는 메소드를 사용하면된다.

exit 입력 되기 전까지 무한 루프

while(true) {
    System.out.println("[구구단] 몇 단을 출력하실건가요?\n");
    str = br.readLine();
    if(str.equals("exit")) {
        break;
    }
}

while(true)

 while문 작성 방법은 while(조건문)이다. 조건문이 true일때 돌아가고 false일때는 while 루프가 끝난다. 그러면 다시while(true)로 라면 무한 루프이다.

if(str.equals("exit")) {
        break;
 }

 

이 부분은 입력받은 문자열이 exit 입력시 빠져나가도 하는 구문이다.

 문법을 보면 str.equals("exit") 이것 부터 본다면 equals는 문자열에서 제공하는 메소드이다. equals 메소드를 사용하면 안에있는 문자열이랑 비교해서 같으면 true 다르면 false로 준다. equals메소드는 문자열 == 문자열 비교하는것보다 더 유용하기 때문에 앞으로 문자열 비교할때는 습관처럼 equals를 사용하도록 하자!

그 다음은 break문인데 break문을 사용하면 내가 현재 블록안의 루프를 빠져 나갈수 있도록 해준다.

1 ~ 9 외 입력시 처리

else if(!check_number.contains(str)) {
    System.out.println("1단에서 9단까지만 출력이 가능합니다.");
    continue;
}

 이 부분은 1 ~ 9, exit외 입력시 다시 처음 물어보도록 하는 구문이다.

!check_number.contains(str)

 일단 contains는 리스트에서 제공하는 하는 메소드이다 contains는 안에 값이 포함 되어있으면 true 아니면 false로 반환 해주는 메소드이다. 그러면 1 ~ 9외에 입력시에서는 false로 반환해주지만 앞에 !는 반되 대는 의미라서 true로 나온다.

continue;

continue는 다음 반복문으로 넘어 가는 것이다. break는 반복문을 종료시킨다면 continue는 아래 코드 무시하고 다음 반복문으로 진행 하도록 한다.구구단 출력
for(int i = 1; i <= 9; i++) {
    System.out.printf("%d * %d = %d\n" , n, i, n * i);
}

for(int i = 1; i <= 9; i++)

 반복문 중 for문이다. for문 선언 방법은 이렇다. for(변수 선언 = 초기값; 조건문; 증감식) 이다. 조건문 만족할때까지 돌아가는것은 while문과 비슷하지만 변수 선언과 증감식이 추가가 된것이다. for문안에 코드가 끈나면 변수에 증감식을 더해서 조건문이 true이면 for문안이 돌아가고 거짓이면 for문이 끝나는 것이다. 다시 for문을 보면 int i = 1은 i가 1부터 시작하고 i <= 9는 i가 9이하 일때 까지 돌아가고 i++은 for문 안 코드가 끝나면 +1을 한다고 보면된다.
 

System.out.printf("%d * %d = %d\n" , n, i, n * i);

구구단을 출력하는 구문이다.

 기존에 출력을 System.out.println으로 했지만 이번에는 pringf함수로 처리한것을 볼수 있다. 이 부분을 문자열 포맷팅이라고 부르는 데 %d는 정수 \n은 다음줄이다. 그리고 그 다음에는 콤마 뒤로는 순서대로 값을 집어 넣는다고 보면된다. format 지시자는 아래표를 확인해보면된다.  

%d 정수
%f 실수
%s 문자열
%t 날짜, 시간
%o 8진수
%x 16진
%b boolean
전체 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Main {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String str; // 입력 받을 변수
		int n; // 구구단 변후
		
        // 1 ~ 9 까지 리스트에 저장
		List<String> check_number = new ArrayList<String>();
		for(int i = 1; i <=9; i++) {
			check_number.add(String.valueOf(i));
		}
        
		while(true) {
			System.out.println("[구구단] 몇 단을 출력하실건가요?\n");
			str = br.readLine();
			// exit입력시 루프 탈출
            if(str.equals("exit")) {
				break;
              // 1 ~ 9 포함 되어 있는지 여부 포함 안되어 있으면 다시 루프 시작
			}else if(!check_number.contains(str)) {
				System.out.println("1단에서 9단까지만 출력이 가능합니다.");
				continue;
			}
			
			n = Integer.parseInt(str);
            // 구구단 출력
			for(int i = 1; i <= 9; i++) {
				System.out.printf("%d * %d = %d\n" , n, i, n * i);
			}
			
			
		}
		System.out.println("프로그램을 성공적으로 종료했습니다.");
	}
	
}

ArrayList와 친해지기

코드

  1. 정수(int) 데이터를 담을 빈 ArrayList를 만들어라.
  2. ArrayList에 5, 7, 10, 9, 4라는 데이터를 차례대로 넣어라.
  3. ArrayList에서 7이라는 데이터를 삭제해라.
  4. ArrayList에 들어있는 두 번째 값을 조회해서 출력해라.
  5. ArrayList를 내림차순으로 정렬해라.
  6. for문을 활용해서 ArrayList의 모든 데이터를 차례차례 출력해라.
  7. ArrayList안에 11의 값이 존재하는 지 여부를 출력해라.
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
	
	public static void main(String[] args) throws IOException {
		//1
		List<Integer> list = new ArrayList<>();
		
		//2
		list.add(5);
		list.add(7);
		list.add(10);
		list.add(9);
		list.add(4);
		
		//3
		list.remove(list.indexOf(7));
		
		//4
		System.out.println(list.get(1) + "\n");
		
		//5
		Collections.sort(list, Collections.reverseOrder());
		
		//6
		list.forEach(i -> System.out.println(i));

		
		//7
		System.out.println("\n" + list.contains(11));	
	}
	
}

 이번 연습 문제는 리스트를 응요한것인데 리스트의 기본 설명은 위에 구구단 연습문제에 설명은 했는지 사용하는 메소드에 대해서는 설명 안했다. 위에서 리스트에서 사용하는 메소드에 대한 설명은 아래표에서 확인 하면된다.

add() 데이터 추가
get(i) i번째 데이터 추가
indexOf(x) x데이터 위치 반환 없으면 -1로 반환
remove(i) i번째 데이터 삭제
forEach 리스트안에 데이터 순차적으로 처리
contains 리스트안에 데이터 포함하는 여부
size 리스트 크기 출력

위에 표에 외의것을 설명하겠다.

Collections.sort(list, Collections.reverseOrder());

5번 보면 문제에서 내침 차순으로 정렬 하라고 했다. 그냥 sort메소드 사용하면 오름차순 정렬이지만 뒤에 Collections.reverseOrder() 사용하면 역순으로 정렬이 된다.

list.forEach(i -> System.out.println(i));

 for문대신 forEach문에 람다식을 사용하면  6번 내용을 for문을 선언안하고 간단하게 반복문을 처리할수 있다. 실제로도 많이 사용하니 람다식 익히후에 위 코드처럼 쓰는것을 추천한다.

미션

문제1

아래와 같이 작동하도록 코드를 작성해라.

학생의 이름을 입력하고 엔터를 누르세요. (한글로만 입력해야 합니다.)
학생들을 다 입력했다면, print라고 입력해주세요.
박재성
유재석
jason
학생의 이름은 한글로만 입력해야 합니다.
강호동
신동엽
print
[학생 명단(가나다순)]
강호동
박재성
신동엽
유재석
  • 배열(int[], String[] 등)을 사용하지 말고, ArrayList를 사용해라.
  • ArrayList를 사용할 때, 제네릭(Generic)을 사용해라.
  • 입력값이 한글 또는 print가 아니라면, 학생의 이름은 한글로만 입력해야 합니다.라는 문구가 출력된다.

문제 해설

요구 사항에서 구현 할것은 아래와 같다.

1. print입력 될때 까지 무한 루프

2. 한글만 입력된 학생 저장

3. 한글외 입력시 학생 오류 메세지 날리고 다시 입력

4. 정렬후 출력

위 3가지만 구현만 하면 끝이다.

 

준비

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
List<String> students = new ArrayList<>(); // 학생 저장
String str;

 일단 요구조건 구현 하기전에 필요한게 있다. 학생들 저장할 리스트, 입력 처리, 입력 받을 변수이다. 3가지 부터 먼저 선언하면된다.

print입력 될때 까지 무한 루프

while(true) {
    str = br.readLine();
    if(str.equals("print")){
        break;
    }
    // To do Code
}

 위에 구구단 연습 문제할때 eixt입력 받을시 종료하는것이랑 비슷하다.

한글만 입력된 학생 저장

if(tr.matches("^[가-힣]+$")) {
    students.add(str);
}

이 부분은 한글로 입력된 학생시 저장하는 구문이다.  

str.matches("^[가-힣]+$") 

mathes연산자는 문자열이랑 안에 정규식이 맞는경우 참/거짓을 반환한다. 하지만 중요한것은 '^[가-힣]*$' 이 정규 표현식이다. 다 설명하기는 그렇지만 ^는 처음 부터 [가-힣]가 부터 힣까지 모든 한글(자음 모음 제외)중, +는 앞에 문자가 1개 이상일때까지 $ 앞의 문자가 종료될때라고 보면 된다. 즉 전체 식을 해석하면 앞부터 뒤까지 한글로만 되어있는것이라고 보면된다.

그 외는 위에 연습문제에서 설명했다.

한글외 입력시 학생 오류 메세지 날리고 다시 입력

else {
    System.out.println("학생의 이름은 한글로만 입력해야 합니다.");
    continue;
}

 이 부분은 그 외의 경우 이고 그 외 경우 오류 메세지 날라고 다시 반복문 처음 코드로 이동해서 다시 입력 할수 있도록한다. 문법은 위에서 설명했으니 넘어 가겠다.

정렬후 출력

students.stream().sorted().forEach(System.out::println);

이 구문은 리스트에서 제공하는 람다식이다. 리스트에도 stream을 제공하다. stream은 간단하게 설명하면  자바 8부터 제공한것중하나이고 데이터를 일괄 처리하도록 도와주는 기술이다. 그리고 stream에 정렬도 제공한다. sorted()연산자 사용하면된다. 그 다음에 forEach문에 System.out::println인데  ::메소드는 클래스의 참조한다고 보면된다. 즉 forEach돌릴때 꺼내는 값을 println메소드를 실행시킨다고 보면된다. 지금 보면 복잡한데 자바심화 과정이기때문에 간단하게 이렇다라고 보면될거 같다.

전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Main {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		List<String> students = new ArrayList<>();
		String str;
		while(true) {
			str = br.readLine();
			if(str.equals("print")){
				break;
			}else if(!str.isEmpty() && str.matches("^[가-힣]+$")) {
				students.add(str);
			}else {
				System.out.println("학생의 이름은 한글로만 입력해야 합니다.");
				continue;
			}
		}
		System.out.println("[학생 명단(가나다순)]");
		students.stream().sorted().forEach(System.out::println);
	}
	
}

문제2

아래와 같이 작동하도록 코드를 작성해라.

선수의 번호를 입력하세요.
13
이 선수의 100m 달리기 기록이 몇 초인지 입력하세요.
13.56
선수의 번호를 입력하세요.
7
이 선수의 100m 달리기 기록이 몇 초인지 입력하세요.
15.153
선수의 번호를 입력하세요.
7
이 선수의 100m 달리기 기록이 몇 초인지 입력하세요.
12.157
선수의 번호를 입력하세요.
2
이 선수의 100m 달리기 기록이 몇 초인지 입력하세요.
14
선수의 번호를 입력하세요. 
print
1등 : 7번 선수 / 12.16초 (참가인원 : 3명)
  • 똑같은 선수 번호를 입력할 경우, 새로운 기록으로 갱신한다.
  • 100m 달리기 기록을 입력할 때, 소숫점 둘째자리까지 반올림하여 기록한다.
  • print라고 입력하면 1등의 선수를 출력한다.
  • 배열(int[], String[] 등)을 사용하지 말고, ArrayList를 사용해라.
  • ArrayList를 사용할 때, 제네릭(Generic)을 사용해라.

문제 해설

 이번 문제는 복잡해보이지만 구현 해야 될것은 많이 없고 밑에것을 한개 씩하면 쉽게 풀 수 있다.

  1. print 입력 될때 까지 무한루프
  2. 달리기 기록 입력 할때 소숫점 둘째 자리까지 반올림하여 기록
  3. 똑같은 선수 번호 입력할때 기록 갱신
  4. 1등 선수, 기록, 전체 선수 출력

준비

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
List<float[]> players = new ArrayList<>();
String str;
int player; // 선수 번호
float record; // 기록
boolean flag;
int index = -1; // 리스트 위치 값

 처음에 변수 선언하는게 필요하다 요구사항 보면 리스트에 담을 선수들, 선수번호, 선수, 깉은 선수 반펼할 변수, 리스트의 선수 위치가 필요한다.

print 입력 될때 까지 무한루프

while(true) {
    System.out.println("선수의 번호를 입력하세요.");
    str = br.readLine();
    if(str.equals("print")) {
        break;
    }
}

 위에 문제에서 설명했기 때문에 위에 문제 참조 하면된다.

 

달리기 기록 입력 할때 소숫점 둘째 자리까지 반올림하여 기록

System.out.println("이 선수의 100m 달리기 기록이 몇 초인지 입력하세요.");
record = (float) ((float)(Math.round(Float.parseFloat(br.readLine()) * 100)) / 100.0);

 round는 소수 첫째자리 까지 반올림한다. 그러면 2째자리 반올림 할려면 100을 곱해서 반올림한다음 100을 나누면 된다,.

 

똑같은 선수 번호 입력할때 기록 갱신

flag = true;
for(int i = 0; i < players.size(); i++) {
    if(players.get(i)[0] ==  player) {
        index = i;
        flag = false;
        break;
    }
}
if(flag) {
    players.add(new float[] {player, record});
}else {
    players.get(index)[1] = record;
}

flag 라는 변수 true로 초기화 하고 리스트안에 똑같은 선수가 있으면 flag 거짓으로하고 위치값을 저장한다. 그다음 flag가 true이면 추가 하고 false이면 갱신한다. 아마 이부분에서 고민을 많이 했을거라 생각한다.

 

1등 선수, 기록, 전체 선수 출력

int best_palyer = 0; // 1등 선수
float best_recode = Float.MAX_VALUE; // 1등 기록
for(float[] result : players) {
    if(result[1] < best_recode) {
        best_palyer = (int) result[0];
        best_recode = result[1];
    }
}

System.out.printf("1등 : %d번 선수 / %.2f초 (참가인원 : %d명)", best_palyer, best_recode, players.size());

 이 부분은  1등 선수 기록을 구현 하는 부분인데 for문을 돌려서 최고 기록기랑 비교해서 가장 적은 값을 저장하는 하도록 구현 했다. 문법적으로 봐야 할것은은 2개 정도 라고 생각한다.

float best_recode = Float.MAX_VALUE;

Float 클래스에 MAX_VALUE는  float 타입의 최대로 나타낼수 있는 값이다 이렇게 선언한 이유는 기징 적은 값을 출력하기 때문에 가장 큰 값으로 초기화 하는게 좋다.

for(float[] result : players)

기존 for 문 유형이랑 다르다 하지만 위에것은 초기화, 조건문, 증감식이지만 이것은 for(변수 : iteralble 객체)로 표현한것이다. iteralble은 연속된 데이터이다. 즉 연속적으로 데이터가 담아있는 객체라고 보면 된다. 그러면 연속된 객체 데이터에서 하나씩 변수에 담아서 처리한다고 보면된다. 많이 쓰는 표현이니까 알아두도록 하자.

전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Main {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		List<float[]> players = new ArrayList<>();
		String str;
		int player; // 선수 번호
		float record; // 기록
		boolean flag;
		int index = -1; // 리스트 위치 값
		while(true) {
			System.out.println("선수의 번호를 입력하세요.");
			str = br.readLine();
			if(str.equals("print")) {
				break;
			}
			player = Integer.parseInt(str);
			System.out.println("이 선수의 100m 달리기 기록이 몇 초인지 입력하세요.");
			record = (float) ((float)(Math.round(Float.parseFloat(br.readLine()) * 100)) / 100.0);
			flag = true;
			for(int i = 0; i < players.size(); i++) {
				if(players.get(i)[0] ==  player) {
					index = i;
					flag = false;
					break;
				}
			}
			if(flag) {
				players.add(new float[] {player, record});
			}else {
				players.get(index)[1] = record;
			}
		}
		
		int best_palyer = 0;
		float best_recode = Float.MAX_VALUE;
		for(float[] result : players) {
			if(result[1] < best_recode) {
				best_palyer = (int) result[0];
				best_recode = result[1];
			}
		}
		
		System.out.printf("1등 : %d번 선수 / %.2f초 (참가인원 : %d명)", best_palyer, best_recode, players.size());
		
	}
	
}

마무리

 이번 문제는 처음 공부한 사람한테는 힘들겠지만 위에 설명처럼 전체를 구현 할려고 하지말고 하나씩 구현하면 쉽게 구현이 가능하다. 자세한 자바에 대한 설명은 따로 글로 올릴 예정이다. 

728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함