티스토리 뷰
다음은 입력받은 학생을 고유번호에 따라 팀을 나누는 프로그램이다. 단 여기서 이름이 같은 사람이 나오면 두번째 부터는 차례로 (1), (2), 순서로 번호를 이름 뒤에 붙여준다.
왼쪽의 입력에 대해 오른쪽과 같은 출력이 나오게 프로그램을 작성해 보자. 이름은 같은 이름이 나오면 구분되게 차례로 증가하는 번호를 뒤에 붙여주고, 팀은 학생의 번호로 해당 학생을 찾는다.
1 lee 3 m 2 kim 4 m 3 cho 3 f 4 park 2 m 5 kang 3 f 6 lee 2 f 7 kim 3 m 8 song 3 f 9 choi 2 m 10 cho 2 f 0 A 1 2 3 4 0 B 3 5 7 0 C 2 4 0 D 7 8 9 10 0 end |
1 lee 3학년 남 2 kim 4학년 남 3 cho 3학년 녀 4 park 2학년 남 5 kang 3학년 녀 6 lee(1) 2학년 녀 7 kim(1) 3학년 남 8 song 3학년 녀 9 choi 2학년 남 10 cho(1) 2학년 녀 [A] park, cho, lee, kim, [B] kim(1), cho, kang, [C] park, kim, [D] kim(1), cho(1), choi, song, |
먼저 프로그램의 자료구조를 선언하는 부분은 다음과 같다. 학생의 아이디(int)에 대해 학생을 매핑하는 map과 이름에 대해 그 이름이 등장한 회수를 가지는 cntMap을 정의한다. 또한 팀의 이름에 팀을 매핑하는 teams가 있다.
public class Main { HashMap<integer, student=""> map = new HashMap<>(); HashMap<string, integer=""> cntMap = new HashMap<>(); HashMap<String, Team> teams = new HashMap<>(); Scanner scan = new Scanner(System.in); void doit() { readAllStudents(); readAllTeams(); printAllStudents(); printAllTeams(); }
학생은 번호를 먼저 읽고 학생 정보를 읽게 된다. 번호가 0이면 종료로 판단한다.
학생을 읽는 부분에서는 중복되는 이름에 (1), (2)를 붙이는 방법으로 cntMap을 사용한다. (위의 출력에서 lee(1), kim(1) 등이 두 번째 나와서 (1)이 붙은 예다.)
다음 코드에서 일단 학생이 이름과 나이, 성별 등을 읽고 이름이 겹치는 경우는 이름을 바꾼다. 또한 등장회수를 1 증가시켜 다음에 또 같은 이름이 나오면 번호가 증가되게 해 준다.
void readAllStudents() { int n, k; Student st = null; while (true) { n = scan.nextInt(); if (n == 0) break; st = new Student(n); st.read(scan); if (cntMap.containsKey(st.name)) { k = cntMap.get(st.name); // 그 이름이 몇번 나왔는지 st.name += "(" + k + ")"; // 이름에 번호를 붙여준다. cntMap.put(st.name, k+1); // 등장회수를 1 증가시킨다. } else { cntMap.put(st.name, 1); // 처음 나온 이름을 회수 1번으로 등록한다. } map.put(n, st); } }
팀은 이름과 그 팀에 속하는 학생 번호로 입력된다. 이것을 읽어 팀에서는 번호로 학생을 찾아 그 팀의 팀원으로 추가한다. 다음은 팀의 정보를 입력하는 메소드다. 팀을 만들어 이름을 등록하고 팀의 입력 함수 read 안에서는 학생의 번호로 학생을 찾는 메소드를 호출한다.
void readAllTeams() { String name = null; Team t = null; while (true) { name = scan.next(); if (name.equals("end")) break; t = new Team(name); t.read(scan); teams.put(name, t); } }
학생 번호로 학생을 찾는 검색 함수는 다음과 같다.
Student getStudent(int n) { return map.get(n); }
이것을 Team 클래스의 read 메소드에서 호출한다. 이를 위해 다음과 같이 Main의 GetInstance()로 싱글톤 패턴을 사용한다. 팀에서 번호로 학생을 찾아야 하는데 이것은 Main 클래스가 가지고 있는 맵을 사용해야 하므로 Main 클래스에 요청해야 한다. 이 때 getStudent()를 static으로 만들면 Main.getStudent()로 호출할 수 있겠지만 그러면 map이 또 static 필드가 되어야 한다. 그럼 또 그걸 사용하는 다른 메소드가 static이 되어야 하므로 static이 꼬리를 물로 퍼져나간다. 이를 막기 위해 싱글톤 패턴을 사용할 수 있다. 이에 대해서는 별도의 포스트에서 다루겠다.
void read(Scanner scan) { int n; while (true) { n = scan.nextInt(); if (n == 0) break; members.add(Main.GetInstance().getStudent(n)); } }
이렇게 해서 Main 클래스가 세 개의 맵으로 학생과 이름과 팀을 관리하는 프로그램을 완성할 수 있다.
'자바 프로그래밍' 카테고리의 다른 글
객체의 참조와 객체 간의 관계 (0) | 2019.01.17 |
---|---|
자바 생성자와 초기화 이야기 (0) | 2019.01.17 |
자바 콜렉션 (2) - HashMap (0) | 2019.01.13 |
자바 콜렉션 - ArrayList (0) | 2019.01.13 |
객체 clone과 깊은/얕은 복사 (0) | 2019.01.12 |
- Total
- Today
- Yesterday
- 이터러블
- 스트링
- APPEND
- 이터레이터
- python exercise
- 자바regex
- zip
- python example
- 콜렉션
- 동적바인딩
- contains
- indexof
- 스트링 +
- 지연계산
- ToString
- comparable
- contentEquals
- max
- rust
- TypeError
- sort key
- typedef
- CompareTo
- format
- Camel Style
- Iterator
- C++ 클래스
- 패턴
- Lazy evaluation
- follow
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |