Q ) 중간고사 성적을 출력하라.
조건 1 ) 학생들의 중간고사 국어, 영어, 수학, 그리고 전과목 총점과 평균을 출력하세요.
조건 2 ) 학생 개별 과목 점수와 총점을 출력하세요.
조건 3 ) 등수를 출력하세요.

 

1. 실행 클래스 (하단에 개선 버전 추가)

import java.util.Arrays;

public class ScorePrint_executionClass {
	public static void main(String[] args) {
		
		// Step 1. 학생 10명의 데이터를 객체데이터로 만들어 배열로 생성.		
		ScorePrint s[] = new ScorePrint[10]; // 클래스 ScorePrint를 이름 s로 배열로 만들거다. ScorePrint를 10개를 만들어 메모리에 할당해라. 즉, 배열 하나로 묶어서 이곳에 0번부터 9번까지 10개의 ScorePrint 클래스 방을 오려다 붙인거다.
		s[0] = new ScorePrint("홍길동", 100, 100, 80);	// s의 0번방 ScorePrint 클래스에는 "홍길동", 100, 100을 생성자로 넣어라.
		s[1] = new ScorePrint("둘리", 10, 10, 90);		// s의 1번방 ScorePrint 클래스에는 "둘리", 10, 10을 생성자로 넣어라.
		s[2] = new ScorePrint("고길동", 74, 46, 34);
		s[3] = new ScorePrint("짱구", 39, 85, 60);
		s[4] = new ScorePrint("이순신", 41, 65, 45);
		s[5] = new ScorePrint("장보고", 26, 100, 70);
		s[6] = new ScorePrint("이성계", 93, 57, 76);
		s[7] = new ScorePrint("희동이", 24, 41, 20);
		s[8] = new ScorePrint("또치", 98, 95, 0);
		s[9] = new ScorePrint("박혁거세", 32, 54, 99);
		
		// Step 2. 객체데이터를 이용해 과목별 총점을 구한 후 평균을 구함.
		int totalMidKorean = 0;
		int totalMidEnglish = 0;
		int totalMidMath = 0;
		int numberOfstudents = s.length;
		for (int i = 0; i < numberOfstudents; i++) {
			totalMidKorean = totalMidKorean + s[i].midKorean;
			totalMidEnglish = totalMidEnglish + s[i].midEnglish;
			totalMidMath = totalMidMath + s[i].midMath;
		}
		int totalMidAllClass = totalMidKorean + totalMidEnglish + totalMidMath;
		
		double avgMidKorean = (double)totalMidKorean / numberOfstudents;
		double avgMidEnglish = (double)totalMidEnglish / numberOfstudents;
		double avgMidMath = (double)totalMidMath / numberOfstudents;
		double avgMidAllClass = (double)(avgMidKorean + avgMidEnglish + avgMidMath) / 3;
		
		System.out.println("중간고사 국어 총점은 " + totalMidKorean);
		System.out.println("중간고사 국어 평균은 " + avgMidKorean);
		System.out.println("중간고사 영어 총점은 " + totalMidEnglish);
		System.out.println("중간고사 영어 평균은 " + avgMidEnglish);
		System.out.println("중간고사 수학 총점은 " + totalMidMath);
		System.out.println("중간고사 수학 평균은 " + avgMidMath);	
		System.out.println("중간고사 전과목 총점은 " + totalMidAllClass);
		System.out.println("중간고사 전과목 평균은 " + avgMidAllClass);
		
		System.out.println("");
		
		// Step 3. 학생의 데이터를 관리하고 등수를 구하기 위해 매트릭스로 각 행에 한 사람씩 객체 데이터를 생성.
		String studentRank[][] = new String[10][3];		// 나중에 등수를 넣을거라 [10][2] 대신 [10][3]으로 생성.
		for (int i = 0; i < numberOfstudents; i++) {
			System.out.println(s[i].name + "의 국어 점수는 "  + s[i].midKorean + " , 영어 점수는 " + s[i].midEnglish + " , 수학 점수는 " + s[i].midMath + " , 총점은 " + s[i].midSum);
			studentRank[i][0] = s[i].name;							// 1열에는 이름을 넣는다.
			studentRank[i][1] = Integer.toString(s[i].midSum);		// 2열에는 개인 총점을 넣는다.
			studentRank[i][2] = "1";								// 3열에는 등수를 넣는다.
		}
		
		
		System.out.println("");
		
		
		// Step 4. 등수 구하기. 모두 1등으로 시작해서 나보다 점수 높은 사람이 있다면 +1등씩 더함.
		for (int i = 0; i < numberOfstudents; i++) {
			int rankTemp = 1;	// i번째 학생의 등수 계산을 위해 1등으로 선언.
			for (int j = 0; j< numberOfstudents; j++) {
				if (s[i].midSum < s[j].midSum) {	// i번째 학생이 j번째 학생보다 점수가 낮다면 +1등씩 더함.
					rankTemp = rankTemp + 1;		// Integer.parseInt(studentRanki[i][1]) < Integer.parseInt(studentRanki[j][1])
				}
				
			}
			studentRank[i][2] = Integer.toString(rankTemp);	// 매트릭스가 String이라 형변환.
		}

//		// 위에 Step 4. 는 Step 3.에서 만든 매트릭스를 이용해 이렇게 구할 수도 있다. 다만 형변환을 계속 해야해서 위에 방법으로 구현했다.
//		for (int i = 0; i < numberOfstudents; i++) {
//			int rankTemp = 1;	// i번째 학생의 등수 계산을 위해 1등으로 선언.
//			for (int j = 0; j< numberOfstudents; j++) {
//				int prevStudent = Integer.parseInt(studentRank[i][1]);
//				int nextStudent = Integer.parseInt(studentRank[j][1]);
//				if (prevStudent < nextStudent) {	// i번째 학생이 j번째 학생보다 점수가 낮다면 +1등씩 더함.
//					rankTemp = rankTemp + 1;
//				}
//				
//			}
//			studentRank[i][2] = Integer.toString(rankTemp);	// 매트릭스가 String이라 형변환.
//		}
		
	
		
		System.out.println("");
		
		

//		// [10][3] 매트릭스 디버깅용
//		for (int i = 0; i < numberOfstudents; i++) {
//			System.out.println(Arrays.toString(studentRank[i]));
//		}
//		System.out.println("");
		
		
		// Step 5.1 등수 출력하기.
		
		for (int i = 0; i < numberOfstudents; i++) {
			System.out.println(studentRank[i][0] + "은 " + studentRank[i][2] + "등입니다.");
		}
		
		System.out.println("");
		
		// Step 5.2 등수로 정렬해서 출력하기. 
		
		String RankAscendingOrder[] = new String[10];
		
		for (int i = 0; i < numberOfstudents; i++) {
			int rankTemp = 1;
			for (int j = 0; j< numberOfstudents; j++) {
				if (s[i].midSum < s[j].midSum) {	// i번째 학생이 j번째 학생보다 점수가 낮다면 +1등씩 더함.
					rankTemp = rankTemp + 1;
				}
				
			}
			RankAscendingOrder[rankTemp - 1] = studentRank[i][0];	// 1등부터 10등까지니까 배열에 0번부터 9번까지 넣어야 해서 'rankTemp - 1'.
		}
		

		for (int i = 0; i < numberOfstudents; i++) {
			System.out.println((i + 1) + "등은 " + RankAscendingOrder[i] + "입니다.");
		}
		
		
	}

}

결과 : 

중간고사 국어 총점은 537
중간고사 국어 평균은 53.7
중간고사 영어 총점은 653
중간고사 영어 평균은 65.3
중간고사 수학 총점은 574
중간고사 수학 평균은 57.4
중간고사 전과목 총점은 1764
중간고사 전과목 평균은 58.800000000000004

홍길동의 국어 점수는 100 , 영어 점수는 100 , 수학 점수는 80 , 총점은 280
둘리의 국어 점수는 10 , 영어 점수는 10 , 수학 점수는 90 , 총점은 110
고길동의 국어 점수는 74 , 영어 점수는 46 , 수학 점수는 34 , 총점은 154
짱구의 국어 점수는 39 , 영어 점수는 85 , 수학 점수는 60 , 총점은 184
이순신의 국어 점수는 41 , 영어 점수는 65 , 수학 점수는 45 , 총점은 151
장보고의 국어 점수는 26 , 영어 점수는 100 , 수학 점수는 70 , 총점은 196
이성계의 국어 점수는 93 , 영어 점수는 57 , 수학 점수는 76 , 총점은 226
희동이의 국어 점수는 24 , 영어 점수는 41 , 수학 점수는 20 , 총점은 85
또치의 국어 점수는 98 , 영어 점수는 95 , 수학 점수는 0 , 총점은 193
박혁거세의 국어 점수는 32 , 영어 점수는 54 , 수학 점수는 99 , 총점은 185


홍길동은 1등입니다.
둘리은 9등입니다.
고길동은 7등입니다.
짱구은 6등입니다.
이순신은 8등입니다.
장보고은 3등입니다.
이성계은 2등입니다.
희동이은 10등입니다.
또치은 4등입니다.
박혁거세은 5등입니다.

1등은 홍길동입니다.
2등은 이성계입니다.
3등은 장보고입니다.
4등은 또치입니다.
5등은 박혁거세입니다.
6등은 짱구입니다.
7등은 고길동입니다.
8등은 이순신입니다.
9등은 둘리입니다.
10등은 희동이입니다.


 

2. 함수 메소드가 있는 클래스

public class ScorePrint {
	
	String name;
	int midKorean;
	int midEnglish;
	int midMath;
	int midSum;
	
	// 생성자 이용하기. 일반적으로 객체데이터 만들 때는 생성자 이용하는게 코드가 간결해진다.
	ScorePrint(String name, int midKorean, int midEnglish, int midMath) {
		this.name = name;
		this.midKorean = midKorean;
		this.midEnglish = midEnglish;
		this.midMath = midMath;
		this.midSum = this.midKorean + this.midEnglish + this.midMath;
	}

}

 

 

등수를 구하는 것과 정렬을 하는 것은 비슷해 보이지만 차이가 있다.

등수를 구할 때는 시작 값을 1로 잡고 각각의 i 모두가 나를 제외한 모든 j와 비교해서 카운트를 하는 것이라 

for (i = 0; i < 길이; i++)
    for (j = 0; j < 길이; j++)

이지만 정렬을 할 때는 앞에 있는 값과 뒤에 있는 값을 구분하고 자리를 교환하는 것이기 때문에 n번째 i는 0번째 j부터 할 필요가 없다. 이미 했으니까.

for (i = 0; i < 길이; i++)
    for (j = i; j < 길이; j++)

따라서 두 번째 for문 j의 시작이 다르다.

 

 

그리고 위에 실행 클래스의 Step 3. ~ Step 5.2 까지의 과정은 다음과 같이 짧게 개선될 수 있다.

1.1 실행 클래스 (개선 버전)

// 객체데이터와 생성자의 활용, 등수와 매트릭스 정렬에 대해 학습한다.
// 등수를 구하는 이중 for문과 정렬을 하는 이중 for문은 비슷하지만 다르다. j의 시작점에 대해 주목한다.

import java.util.Arrays;

public class ScorePrint_executionClass {
	public static void main(String[] args) {
		
		// Step 1. 학생 10명의 데이터를 객체데이터로 만들어 배열로 생성.		
		ScorePrint s[] = new ScorePrint[10]; // 클래스 ScorePrint를 이름 s로 배열로 만들거다. ScorePrint를 10개를 만들어 메모리에 할당해라. 즉, 배열 하나로 묶어서 이곳에 0번부터 9번까지 10개의 ScorePrint 클래스 방을 오려다 붙인거다.
		s[0] = new ScorePrint("홍길동", 100, 100, 80);	// s의 0번방 ScorePrint 클래스에는 "홍길동", 100, 100을 생성자로 넣어라.
		s[1] = new ScorePrint("둘리", 10, 10, 90);		// s의 1번방 ScorePrint 클래스에는 "둘리", 10, 10을 생성자로 넣어라.
		s[2] = new ScorePrint("고길동", 74, 46, 34);
		s[3] = new ScorePrint("짱구", 39, 85, 60);
		s[4] = new ScorePrint("이순신", 41, 65, 45);
		s[5] = new ScorePrint("장보고", 26, 100, 70);
		s[6] = new ScorePrint("이성계", 93, 57, 76);
		s[7] = new ScorePrint("희동이", 24, 41, 20);
		s[8] = new ScorePrint("또치", 98, 95, 0);
		s[9] = new ScorePrint("박혁거세", 32, 54, 99);
		
		// Step 2. 객체데이터를 이용해 과목별 총점을 구한 후 평균을 구함.
		int totalMidKorean = 0;
		int totalMidEnglish = 0;
		int totalMidMath = 0;
		int numberOfstudents = s.length;
		for (int i = 0; i < numberOfstudents; i++) {
			totalMidKorean = totalMidKorean + s[i].midKorean;
			totalMidEnglish = totalMidEnglish + s[i].midEnglish;
			totalMidMath = totalMidMath + s[i].midMath;
		}
		int totalMidAllClass = totalMidKorean + totalMidEnglish + totalMidMath;
		
		double avgMidKorean = (double)totalMidKorean / numberOfstudents;
		double avgMidEnglish = (double)totalMidEnglish / numberOfstudents;
		double avgMidMath = (double)totalMidMath / numberOfstudents;
		double avgMidAllClass = (double)(avgMidKorean + avgMidEnglish + avgMidMath) / 3;
		
		System.out.println("중간고사 국어 총점은 " + totalMidKorean);
		System.out.println("중간고사 국어 평균은 " + avgMidKorean);
		System.out.println("중간고사 영어 총점은 " + totalMidEnglish);
		System.out.println("중간고사 영어 평균은 " + avgMidEnglish);
		System.out.println("중간고사 수학 총점은 " + totalMidMath);
		System.out.println("중간고사 수학 평균은 " + avgMidMath);	
		System.out.println("중간고사 전과목 총점은 " + totalMidAllClass);
		System.out.println("중간고사 전과목 평균은 " + avgMidAllClass);
		
        
        
		System.out.println("");
	
    
		
		// ***** Step 3. ~ Step 5.2 배열 자체를 정렬시키는 방법으로 축약하기 *****
		// New Step 3. 학생의 데이터를 관리하고 등수를 구하기 위해 매트릭스로 각 행에 한 사람씩 객체 데이터를 생성.
		String studentRank[][] = new String[10][2];		// 이 경우 등수를 배열에 포함할 필요가 없어  studentRank[10][2]로 만들어도 된다.
		for (int i = 0; i < numberOfstudents; i++) {
			System.out.println(s[i].name + "의 국어 점수는 "  + s[i].midKorean + " , 영어 점수는 " + s[i].midEnglish + " , 수학 점수는 " + s[i].midMath + " , 총점은 " + s[i].midSum);
			studentRank[i][0] = s[i].name;							// 1열에는 이름을 넣는다.
			studentRank[i][1] = Integer.toString(s[i].midSum);		// 2열에는 개인 총점을 넣는다.
		}
		
		
		System.out.println("");
		
		
		// New Step 4. 배열 자체를 정렬시키키고 출력하기.
		for (int i = 0; i < numberOfstudents; i++) {		// i를 앞에 있는 학생, j를 뒤에 있는 학생으로 선언하고 비교하기.
			for (int j = i; j< numberOfstudents; j++) {		// 이때는 int j = 0 이 아니라 int j = i 로 시작한다.
				
				int prevStudent = Integer.parseInt(studentRank[i][1]);
				int nextStudent = Integer.parseInt(studentRank[j][1]);
				if (prevStudent < nextStudent) {	// 앞에 있는 학생 < 뒤에 있는 학생 라면 실행.
					String temp[] = studentRank[i];
					studentRank[i] = studentRank[j];
					studentRank[j] = temp;
				}
				
			}

		}
		
		
		for (int i = 0; i < numberOfstudents; i++) {
			System.out.println((i + 1) + "등은 " + studentRank[i][0] + "입니다.");
		}

		
	}

}


결과 : 

중간고사 국어 총점은 537
중간고사 국어 평균은 53.7
중간고사 영어 총점은 653
중간고사 영어 평균은 65.3
중간고사 수학 총점은 574
중간고사 수학 평균은 57.4
중간고사 전과목 총점은 1764
중간고사 전과목 평균은 58.800000000000004


홍길동의 국어 점수는 100 , 영어 점수는 100 , 수학 점수는 80 , 총점은 280
둘리의 국어 점수는 10 , 영어 점수는 10 , 수학 점수는 90 , 총점은 110
고길동의 국어 점수는 74 , 영어 점수는 46 , 수학 점수는 34 , 총점은 154
짱구의 국어 점수는 39 , 영어 점수는 85 , 수학 점수는 60 , 총점은 184
이순신의 국어 점수는 41 , 영어 점수는 65 , 수학 점수는 45 , 총점은 151
장보고의 국어 점수는 26 , 영어 점수는 100 , 수학 점수는 70 , 총점은 196
이성계의 국어 점수는 93 , 영어 점수는 57 , 수학 점수는 76 , 총점은 226
희동이의 국어 점수는 24 , 영어 점수는 41 , 수학 점수는 20 , 총점은 85
또치의 국어 점수는 98 , 영어 점수는 95 , 수학 점수는 0 , 총점은 193
박혁거세의 국어 점수는 32 , 영어 점수는 54 , 수학 점수는 99 , 총점은 185

1등은 홍길동입니다.
2등은 이성계입니다.
3등은 장보고입니다.
4등은 또치입니다.
5등은 박혁거세입니다.
6등은 짱구입니다.
7등은 고길동입니다.
8등은 이순신입니다.
9등은 둘리입니다.
10등은 희동이입니다.

 

 

------------------------------------ 다른 방법 추가 ------------------------------------

public class Student_executionClass {
	public static void main(String[] args) {
		Student stu[] = new Student[10];	        // Student 클래스를 자료형으로 가지는 stu라는 이름의 배열을 만들어라. 그리고 비어있는 방 10칸을 사용할 수 있게 메모리에 배정해 초기화해라. (이건 배열을 만드는거다. 아래 객체데이터를 만드는 것과 혼동하지 말 것.)
		stu[0] = new Student("홍길동", 100, 100, 80);	// stu 배열의 0번 방에 Student를 오려다 넣어라. 그 방은 "홍길동", 100, 100, 80을 생성자로 가진다. (객체 데이터를 만드는거.)
		stu[1] = new Student("둘리", 10, 10, 90);		// stu 배열의 1번 방에 Student를 오려다 넣어라. 그 방은 "둘리", 10, 10, 90을 생성자로 가진다.
		stu[2] = new Student("고길동", 74, 46, 34);
		stu[3] = new Student("짱구", 39, 85, 60);
		stu[4] = new Student("이순신", 41, 65, 45);
		stu[5] = new Student("장보고", 26, 100, 70);
		stu[6] = new Student("이성계", 93, 57, 76);
		stu[7] = new Student("희동이", 24, 41, 20);
		stu[8] = new Student("또치", 98, 95, 0);
		stu[9] = new Student("박혁거세", 32, 54, 99);
		
		int totalKorScore = 0;
		int totalMathScore = 0;
		int totalEngScore = 0;
		int stuLen = stu.length;
		for (int i = 0; i < stuLen; i++) {
			totalKorScore = totalKorScore + stu[i].korScore;
			totalMathScore = totalMathScore + stu[i].mathScore;
			totalEngScore = totalEngScore + stu[i].engScore;

		}
		
		// 지난번 순위를 이중 for문으로 구했던 것의 바깥 for문에 해당한다. i 번째 학생.
		for (int i = 0; i < stuLen; i++) {	// 위 for문에 합칠 수 없다. 0~9번 방이 모두 채워진 이후에 i번째 학생의 점수를 0~9번째 학생의 점수와 비교를 해야하기 때문이다.
			stu[i].printInfo();			// 얘는 그냥 i번째 정보만 있으면 되기 때문에 위 for문에 들어가도 상관 없다. 다만 총점, 평균, 등수를 한 줄에 출력하기 위해 여기 넣었다.
			stu[i].printLevel(stu);		// 객체 데이터 stu = {stu[0] ~ stu[9]}배열 전체를 인풋 파라미터로 전달한다.
		}
			
	}

}
public class Student {
	private String name;	// 직접 접근하지 않는 애들은 private로 보호를 해줘도 된다. (생성자 말고 stu[i].name 이런애들 말하는거다.)
	int korScore;			// 얘네는 stu[i].korScore로 직접 접근을 하기 때문에 보호하면 안 된다. 할거면 setter getter 엄청나게 만들어야한다.
	int mathScore;
	int engScore;
	private int totalScore;
	private double avgScore;
	private int level = 1;

	Student(String name, int korScore, int mathScore, int engScore) {
		this.name = name;
		this.korScore = korScore;
		this.mathScore = mathScore;
		this.engScore = engScore;
		
		// 이 부분을 아래 calc()로 따로 빼서 분리할 수 있다.
//		this.totalScore = korScore + mathScore + engScore;
//		this.avgScore = (double)this.totalScore / 3;
		this.calc();
	}
	
	public void calc() {
		this.totalScore = korScore + mathScore + engScore;
		this.avgScore = (double)this.totalScore / 3;		
	}
	
	
	
	public void printInfo() {
		System.out.print("이름: " + this.name);
		System.out.print("  국어: " + this.korScore);
		System.out.print("  수학: " + this.korScore);
		System.out.println("  영어: " + this.korScore);
		System.out.print("학생 총점: " + this.totalScore + " 평균: " + this.avgScore);
	}
	
	// 지난번 순위를 이중 for문으로 구했던 것의 안쪽 for문에 해당한다. 이거를 통째로 Student_executionClass의 for문 안에 pritLevel 안에 오려다 붙여보면 이해가 될거다.
	public void printLevel(Student[] student) {	// Student_executionClass한테서 객체데이터를 배열로 받기 때문에 인풋 파라미터를 이렇게 받는다. stu = {stu[0] ~ stu[9]} 
		int studentLen = student.length;
		for (int j = 0; j < studentLen; j++) {	// 지역 변수라 i로 해도 되지만 지난번과 비교를 쉽게 하기 위해 j로 잡았다.
			if (this.totalScore < student[j].totalScore) {
				this.level++;		
			}
		}
		System.out.println("  등수: " + level);
	}
	
	// 위 로직을 순위를 구하는 로직과 출력을 하는 로직을 따로 분리하면 이렇게 사용할 수 있다.
//	public void findMyLevel(Student[] student) {
//		int studentLen = student.length;
//		for (int j = 0; j < studentLen; j++) {	// 지역 변수라 i로 해도 되지만 지난번과 비교를 쉽게 하기 위해 j로 잡았다.
//			if (this.totalScore < student[j].totalScore) {
//				this.level++;		
//			}
//		}
//	}
//	
//	public void printLevel(Student[] student) {	// Student_executionClass한테서 객체데이터를 배열로 받기 때문에 인풋 파라미터를 이렇게 받는다. stu = {stu[0] ~ stu[9]} 
//		this.findMyLevel(student);
//		System.out.println("  등수: " + level);	// 얘만 남기고 위에 등수를 구하는 로직은 따로 메소드로 뺀 다음 this.findMyLevel(student);로 넘겨줄 수도 있다.
//	}
	
	
	

}

+ Recent posts