수업내용/Java

[2022.09.29.목] 학생, 성적 처리 실습

주니어주니 2022. 9. 30. 01:16

 

 

 

< 성적처리샘플 애플리케이션구조> 

 

 

  • Student(), Score() : 학생 정보, 성적 정보 담당
    • Student의 변수 중 Score score 가 있음 -> Score객체 참조

  • StudentApp() : 실행 담당
    • Controller 객체 생성, Controller의 메소드들 실행
    • Controller가 필요함 (프로그램을 실행하기 위해)
  • StudentController() : 사용자와 상호작용 담당 (메뉴표시, 키보드로 입력받기, 출력하기)
    • keyboardreader가 필요함 (상호작용 - 키보드로 입력받기 위해서)
      Service도 필요함 (서비스기능(업무로직)을 사용하기 위해서 - Service의 로직에 따라서 실행)
    • ~~ 기능들이 있고, 키보드로 입력받고 저장하는 정도로만 되어있음
    • Controller 안의 변수와 메소드를 다 숨겨
  • StudentService() : 학생, 성적관련 업무로직 담당
    • 구체적이고 실질적인 업무로직
    • Service안의 변수들도 숨겨놓고, 메소드(기능)만 공개해
    • Service에는 Student[ ]타입의 배열객체가 있고
      이 배열객체의 한칸은 Student()객체가 있고, 이 객체는 Score()를 참조함 (Score score)

 

** 값을 담을 때는 setter 메소드, 값을 빼올 때는 getter메소드!!! 

 


 

 

<반환값에 따른 null체크>

 

  • 반환값이 여러개(배열, 콜렉션)인 경우 (객체가 여러개 저장된 배열을 반환)
    • public Student[ ] getAllStudents() {
         ...
      }
    • --> 조회결과가 없으면 길이가 0인거지, 절대로 null이 반환되지 않는다. 반환값이 null일 수 없음 !! 
           길이가 0인 배열. 길이가 0인 콜렉션(리스트, 셋)
    • --> 조회결과가 있으면 배열이나 콜렉션에 순서대로 담아서 반환

  • 반환값이 객체 1개인 경우 (객체 하나를 반환)
    • public  Student findStudentByName(String name) {
        ...
      }
    • --> 조회결과가 없으면 null이 반환 ( 따라서, 객체 1개를 반환할 때는 null에 대한 대비 필요 )
    • --> 조회결과가 있으면 그 객체 1개가 반환

 

ex)
public Student[ ] getAllStudents() {
   if(position == 0) {
      return new Student[0];
   }
   return students;
}
하나라도 담기면 position이 1인데, 하나도 안담겨야 position이 0 
-> 담은게 하나도 없다는 뜻
원래 배열이 5칸 짜리니까, 그냥 주면 값이 있는줄 알아
길이가 0인 배열을 새로 만든거야 -> 길이가 0인거를 넘겨주니까 
students.length == 0 -> 학생정보가 존재하지 않습니다 출력

 

 


 

<실습>

 

 

-성적정보 담당 객체 

public class Score {
	
	private int kor;
	private int eng;
	private int math;
	
	// 기본 생성자
	public void Score() {}
	
	// 모든 멤버변수를 초기화하는 생성자
	public void Score(int kor, int eng, int math) {
		this.kor = kor;
		this.eng = eng;
		this.math = math;
	}
	
	// Getter, Setter 메소드 
	public int getKor() {
		return kor;
	}
	public int getEng() {
		return eng;
	}
	public int getMath() {
		return math;
	}
	public void setKor(int kor) {
		this.kor = kor;
	}
	public void setEng(int eng) {
		this.eng = eng;
	}
	public void setMath(int math) {
		this.math = math; 
	}

	// 총점을 반환하는 메소드
	// 반환타입: int
	// 메소드명: getTotal
	// 매개변수: 없음 
	public int getTotal() {
		return kor + eng + math;
	}
	
	// 평균을 반환하는 메소드
	// 반환타입: int 
	// 메소드명: getAverage
	// 매개변수: 없음 
	public int getAverage() {
		return getTotal()/3;
	}

	// 모든 멤버변수의 값을 문자열로 반환하는 toString() 메소드 재정의 
	@Override
	public String toString() {
		return "Score [kor=" + kor + ", eng=" + eng + ", math=" + math + ", total()=" + getTotal()
				+ ", average()=" + getAverage() + "]";
	}
}

 

-학생정보 담당 객체 

public class Student {
	
	private String name;
	private int grade;
	private String tel;
	private String email;
	private Score score;	// Student has s Score. Student객체는 Score객체를 포함한다. 포함관계 (학생들마다 성적을 갖고있음) 
	
	public Student() {}
	
	public String getName() {
		return name;
	}
	public int getGrade() {
		return grade;
	}
	public Score getScore() {
		return score;
	}
	public String getTel() {
		return tel;
	}
	public String getEmail() {
		return email;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setGrade(int grade) {
		this.grade = grade;
	}
	public void setScore(Score score) {
		this.score = score;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", grade=" + grade + ", tel=" + tel + ", email=" + email + ", score=" + score
				+ "]";
	}
}

 

- 사용자와 상호작용 담당 객체 (메뉴표시, 키보드 입력받기, 조회, 출력하기)

  ( 등록, 출력, 변경 얘네들은 메뉴를 통해서만 할 수 있음 -> private 이니까 )

import utils.KeyboardReader;

public class SchoolController {	//틀 잡기
	
	private KeyboardReader keyboard = new KeyboardReader();
	private SchoolService service = new SchoolService();
	
	public void 실행() {
		메뉴();
	}
	public void 메뉴() {
		while(true) {
			
			System.out.println("-----------------------------------------------------------------------");
			System.out.println("1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료");
			System.out.println("-----------------------------------------------------------------------");
			System.out.println();
			
			System.out.print("메뉴선택: ");
			int menuNo = keyboard.getInt();
			
			if(menuNo == 1) {
				학생등록();
			} else if(menuNo == 2) {
				성적등록();
			} else if(menuNo == 3) {
				전체학생조회();
			} else if(menuNo == 4) {
				학생성적조회();
			} else if(menuNo == 5) {
				성적변경();
			} else if(menuNo == 6) {
				학생정보삭제();
			} else if(menuNo == 0) {
				System.out.println("## 프로그램을 종료합니다.");
				System.exit(0);
			}
			System.out.println();
			System.out.println();
		}		
	}
	/*
	 * 1."<< 신규 학생 등록 >>"
	 * 2. 학생정보 입력(이름,학년,전화번호,이메일)  --> "홍길동,3,010-1111-1111,hong@naver.com"
	 * 3. 문자열을 쪼개서 String[]에 넣기  --> 변수 = {"홍길동", "3", "010-111-1111", "hong@naver.com"}
	 * 4. 학생객체를 만들고, 객체가 null이면 "신규 학생정보 등록에 실패하였습니다."***왜아니지??
	 * 5. 배열객체의 값을 하나씩 학생객체의 값에 대입 (숫자는 문자열을 순자로 변환)
	 * 6. insertStudent()메소드를 통해 학생정보 등록
	 * 		boolean값이 true이면 "## 신규학생정보가 등록"
	 * 				   false이면 "## 신규 학생정보 등록에 실패"
	 */
	public void 학생등록() {
		System.out.println("<< 신규 학생 등록 >>");
		System.out.print("학생정보 입력(이름,학년,전화번호,이메일): ");
		String text = keyboard.getString();
		
		String[] newStudent = text.split(",");	// newStudent={"홍길동", "3", "010-111-1111", "hong@naver.com"}
		
		Student student = new Student();
		
		student.setName(newStudent[0]);
		student.setGrade(Integer.parseInt(newStudent[1]));
		student.setTel(newStudent[2]);
		student.setEmail(newStudent[3]);
		
		boolean isSuccess = service.insertStudent(student);
		if(isSuccess) {
			System.out.println("## 신규학생정보가 등록되었습니다.");
		} else {
			System.out.println("## 신규학생정보 등록에 실패하였습니다.");
		}
	}
	
	/*
	 * 1. "<< 성적 등록 >>"
	 * 2. 학생 이름 입력: 
	 * 3. 성적 입력(국어,영어,수학):  ---> 문자열 쪼개기
	 * 4. 입력한 이름의 학생 객체 안의 Score객체에 성적 대입
	 * 5. insertScore 메소드 실행 후
	 * 		true --> "## 성적 등록이 완료되었습니다."
	 * 		false --> "## 성적 등록에 실패하였습니다."
	 */
	public void 성적등록() {
		System.out.println("<< 성적 등록 >>");
		System.out.print("학생 이름 입력: ");
		String name = keyboard.getString();
		System.out.print("성적 입력(국어,영어,수학): ");
		String text = keyboard.getString();
		
		String[] scores = text.split(",");	// scores={"100","90","80"}
		
		Score score = new Score();
		score.setKor(Integer.parseInt(scores[0]));
		score.setEng(Integer.parseInt(scores[1]));
		score.setMath(Integer.parseInt(scores[2]));
		
		boolean isSuccess = service.insertScore(name,score);
		if(isSuccess) {
			System.out.println("## 성적 등록이 완료되었습니다.");
		} else { 
			System.out.println("## 성적 등록에 실패하였습니다.");
		}
	}
	
	/*
	 * 1. << 전체 학생 조회 >>
	 * 2. getAllStudent메소드를 실행해서 Student[]배열객체를 받는다
	 * 3. 화면에 "이름 학년  번호   이메일" 출력
	 * 4. 반복해서 출력
	 */
	public void 전체학생조회() {
		
		System.out.println("<< 전체 학생 조회 >>");
		
		Student[] students = service.getAllStudent();
		if(students.length == 0) {
			System.out.println("학생정보가 존재하지 않습니다.");
		} else {
			System.out.println("이름\t학년\t번호\t\t이메일");
			
			for(Student item : students) {
				if(item==null) {
					break;
				}
				System.out.print(item.getName()+"\t");
				System.out.print(item.getGrade()+"\t");
				System.out.print(item.getTel()+"\t");
				System.out.println(item.getEmail());
				
			}
			
		}
	}
	
	/*
	 * 1. <<학생성적조회>>
	 * 2. 학생 이름: 
	 * 3. 메소드를 통해 입력받은 이름에 해당하는 학생객체를 반환받기
	 * 		null이면 "## 학생정보가 존재하지 않습니다."
	 * 		null이 아니면 아래와 같이
	 * 4. 이름: 학년: 번호: 메일: 국어: 영어: 수학: 총점: 평균: 
	 * 5. 
	 */
	public void 학생성적조회() {
		System.out.println("<< 학생 성적 조회 >>");
		System.out.print("학생 이름: ");
		String name = keyboard.getString();
		
		Student student = service.findStudentByName(name);
		if(student == null) {
			System.out.println("## 학생정보가 존재하지 않습니다.");
			return;
		} else {
			System.out.println("이름: "+student.getName());
			System.out.println("학년: "+student.getGrade());
			System.out.println("번호: "+student.getTel());
			System.out.println("메일: "+student.getEmail());
			
			Score score = student.getScore();
			System.out.println("국어점수: "+score.getKor());
			System.out.println("영어점수: "+score.getEng());
			System.out.println("수학점수: "+score.getMath());
			System.out.println("총점: "+score.getTotal());
			System.out.println("평균: "+score.getAverage());
			
		}
		
	}
	
	/*
	 * 1.<<성적 변경>> 
	 * 2. 학생 이름: 
	 * 3. 변경할 성적 입력(국어,영어,수학):
	 * 4. 문자열 잘라서 Score객체에 대입 
	 * 5. updateScore 메소드 실행 후 
	 * 		true -> "## 성적 변경이 완료되었습니다."
	 * 		false -> "##성적 변경에 실패하였습니다." 
	 */
	public void 성적변경() {
		System.out.println("<< 성적 변경 >>");
		System.out.print("학생 이름: ");
		String name = keyboard.getString();
		System.out.print("변경할 성적 입력(국어,영어,수학): ");
		String text = keyboard.getString();
		String[] scores = text.split(",");
		
		Score score = new Score();
		score.setKor(Integer.parseInt(scores[0]));
		score.setEng(Integer.parseInt(scores[1]));
		score.setMath(Integer.parseInt(scores[2]));
		
		boolean isSuccess = service.updateScore(name,score);
		if(isSuccess) {
			System.out.println("## 성적 변경 완료");
		} else {
			System.out.println("## 성적 변경 실패");
		}
		
	}
	/*
	 * <<삭제>>
	 * 학생 이름:
	 * 삭제 메소드 실행
	 * true -> 삭제완료
	 */
	public void 학생정보삭제() {
		System.out.println("<< 학생정보 삭제 >>");
		System.out.print("학생 이름: ");
		String name = keyboard.getString();
		
		boolean isSuccess = service.deleteStudent(name);
		if(isSuccess) {
			System.out.println("## 삭제 완료");
		} else {
			System.out.println("## 삭제 실패");
		}
	}
}

 

- 업무로직 객체 

import java.util.Arrays;

public class SchoolService {	//업무로직(구체적인 조건 등)
	
	private Student[] students = new Student[5];
	private int position = 0;
	private int limit = students.length;
	private int size = 5;
	
	/*
	 * <신규 학생 등록>
	 * Student 객체를 입력받으면 Student[] 배열 한칸씩 Student객체를 담기
	 * 1. 반환타입에 해당하는 변수, 초기화
	 * 2. 입력받은 학생이 배열에 있는지 확인
	 * 		-이름을 전달받아서, 배열에 같은 이름이 있는지 확인
	 * 		-있으면 true -> 종료, 없으면 false -> 수행
	 * 3. 배열객체 한칸씩 Student객체 담기
	 * 4. position==limit이면 배열크기 늘리기
	 */
	public boolean insertStudent(Student student) {
		boolean isSuccess = false;
		
		if(!isExist(student.getName())) {	//겹치는 이름이 없으면
			
			students[position]=student;		//배열에 Student객체를 담아
			position++;
			
			isSuccess = true;
			resize();			
		}	
		return isSuccess;
	}
	
	/*
	 * <성적 등록>
	 * 1. 입력한 이름과 겹치는 이름이 배열에 있는지 확인
	 * 		false(일치하는 이름이 없으면) -> false
	 * 2. 입력한 이름으로 등록한 학생정보를 찾기
	 * 		- 찾은 학생정보를 저장할 변수 선언 
	 * 		- 향상된 for문으로 배열의 전체 객체중 해당 이름의 객체를 찾아서 반환
	 * 3. 변수에 저장
	 * 4. true 반환
	 */
	public boolean insertScore(String name, Score score) {
		boolean isSuccess = false;
		
		if(!isExist(name)) {	//배열에 이름이 있는지없는지 확인
			return false;
		}
		
		Student student = findStudentByName(name);
		student.setScore(score);	//학생 객체에 점수 저장
		isSuccess = true; 
		
		return isSuccess;
	}
	
	/*
	 * <전체 학생 조회>
	 * students 배열에 있는 모든 Student 객체를 꺼내기
	 * 
	 */
	public Student[] getAllStudent() {
		if(position==0) {
			return new Student[0];
		}
		
		return students; 
	}
	
	/*
	 * <성적 변경>
	 * 이름과 일치하는 객체가 있는지 찾기
	 * 일치하는 객체를 반환하기
	 * 객체의 성적을 새 성적으로 덮어쓰기
	 */
	public boolean updateScore(String name,Score score) {
		boolean isSuccess = false;
		
		if(!isExist(name)) {
			return false;
		}
		Student findStudent = findStudentByName(name);
		if(findStudent==null)
			return false;
		findStudent.setScore(score);
		isSuccess = true;
		
		return isSuccess;
	}

	/*
	 * <삭제>
	 * 입력한 이름과 일치하는 객체 있는지 확인
	 * 일치하는 객체가 몇번쨰에 있는지 확인
	 * 한칸씩 앞으로 당기기
	 * true 반환 
	 */
	public boolean deleteStudent(String name) {
		
		if(!isExist(name)) {
			return false;
		}
		
		int foundIndex = findIndexByName(name); // 인덱스 반환 
		moveToLeft(foundIndex+1);	//찾은 인덱스를 삭제하기 위해서는 그 다음칸부터 앞으로 덮어씀
		
		return true;
	}
	
	
	//메소드 추출 
	
	// 입력한 이름과 일치하는 객체를 배열에서 찾아서 반환
	public Student findStudentByName(String name) {
		Student findStudent = null;
		for(Student item : students) {
			if(item==null) {
				break;
			}
			if(item.getName().equals(name)) {
				findStudent = item;
			}
		}
		return findStudent;
	}

	
	
	// 한칸씩 앞으로 당겨서 덮으쓰는 메소드
	// 배열의 크기(limit) = 5 이면, position = 4 (값 하나를 입력하면 그 다음칸에 +1해서 준비)
	// 항상 position보다 한칸 앞까지만 값이 있음 
	// 값을 다 당기고 마지막 position에 있던 값을 null로 바꾸고, position을 -1 함
	private void moveToLeft(int beginIndex) {
		for(int index = beginIndex; index<position; index++) {
			students[index-1] = students[index];
		}
		students[position-1] = null;
		position--;
	}

	/**
	 * 이름을 전달받아서 이름과 일치하는 학생정보가 저장된 배열의 인덱스 반환
	 * @param name 학생이름
	 * @return 배열의 인덱스, 일치하는 학생정보가 없으면 -1 반환 
	 */
	// 찾는 객체가 몇번째에 있는지 
	private int findIndexByName(String name) {
		for(int index=0; index<position; index++) {	//값을 3개 입력하면, position이 3, position보다는 무조건 작을것
			Student student = students[index];
			if(student.getName().equals(name)) {	// 이름이 같으면
				return index;						// 그 인덱스를 바로 반환
			}
		}
		return -1;	// index에 절대 없는 값(=일치하는 학생정보가 없다) 
	}
	
	
	// 배열 크기 늘리기
	private void resize() {
		if(position==limit) {
			limit+=size;
			Student[] dest = new Student[limit];
			System.arraycopy(students, 0, dest, 0, students.length);
			students = dest;
		}
	}

	// 입력한 이름과 같은 객체가 배열에 있는지 확인 
	private boolean isExist(String name) {
		boolean isStudentExist = false;	//입력한 객체의 이름과 일치하는 이름이 배열에 있는지 확인
		for(Student item : students) {
			if(item==null) {
				break;
			}
			if(item.getName().equals(name)) {
				isStudentExist = true;		// 겹치는 이름이 있으면 
				break;
			}
		}
		return isStudentExist;		// 이름이 있으면 true인 상태, 없으면 false인 상태
	}	
}

 

-실행객체

public class SchoolApp {
	
	public static void main(String[] args) {
		SchoolController controller = new SchoolController();
		controller.실행();
	}
}

 

-출력

-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 1
<< 신규 학생 등록 >>
학생정보 입력(이름,학년,전화번호,이메일): 홍길동,1,010-1111-1111,hong@nvaer.com
## 신규학생정보가 등록되었습니다.


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 1
<< 신규 학생 등록 >>
학생정보 입력(이름,학년,전화번호,이메일): 김유신,2,010-2222-2222,kim@naver.com
## 신규학생정보가 등록되었습니다.


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 2
<< 성적 등록 >>
학생 이름 입력: 홍길동
성적 입력(국어,영어,수학): 90,80,90
## 성적 등록이 완료되었습니다.


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 2
<< 성적 등록 >>
학생 이름 입력: 김유신
성적 입력(국어,영어,수학): 100,80,70
## 성적 등록이 완료되었습니다.


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 3
<< 전체 학생 조회 >>
이름	학년	번호		이메일
홍길동	1	010-1111-1111	hong@nvaer.com
김유신	2	010-2222-2222	kim@naver.com


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 4
<< 학생 성적 조회 >>
학생 이름: 김유신
이름: 김유신
학년: 2
번호: 010-2222-2222
메일: kim@naver.com
국어점수: 100
영어점수: 80
수학점수: 70
총점: 250
평균: 83


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 5
<< 성적 변경 >>
학생 이름: 홍길동
변경할 성적 입력(국어,영어,수학): 80,80,50
## 성적 변경 완료


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 4
<< 학생 성적 조회 >>
학생 이름: 홍길동
이름: 홍길동
학년: 1
번호: 010-1111-1111
메일: hong@nvaer.com
국어점수: 80
영어점수: 80
수학점수: 50
총점: 210
평균: 70


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 6
<< 학생정보 삭제 >>
학생 이름: 김유신
## 삭제 완료


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 3
<< 전체 학생 조회 >>
이름	학년	번호		이메일
홍길동	1	010-1111-1111	hong@nvaer.com


-----------------------------------------------------------------------
1.학생등록  2.성적등록  3.전체학생조회  4.학생성적조회  5.성적변경  6.삭제  0.종료
-----------------------------------------------------------------------

메뉴선택: 0
## 프로그램을 종료합니다.

 

 

 

 

 

 

public boolean insertStudent(Student student) {
	boolean isSuccess = false;
		
	if(!isExist(student)) {	
			
		students[position]=student;		
		position++;
			
		isSuccess = true;
		resize();			
	}	
	return isSuccess;
}

 

private boolean isExist(String name) {
	boolean isStudentExist = false;	//입력한 객체의 이름과 일치하는 이름이 배열에 있는지 확인
	for(Student item : students) {
		if(item==null) {
			break;
		}
		if(item.getName().equals(name)) {
			isStudentExist = true;		
			break;
		}
	}
	return isStudentExist;

 

******** if ( ! isExist() ) 라고 하는 이유!!!!!!

 

- isExist(name) 메소드 실행 결과, 

  일치하는 이름이 있으면 true, 일치하는 이름이 없으면 false 반환

 

-> isExist() = true : 중복되는 이름이 있다    ----> 다음꺼 수행 못함   

    isExist() = false : 중복되는 이름이 없다   ----> 다음꺼 수행

 

 

 if ( ! isExist() ) 라고 하면 

 

- isExist() = true (존재함) 일 때, 

  ! isExist() = ! true = false 

  -> 수행 가능 (존재하는 이름이 없음 으로 바꿨음) 

 

- isExist() = false (존재하지 않음) 일 때, 

  ! isExist() = ! false = true 

 -> 어차피 수행 못함

 

if ( ! isExist(student) )    ==> '학생(student)'이 '존재하지(isExist)' '않으면( ! ) '