본문 바로가기

JAVA/DAY 10 _ 23.08.30

Student Manager V1 (original)

import java.util.*;	
public class P1_main {

public static void main(String[] args) {
		
    // 기능 : 1. 학생정보입력, 2. 학생정보 리스트 출력, 3. 정보 검색, 4. 정보 삭제, 5. 점수통계
    // 학생 정보 : 1.이름, 2.나이, 3.점수 

    Scanner scn = new Scanner(System.in);	// 2. import

    String[] nameList = new String[5];		// 4-4. 이 메모리들은 heap메모리에 저장되겠지.
    int[] ageList = new int[5];			// 스코프 탈출순간 주소값이 삭제되어 heap메모리의 정보도 삭제됨
    int[] scoreList = new int[5];		// ★★★ 최종까지 누적되어야할 정보는 while블록 밖으로 나가자고!!!

    int count = 0;				// 5. 학생 정보가 입력될때마다 conut가 증가되게 해야한다...

 

1. 메뉴, 프로그램 종료

System.out.println("======== 학생정보 관리프로그램 V1 ========");

while(true) {

    System.out.println("===== MENU(현재 정보 입력된 학생 수 : " + count + ") =====");\
    // 1. command user interface생성
    System.out.println("1. 정보 입력");
    System.out.println("2. 리스트 출력");
    System.out.println("3. 정보 검색");
    System.out.println("4. 정보 삭제");
    System.out.println("5. 점수 통계");
    System.out.println("q. 프로그램 종료");

    System.out.print("입력 > ");		
    String command = scn.nextLine();	
    // 2-1. 밑에 scn과 순서가 바뀌면 그냥 깜박이기만함. 입력해야되는걸 모를 수도있다!!
    // 2-2. 내가 while문밖에 입력을 넣으니까 잘못된입력+enter.. 가 반복된다 ㅠㅠ


    if(command.equals("q")) {			
        break;					
    }						
    
    // 3-1. 입력되는 command변수가 q와 같다면 프로그램 종료를 하겠다.
    // 3-2. 왜 else if에 같이 X? --> 종료는 개념이 달라서! 그냥 위로 올려.
    // --> 논리적으로 else if로 맨밑에 넣어도 돌아가긴 한다.

 

2. 정보등록

if(command.equals("1")) {	

    System.out.println("학생 정보등록");

    System.out.print("이름 입력 > ");
    String name = scn.nextLine();


    System.out.print("나이 입력 > ");				
    String inputAge = scn.nextLine();					
    int age = Integer.parseInt(inputAge);				
	
    // 4-1. 나이를 출력만 하는경우 (산술연산 X) -> String
    // 산술연산 해야하는 경우 -> int
    // 4-2. 문자를 넣으면 숫자로 return해준다
	
    System.out.print("점수 입력 > ");						
    String inputScore = scn.nextLine();					
    int score = Integer.parseInt(inputScore);			
    
    // 4-3. 정보들은 작성하고 스코프 탈출순간에 바로 소멸된다... 
    // ★★★ 배열의 필요성(정보를 묶기위해)
    // 이름, 나이, 점수의 배열을 각각 1중으로 따로 만드는게 정답!
    // int로 type이 같다고해서 같이 묶는게 아니야. ex) [10][2]로 이중배열 만드는게 X
    // 나이랑 점수는 개념이 다르니까 같은 개념끼리 따로 만들어야지. ★★★
    // {민지 20 98}가 아니라, {민지, 지민}{20, 22}{98, 85}
    // {민지 20 98} ---> 이거는 CLASS...하하
    

    // 5-1. 0번째 배열값을 넣고 / 5-3. 다시돌아와서 1번째 배열값을 넣을 수 있겠지
    ageList[count] = age;
    nameList[count] = name;					
    scoreList[count] = score;

    count++;		
    // 5-2. conut값이 +1되면 여기다 넣어야겠지?
    // 5-3. 근데 count가 5이상되면 stack overflow가 생긴다...
    

    // 5-4. ★★★ memory가 꽉찼을 때, 배열 메모리를 증가하는 방법 (aka.무한호텔ㅋㅋ)
    if(count == nameList.length) {					
        String[] tempNameList = new String[nameList.length * 2];
        for(int x = 0 ; x < nameList.length ; x++) {

            tempNameList[x] = nameList[x];				
        }												
        nameList = tempNameList;						

// 	tempNameList는 heap에 새 메모리를 만든거니까 내용을 복사하는 과정이 필요함		
// 	for문 탈출하는 순간 heap메모리의 nameList도 소멸되겠지
// 	★★★ 이게 필요하다. 주소값을 같게 해줘야하는 것 같은데?
// 	([]가 없어야하는 이유는 내용이아니라 주소값을 옮기는거니까!!)
// 	heap메모리의 nameList가 소멸돼도 같은 주소값이 남아있으니까 내용자체는 계속 남아있는 것!!!
// 	if탈출하는 순간 stack메모리의 tNL가 소멸돼도
// 	stack의 nL와 heap의 tNL의 주소값이 같으므로 내용이 보존됨.(깔끔한 메모리 관리 ★★★)


        int[] tempAgeList = new int[ageList.length * 2];
        for(int x = 0 ; x < ageList.length ; x++) {
            tempAgeList[x] = ageList[x];	
        }
        ageList = tempAgeList;


        int[] tempScoreList = new int[scoreList.length * 2];
        for(int x = 0 ; x < scoreList.length ; x++) {
            tempScoreList[x] = scoreList[x];	
        }
        scoreList = tempScoreList;

    }
System.out.println("입력이 완료 되었습니다");

 

3. 리스트 출력

}else if(command.equals("2")) {

    System.out.println("==== 학생 리스트 출력 ====");	// 6. 몇명까지의 이름, 나이, 점수를 주르륵 출력하도록.
    for(int x = 0 ; x < count ; x++) {
        String name = nameList[x];			// 6-1. result가 필요없는 변수인것처럼, String name.. 
        						// 이 3개도 그냥 syso에 넣으면 되긴한다!
        int age = ageList[x];				// 좀 더 보기 명확하게 하도록 한거임.
        int score = scoreList[x];

        System.out.println("이름 : " + name + ", 나이 : " + age + ", 점수 : " + score);

    }

    if(count == 0) {
        System.out.println("입력된 학생 정보가 없습니다. 계속하려면 enter를 입력하세요");
        // scn.nextLine();		
        // 6-2. 여기에 scn을 안넣는 이유는.... (출력해보고 다시 생각)

    }

 

4. 정보 검색

}else if(command.equals("3")) {
    System.out.println("==== 학생 검색 ====");
    System.out.print("검색할 학생의 이름을 입력하세요 > ");
    String inputSearchWord = scn.nextLine();

    int searchCount = 0;				// 7-1. 몇명이 검색됐는지 확인할 수 있음
    for(int x = 0 ; x < count ; x++) {			// 7. 돌아가면서 이름이 있는지 확인

        if(nameList[x].contains(inputSearchWord)) {
        // 7-3. inputSearchWord.equals(nameList[x])
	// nameList[x].equals(inputSearchWord) 위아래 둘다된다 --> 이건 민지 != 이민지로 인식함
	// 저 API는 민지 == 이민지 == 김민지 (민지만 검색해도 포함된 모든 이름이 뜬다는거)
        
        
            String name = nameList[x];						
            int age = ageList[x];						
            int score = scoreList[x];

            System.out.println("이름 : " + name + ", 나이 : " + age + ", 점수 : " + score);
            searchCount++;
        }


    }
    System.out.println(searchCount + "명이 검색되었습니다");	// 7-2. 동명이인이 있으면 그 정보들을 다 보여줌! 신기하노

 

5. 정보 삭제

}else if(command.equals("4")) {	 
// 9. 삭제 : 정확히 같은 이름(.equals)을 찾아서, 그 정보를 삭제할게.

    System.out.println("==== 학생정보 삭제 ====");
    System.out.print("삭제할 학생의 이름을 입력하세요 > ");
    String deleteName = scn.nextLine();

    int deleteCount = 0;
    for(int x = 0 ; x < count ; x++) {

        if(deleteName.equals(nameList[x])) {

            for(int y = x ; y < count-1 ; y++) {		
                nameList[y] = nameList[y+1];		// 9-1. 1개만 삭제하는건 여기서만 끝내도 되는데
                ageList[y] = ageList[y+1];				
                scoreList[y] = scoreList[y+1];			
            }
            x--;			
            // 9-2. 계속 반복하려면 -> 12345이면 2345가 되니까 x가 1에서 3으로 건너뛰겠지. - 잘해주기
            count--;			// 9-3. 확인할 값이 5개에서 4개로 줄었으니까뭐... 하하	
            deleteCount++;
        }
    }
    System.out.println(deleteCount + "명의 학생 정보가 삭제되었습니다");
// 9-4. 배열의 단점 : 백만개가있고 맨앞을 삭제하고싶으면 그걸 다~~ 앞으로 밀어넣는...삭제 빡세다

 

6. 통계

}else if(command.equals("5")) {							

    //	통계 : 총인원. 평균, 최대값, 표준편차

    int sum = 0;
    for (int x = 0 ; x < count ; x++) {
        sum += scoreList[x];	
    }

    double average = (double)sum / count;				
    // 8-1. 둘중 하나라도 실수로 typecasting해서 실수 연산을 하자!


    int maxScore = 0;
    for(int x = 0 ; x < count ; x++) {

        if(scoreList[x] > maxScore) {		// 8-2. 8 > 3면 3를 8로 바꾸면되겠지
            maxScore = scoreList[x];
        }
    }

	
    // 8-4. 표준편자 : (점수 - 평균) 제곱의 합...
    
    int tempVarSum = 0;									
    for(int x = 0 ; x < count ; x++) {

        double deviation = scoreList[x] - average;
        // 8-5. average가 double이니까.... 집도 double이어야지!
        tempVarSum += deviation * deviation;
    }

    double std = Math.sqrt(tempVarSum / count);			
    // 8-6. tempVarSum / count --> 분산에 Math.sqrt하면 제곱근을 알려준다...ㅎ


    System.out.println("==== 점수 통계 ====");				
    System.out.println("총 인원 : " + count);
    System.out.println("최고 점수 : " + maxScore);
    System.out.println("표준 편차 : " + std);

 

7. 예외처리, close

}else {
	System.out.println("잘못된 입력입니다. 번호를 다시 입력하세요");	
// 4-1. 사용자가 아에 다른 숫자 or 문자를 입력할 경우	
//	break; --> ★★ break를 걸게되면? while문을 탈출하게돼서 프로그램을 종료한다.(다시해보기)
	}

	System.out.println("계속하시려면 enter를 입력하세요");
	scn.nextLine();		

// 4-2. 이게 정답인데, 만약에 else{}안에 들어가게되면
//	enter치면 menu로 다시 안돌아가고, '계속하시려면..' 이게 반복된다
//	scn.nextLine();에서 enter를 치게되면...?? 다시!!!!

	}
    System.out.println("프로그램이 종료됩니다. 이용해주셔서 감사합니다");		// 3-2.
    scn.close();		// 3. scn 종료

}