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 종료
}