프로그램 예제 풀기
1. 학생 점수 프로그램
2. 차량 관리 프로그램
# 학생 점수 프로그램
Q. 학생수와 각 학생들의 점수를 입력 받아 최고 점수 및 평균점수를 구하는 프로그램을 동작되는 예제를 보고 완성하시오. <배열문제>
<background>
- 학생 수를 입력받기 전까지 배열의 길이를 정할 수 없으므로 runtime때 지정하도록 함.
배열의 레퍼런스변수(참조변수) 선언.
- 4. 분석 에서는 최댓값과 평균값 구하기.
학생 점수 프로그램 코드 Q18.java
public class Q18 {
static Scanner scanner = new Scanner(System.in); //왜 Scanner 객체 선언할때 static을 붙여야하지?
public static void main(String[] args) {
boolean run = true; //반복문 실행할때 쓰일 boolean 변수
int studentNum=0; //학생 수
int[] scores = null; //배열의 레퍼런스변수 선언 (1)
while(run) {
System.out.println("-------------------------------------------");
System.out.println("1.학생 수 | 2.점수입력 | 3.점수리스트 | 4.분석 | 5.종료");
System.out.println("-------------------------------------------");
System.out.println("선택> ");
int selectNo = scanner.nextInt();
if (selectNo == 1) {
System.out.println("학생수> ");
studentNum = scanner.nextInt(); //동적할당은 runtime(프로그램 동작 중에) 때 할당 가능.
scores = new int[studentNum]; //입력된 학생 수만큼의 integer 배열 길이 지정.
//java배열은 만들고나면 수정이 불가능하지만, runtime때는 수정 가능.
}
//점수입력
else if (selectNo ==2 ) {
for (int i=0;i<scores.length;i++) {
System.out.println("scores["+i+"]> ");
scores[i]= scanner.nextInt(); //배열 인덱스 별 점수 넣어주기.
}
}
//점수리스트
else if (selectNo ==3) {
// for (int i:scores) : for each문은 배열반복문일때 사용
for (int i=0;i<scores.length;i++) { //for은 사실상 메서드이기때문에 결국 메서드 오버로딩.
System.out.println("scores["+i+"]: "+scores[i]); //배열에 들어있는 점수를 배열인덱스와 함께 출력. ex)scores[1]: 88
}
}
//분석
else if (selectNo ==4) {
int max=0;
//처음에 넣을때부터 max를 비교하면서 정해놓고싶으면 기준값을 정해. "최소/최대값의 초깃값 규칙" >첫번째 데이터를 기준값으로.
//But, 따로 메서드에서 최댓값을 구하는 것이기 때문에, 가장 작은 값의 변수로 초기화하고, 배열의 값들과 비교하여 최댓값 구함.
int sum=0;
double avg = 0;
for(int i=0;i<scores.length;i++) {
max = (max<scores[i])? scores[i] : max; //삼항연산자 (1)
sum += scores[i]; //평균 구하기 위해 모든 점수 합치는 변수 sum
}
avg = (double) sum / studentNum; //sum을 학생수로 나누면 평균값. (double)로 형전환 해줘야 값이 소수점까지 나옴.
System.out.println("최고 점수: "+max);
System.out.println("평균 점수: "+avg);
}
else if (selectNo ==5) { //run=false되면 while문 종료.
run = false;
}
}
}
}
(1) 참조변수 생성
int[] scores = null;
scores = new int[studentNum];
항상 한 줄로 배열이 생성됐는데 이걸 두 줄로 나눠놓으니 헷갈리기 시작해서 다시 알아보았다.
우선, 객체의 참조변수를 선언할 때를 봐보면 먼저, 메모리를 생성하고 그값(참조값)을 변수에 넣어 참조변수를 생성하는 것이다.
위 코드처럼 배열이 아닌 그냥 참조변수 생성을 나눠서 보면Q18 q = null; //메모리가 생성되기 전, null로 초기화.q = new Q18(); //연산자 new와 생성자를 이용해서 특정 메모리 생성. 그 메모리의 (주소 매핑하는)참조값이 q에 할당됨.이처럼 int[] scores 도 똑같다. 1. integer형인 배열의 변수가 null로 초기화되었고,2. studentNum 길이의 메모리를 생성하여 변수에 할당해줬으므로 레퍼런스변수(참조변수)가 된것이다.
**참조값 != 주소값C++ 언어에서는 new를 이용해서 메모리를 생성하면 주소 그 자체를 직접 넘겨주어 포인터변수를 이용해서 주소를 사용자가 직접 관리하는 반면,Java 에서는 메모리 주소를 바로 주지 않고, 인스턴스의 메모리 주소 대신 참조값을 할당해주는 것이다.
(2) 삼항연산자 (조건)? (참값):(거짓값);
ifelse문 기능과 동일하여, 값을 찾을 때 쓰이는 연산자.
조건이 맞으면 왼쪽값(참값)을 변수에 넣고, 거짓이면, 오른쪽 값(거짓값)을 변수에 저장한다.
# 차량 관리 프로그램
Q. 차량 관리 프로그램을 만드시오.
예시
#### 자동차 정보 프로그램 ####
1. 자동차 정보 입력
2. 저장된 목록 보기
3. 각 자동차의 구매 가격 조회
4. 옵션이 있는 자동차 정보 조회
5. 빠른 자동차와 느린 자동차의 속도차 조회
6. 프로그램 이용 종료
##########################
입력 :
<background>
max와 min 객체를 어디에 선언해야될지 생각하기.
차량 관리 프로그램 코드 Car.java
class save_data { //private으로 선언하여 접근할때는 get메서드 이용해서 접근 가능!
private String carName; //자동차이름
private int enginPrice; //엔진가격
private int tirePrice; //타이어가격
private String option; //옵션
private String optionName; //옵션이름
private int maxSpeed; //최고속도
private int price; //총가격(엔진+타이어가격)
/*(1)
public int max;
public int min=10000;
*/
//매개변수 있는 생성자. 변수 값 설정 가능.
public save_data (String carName, int enginPrice, int tirePrice, String option, String optionName, int maxSpeed, int price) {
this.carName = carName;
this.enginPrice = enginPrice;
this.tirePrice = tirePrice;
this.option = option;
this.optionName = optionName;
this.maxSpeed = maxSpeed;
this.price = price;
}
//프로그래밍이 돌아가면서 값을 갱신하게 되면 set이 필요하지만 지금은 갱신할 일 없으니까 set메서드는 안써도되.
public String getName() { return carName; }
public int getenginPrice() {return enginPrice; }
public int gettirePrice() { return tirePrice; }
public String getOption() { return option; }
public String getoptionName() { return optionName; }
public int getmaxSpeed() {return maxSpeed; }
public int getPrice() {return price; }
/* (2)
public void setName(String carName) { this.carName = carName; }
public void setenginPrice(int enginPrice) {this.enginPrice = enginPrice; }
public void settirePrice(int tirePrice) { this.tirePrice=tirePrice; }
public void setOption(String option) {this.option= option; }
public void setoptionName(String optionName) {this.optionName = optionName; }
public void setmaxSpeed(int maxSpeed) { this.maxSpeed= maxSpeed; }
public void setPrice(int price) {this.price = price; }
*/
}
public class Car {
private static save_data[] carArray = new save_data[100]; //자동차정보 객체들을 한 배열인덱스에 저장할 예정.
private static Scanner scanner= new Scanner(System.in); //static은 메서드가 끝나도 계속 유지됨.
private static int car_num=0; //자동차가 기록돼있는 것까지만 출력하려고 자동차갯수 입력되는 변수.
private static int max_s=-1; //밖에다 선언하면 객체랑 객체끼리 부딪쳐. ??? (1)
private static int min_s=1000; //최댓값, 최소값의 초깃값은 각각 가장 작은 값과 큰 값을 저장해야함.
//(3) main안에 있는 프로그램 목록 출력 코드와 ifelse를 따로 메서드로 만드는 것도 괜찮음.
public static void main(String[] args) {
boolean run = true; //true일때까지 while문 반복
while (run) {
System.out.println("#### 자동차 정보 프로그램 ####");
System.out.println("1. 자동차 정보 입력 \n2. 저장된 목록 보기\n3. 각 자동차의 구매 가격 조회\n4. 옵션이 있는 자동차 정보 조회\n5. 빠른 자동차와 느린 자동차의 속도차 조회\n6.프로그램 이용 종료");
System.out.println("########################");
System.out.println("입력: ");
int selectNo = scanner.nextInt();
if(selectNo == 1) { createCar();} //1. 자동차 생성
else if(selectNo == 2) { carList(); } //2. 자동차 목록 보기
else if(selectNo ==3) { carPrice(); } //3. 자동차 구매가격 조회
else if(selectNo ==4) { optionCarList(); } //4. 옵션있는 자동차 조회
else if(selectNo ==5) { maxminSpeeddiff(); } //5.속도의 최댓값최소값 구하기
else if(selectNo ==6) { //6. run=false; 반복문 종료
System.out.println("프로그램 종료");
run = false;
}
}
}
//자동차 생성하기
static public void createCar() {
scanner.nextLine(); //(4)
System.out.println("----------------");
System.out.println("1. 자동차 정보 입력");
System.out.println("----------------");
System.out.print("이름: "); String carName = scanner.nextLine(); //각각 자동차 정보를 객체에 저장.
//private이어서 접근못하는 carName에 어떻게 여기선 접근해서 설정하지?
System.out.print("엔진 가격: "); int enginPrice = scanner.nextInt();
scanner.nextLine();
System.out.print("타이어 가격: "); int tirePrice = scanner.nextInt();
scanner.nextLine();
System.out.println("옵션유무 입력 (있음/없음): "); String option = scanner.nextLine();
String optionName;
if( option.equals("없음")) //옵션유무가 없으면
optionName = "없음"; //옵션이름에도 "없음"을 저장.
else //옵션유무가 있으면
System.out.print("옵션 이름: "); optionName = scanner.nextLine(); //옵션이름 입력.
System.out.print("최고속도: "); int maxSpeed = scanner.nextInt();
scanner.nextLine();
max_s= (maxSpeed>max_s) ? maxSpeed : max_s; //입력한 최고속도가 최대값인지 그때그때 바로 비교해서 max_s에 저장.
min_s= (maxSpeed<min_s) ? maxSpeed : min_s; //입력한 최고속도가 최솟값인지 그때그때 바로 비교해서 min_s에 저장.
int price = enginPrice+tirePrice; //가격은 엔진+타이어 가격.
System.out.println("구매 가격: "+price);
save_data newCar = new save_data(carName, enginPrice, tirePrice, option, optionName,maxSpeed,price);
//자동차 정보를 다 객체에 입력했으면, 그것을 생성자를 이용해서 초기화 시켜준후 한 객체에 입력. newCar는 한 자동차의 정보가 모두 담겨있는 객체.
//(5)
carArray[car_num] = newCar; //처음엔 0이니까 배열 인덱스 0부터 차곡차곡 자동차정보가 저장됨
car_num+=1; //다음 인덱스에 다른 자동차정보가 저장될 것을 생각하여 +1 해놓기.
System.out.println("자동차 정보가 등록되었습니다.");
}
//자동차목록보기
static public void carList() {
System.out.println("----------------");
System.out.println("2. 자동차 목록 보기");
System.out.println("----------------");
if (car_num<=0) { //car_num을 이용해서 0이하이면 등록된 차가 없으므로 반복문실행하지 않아도 되니까 먼저 확인하기.
System.out.println("등록된 차량이 없습니다.");
return; //메서드 종료.
}
for (int i=0;i<carArray.length;i++) {
save_data account = carArray[i]; //배열의 한 인덱스 정보를 객체에 저장.
if (account != null) { //객체가 비어있지 않으면 자동차 정보를 출력하는데, get()메서드로 각 객체에 접근하여 출력.
System.out.println("이름: "+account.getName());
System.out.println("엔진 가격: "+account.getenginPrice());
System.out.print("타이어 가격: "+account.gettirePrice());
System.out.println("옵션: "+account.getOption());
System.out.println("옵션 이름 : "+account.getoptionName());
System.out.println("최고속도: "+account.getmaxSpeed());
System.out.println("구매 가격: "+account.getPrice());
}
}
}
//구매가격 조회
static public void carPrice() {
System.out.println("----------------------");
System.out.println("3. 각 자동차의 구매가격 조회");
System.out.println("----------------------");
if (car_num<=0) { //마찬가지로 등록된 자동차가 없으면
System.out.println("등록 된 차량이 없습니다.");
return; //메서드 종료.
}
for (int i=0;i<carArray.length;i++) {
save_data car_data = carArray[i]; //각 배열의 인덱스 정보를 객체에 저장.
if ( car_data != null) //객체가 비어있지 않으면 (자동차 정보가 있으면)
System.out.println(car_data.getName()+": "+car_data.getPrice()); //자동차 이름과 가격 출력.
}
}
//옵션이 있는 자동차 조회
private static void optionCarList() {
System.out.println("----------------------");
System.out.println("4. 옵션이 있는 자동차 조회");
System.out.println("----------------------");
if (car_num<=0) { //차량 개수가 0개 이하이면
System.out.println("등록 된 차량이 없습니다.");
return;
}
for (int i=0;i<carArray.length;i++) {
save_data car_data = carArray[i];
if ( car_data.getOption() =="있음") { //option이 있으면 자동차 정보 조회.
System.out.println("이름: "+car_data.getName());
System.out.println("엔진 가격: "+car_data.getenginPrice());
System.out.print("타이어 가격: "+car_data.gettirePrice());
System.out.println("옵션: "+car_data.getOption());
System.out.println("옵션 이름 : "+car_data.getoptionName());
System.out.println("최고속도: "+car_data.getmaxSpeed());
System.out.println("구매 가격: "+car_data.getPrice());
}
}
}
//빠른 자동차와 느린 자동차의 속도차 조회
private static void maxminSpeeddiff() {
if(car_num <2) { //1대만 등록되면 빠른/느린 자동차 비교가 안되니까 2대이상은 있어야해.
System.out.println("차량이 2대이상 등록되지 않았습니다.");
return;
}
System.out.println("-------------------------------");
System.out.println("5. 빠른 자동차와 느린 자동차의 속도차 조회");
System.out.println("-------------------------------");
System.out.println("빠른 자동차와 느린 자동차의 속도차: "+(max_s-min_s)); //두 변수의 차이.
}
}
중요하면서 헷갈린 부분은 번호 표시!
(1) max_s와 min_s를 어디 메서드 안에 선언해주는게 맞을까?
사실 처음에 save_data 메서드 안에 선언했었다. 그런데
// public int max_s;
// public int min=10000;
(2) Q. set()메서드를 선언해주지 않아도 되는 이유는?
프로그래밍이 돌아갈때 객체 값을 갱신하게 되면 set() 메서드가 필요하지만 갱신할 필요 없으니까 set()메서드는 필요없어서 선언해주지 않아도 된다.
//자동차 등록할때 객체들 값을 지정할때 생성자()로 접근하여 지정하니까!
그럼 set을 쓸땐 어떤 경우지?
(3) 선생님은 main을 세줄로 만들고 따로
메뉴 보여주는 여러 줄의 print문을 print_UI() 메서드로,
메뉴선택하는 if-else문을 boolean 타입 mode()메서드로 만들어주었다.
+ifelse대신 switch-case문으로 했고,
print_UI()와 mode()
static public void print_UI() {
System.out.println();
System.out.println("########### 자동차 정보 프로그램 ###########");
System.out.println(" 1. 자동차 정보 입력");
System.out.println(" 2. 저장된 목록 보기");
System.out.println(" 3. 각 자동차의 구매 가격 조회");
System.out.println(" 4. 옵션이 있는 자동차 정보 조회");
System.out.println(" 5. 빠른 자동차와 느린 자동차의 속도 차 조회");
System.out.println(" 6. 프로그램 이용 종료");
System.out.println("############################################");
System.out.print("입력:");
}
static public boolean mode() {
print_UI();
int in=scanner.nextInt();
switch (in) {
case 1:
enter();
return true;
case 2:
view();
return true;
case 3:
search_P();
return true;
case 4:
search_Op();
return true;
case 5:
speed_C();
return true;
case 6:
System.out.println("프로그램이 종료됩니다.");
return false;
default:
System.out.println("잘못 입력 하셧습니다.\n 다시 입력해주세요.");
return true;
}
}
(4)
int price = scanner.nextInt(); //1
scanner.nextLine(); //2String name = scanner.nextLine(); //3
Q. 중간에 scanner.nextLine(); 을 써주는 이유?
A. 첫번째 int만 입력받고 그다음 3번째 라인을 건너띄는 경우가 발생하는데, 이는 nextInt()에서 Enter를 칠때 발생하는 '개행문자'를 처리하지 않고 버퍼에 남기기 때문에 개행문자를 중간에 넣어줘야한다. 그 방법 중 하나로,1번과 2번 사이에 scanner.nextLint();을 넣어주는 것이다.
+하나 더 알게 된 것이 String 변수에 scanner입력을 받을 때 next()를 써왔는데 nextLine()이 더 정확하다는 것이다.
이유는,
next() : 문자 또는 문자열을 공백을 기준으로 한단어 또는 한문자씩 입력 받는다.
nextLine() : 문자 또는 문장 한 라인 전체를 입력받는다.
ex) Hello java 를 입력을 하게 되면, next()는 Hello를, nextLine()은 Hello java를 변수에 넣어주게 된다.
(5) 사실 처음 썼던 코드는 저 두줄이 아니라, 반복문이었다.
for (int i=0; i<carArray.length;i++) {
if (carArray[i] == null) {
carArray[i] = newCar;
System.out.println("자동차 정보가 등록되었습니다.");
break;
}
}
이렇게 해도 작동은 하지만, 등록된 자동차의 갯수 변수(car_num)를 하나 선언해서, 하나씩 자동차가 하나씩 추가될 때마다 그 변수를 1씩 올려주어(car_num+=1;) 배열에 자동차정보를 담는 코드로 쓰는게 훨씬 코드줄이 줄어든다는 것을 알게됐음!
'언어 > Java' 카테고리의 다른 글
기초 #5. 추상클래스 (ex. 계산기 프로그램) (0) | 2020.08.22 |
---|---|
기초 #4. 상속과 다형성 (0) | 2020.08.21 |
기초실습 #1. 계좌이체 프로그램 예제 (0) | 2020.08.14 |
기초 #3 변수 (0) | 2019.06.28 |
기초 #2 이클립스 실행하기 (0) | 2019.06.28 |