TIL/Java

[SIST] Java_days11

야리니 2022. 3. 3. 19:48
728x90
반응형

1. 년도와 월을 입력받아서 달력 출력하기

2010년 5월 달력을 출력할 수 있도록 코딩을 한 뒤 반복문을 이용하여 원하는 달력을 출력할 수 있는 코드를 작성하기

 

달력을 그리기 위해서는 아래와 같은 정보가 필요하다.

 

1. 달력 그리기(생성)
   ㄱ. 해당 년도와 월의 1일은 무슨 요일? 
2010년 5월 1일은 토요일

       1) 총날짜수 구하기 : 1년1월1일 ~ 2010년 5월 1일까지 계산
       2) 총날짜수 % 7    :
0(일) 1(월) 2(화) 3(수) 4(목) 5(금) 6(토)
   ㄴ. 해당 년도와 월의 마지막 날짜는? 
2010년 5월은 31일(월)
       1) 28일 - 2월(평년)

       2) 29일 - 2월(윤년)
       3) 30일 - 4월, 6월, 9월, 11월
       4) 31일 - 1월, 3월, 5월, 7월, 8월, 10월, 12월

 


먼저 년도(year)와 월(month)의 값을 넣을 변수 선언한 다음 입력받은 매개변수가 2개가 아닐 때 매개변수가 필요하다는 메시지를 출력하는 코딩을 한다. Run As - Run Configurations 을 이용하여 매개변수 값을 넣을 수 있도록 args 배열 0번 째 인덱스와 1번 째 인덱스를 year과 month 변수에 넣도록 코딩을 한 후 Run As - Run Configurations 을 이용하여 매개변수 값으로 2010, 5를 입력하여 Apply 후 Run을 하여 출력이 잘되는지 확인할 수 있도록 System.out.printf로 확인을 하는 작업을 먼저 한다. 

 

main() 메서드 안에 코드 작성이 완료되었다면 이제 차근차근 4개의 메서드를 작성해보자!

1) 총날짜수 계산하기 - getTotalDays

2) 총날짜수 % 7 => 요일에 해당되는 정수값 구하기 - getDayOfWeek

3) 해당 월의 마지막 날짜 가져오기 - getLastDay

4) 달력 출력하기 - printCalender

 

1-1. 총날짜수 계산하기

private static int getTotalDays(int year, int month, int date) {
		int totalDays = 0;
		// 1) 구하고자하는 이전년도 (year(2010)-1 == 2009)의 총날짜수
		// 1년 365일 평년
		// 2년 365일 평년
		// 3년 365일 평년
		// 4년 366일 윤년

		// [더 간략하게 윤년구하기] ***
		totalDays = (year-1)*365 + (year-1)/4 - (year-1)/100 + (year-1)/400;
		// (year-1)*365 : 윤년 계산하는 거 없이 모든 년도를 365로 계산
		// (year-1)/4 : 몫이 우리가 구하고자하는 년도에 4의 배수가 몫만큼 있다.
		// (year-1)/100 : 만약에 100의 배수가 있으면 100의 배수가 있는 몫만큼 뺀다.
		// (year-1)/400 : 그리고 400의 배수가 있으면 400의 배수가 있는 몫만큼 더한다.
		
		// 2) 구하고자 하는 해당년도의 month-1까지 합하기
		//    ex) 2010년 5월 1일 이면 -> 31일(1월) + 28일(2월) + 31일(3월) + 30일(4월) + 1 /  ex) 3년 2월 13일 365(1년)+365(2년)+31(1월)+13(2월) = 총날짜수
		// 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
		// 31+28+31+30+31+30+31+31+30+31+30+31
		
		// 풀이3) [가장 간결하고 좋은코딩]*** 733893 잘나옴
		int[] m = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
		for (int i = 0; i < month - 1; i++) totalDays += m[i]; // 이전달까지 합구하는 것
		if(days06.Ex06_02.isLeapYear(year) && month >= 3) totalDays++; // 윤년일 때 일수 +1
		totalDays += date;
		
		
		/*
		// 풀이2) 733893
		for (int i = 1; i < month; i++) {
			switch (i) {
			case 2:
				totalDays += (days06.Ex06_02.isLeapYear(year)) ? 29 : 28;
				break;
			case 4: case 6: case 9: case 11:
				totalDays += 30;
				break;
			default:
				totalDays += 31;
				break;
			} // switch
		} // i for
		totalDays+=date;
		*/
		
		/*
		 // 풀이1) 전체 로직을 이해하는 코드
		switch (month) {  // 5월
	      case 1:         
	           totalDays +=  1;
	         break;
	      case 2:      
	         totalDays += 31 + 1;
	         break;
	      case 3:         // case 3 윤년 +1
	         totalDays += 31+28 + 1;
	         break;
	      case 4:         
	         totalDays += 31+28+31 +1;
	         break;
	      case 5:         
	         totalDays += 31+28+31+30 + 1;
	         break;
	      case 6:         
	         totalDays += 31+28+31+30+31 + 1;
	         break;
	      case 7:         
	         totalDays += 31+28+31+30+31+ 30+ 1;
	         break;
	      case 8:         
	         totalDays += 31+28+31+30+31+ 30+31 + 1;
	         break;
	      case 9:         
	         totalDays += 31+28+31+30+31+ 30+31+31 + 1;
	         break;
	      case 10:      
	         totalDays += 31+28+31+30+31+ 30+31+31+30+ 1;
	         break;
	      case 11:         
	         totalDays += 31+28+31+30+31+ 30+31+31+30+31+ 1;
	         break;
	      case 12:         
	         totalDays += 31+28+31+30+31+ 30+31+31+30+31+30+ 1;
	         break; 
	      }
	    
	      if( days06.Ex06_02.isLeapYear(year) &&  month >=3) totalDays++;
		 */
		
		return totalDays;
	} // getTotalDays

1-2. 총날짜수 % 7 => 요일에 해당되는 정수값 구하기

	private static int getDayOfWeek(int year, int month) {
		// 총날짜수: 733893
		int totalDays = getTotalDays(year, month, 1);
		// System.out.println("> 총날짜수 : " + totalDays);
		int dayOfWeek = totalDays % 7;
		return dayOfWeek;
	} // getDayOfWeek

1-3. 해당 월의 마지막 날짜 가져오기

	private static int getLastDay(int year, int month) {
		int lastDay;
		
		switch (month) {
		case 2:
			lastDay = (days06.Ex06_02.isLeapYear(year)) ? 29 : 28;
			break;
		case 4: case 6: case 9: case 11:
			lastDay = 30;
			break;
		default:
			lastDay = 31;
			break;
		} // switch
		
		return lastDay;
	} // getLastDay

1-4. 달력 출력하기(1-1 ~ 1-3의 메서드를 다 사용)

	private static void printCalender(int year, int month) {
		// 1) 총날짜수 계산하기 : 1년1월1일 ~ n년n월n일 -> 1년1월1일 ~ 2010년5월1일
		// 총날짜수 : 733893
		int totalDays = getTotalDays(year, month, 1); // 년월일을 주면 총날짜수 계산 : 1일로 시작되는 요일을 구하는 것이기 때문에 date는 1일
		// System.out.println("> 총날짜수 : " + totalDays);
		
		// 2) 총날짜수 % 7 => 요일에 해당되는 정수값(0~6)
		int dayOfWeek = getDayOfWeek(year, month);
		// System.out.println("> dayOfWeek=" + "일월화수목금토".charAt(dayOfWeek);
		
		// 3) 마지막 날짜 가져오기
		int lastDay = getLastDay(year, month);
		// System.out.println("> 마지막 날짜 : " + lastDay);
		
		// 4) 달력 출력
		System.out.printf("\t\t\t%d년 %d월\n", year, month);
		String week = "일월화수목금토";

		days08.Ex02.drawLine(60,'-');
		for (int i = 0; i < week.length(); i++) System.out.printf("\t%c", week.charAt(i));
		System.out.println();
		
		days08.Ex02.drawLine(60,'-');
		// 1일 ~ 31일
		for (int i = 0; i < dayOfWeek; i++) {  // 1일이 토요일에 맞춰서 출력하려면 i <= 6인데 마침 dayOfWeek 값이 6이라 바꿔도 됨 + 아래 코딩으로인해 = 연산자 빼기
			System.out.print("\t");
		}
		// ASCII 찍는 것과 동일
		for (int i = 1; i <= lastDay; i++) {
			System.out.print("\t" + i);
			if((dayOfWeek + i) % 7 == 0) System.out.println(); // 공백을 포함(dayOfWeek)시켜서 7로 나누었을 때 0으로 떨어지면 개행
		}
		System.out.println();
		days08.Ex02.drawLine(60,'-');
		
	} // printCalender

위와 같이 4개의 메서드를 다 선언했다면 main() 메서드 안에 아래와 같이 코딩을 하면 2010년 5월 달력이 출력된다.

printCalender(year, month); // 메서드 호출 부분

 

for문을 이용하면 원하는 년도와 월의 달력을 마음대로 출력할 수 있다.

// 메서드 호출 부분 - 2008년 1월 ~ 2010년 12월 달력 출력
for (int j = 2008; j <= 2010; j++) {
	for (int i = 1; i <= 12; i++) {
		printCalender(j, i);
	}
}


// 메서드 호출 부분 - 2010년 1월 ~ 12월 달력 출력				
for (int i = 1; i <= 12; i++) {
	printCalender(year, i); 
}

 

☞ 참고

여기서 사용된 isLeapYear()메서드와 drawLine()메서드는 다른 패키지에서 작성한 함수이다. days06과 days08 글을 보면 활용할 수 있을 것 같다.

 

2. 10진수를 2바이트 2진수로 변환하여 출력하기

import java.util.Arrays;
import java.util.Scanner;

public class Ex02 {

	public static void main(String[] args) {
		// [문제]
		// 정수(int) 입력받아서  ex) 10진수 10
		// 2바이트 2진수로 출력       2진수 00000000 00001010
		
		// Arrays.toString(배열명);  -> 확인용으로 배열 값을 출력해줌 > [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0]
		
		int n;
		Scanner sc = new Scanner(System.in);
		System.out.println("> 10진수 정수를 입력하세요?");
		n = sc.nextInt();
		
		int[] binary = new int[16];
		int idx = binary.length-1;
		
		int share = n; // 몫
		int rest; // 나머지
		
		while(share != 0) {
			share = n / 2; // 몫
			rest = n % 2; // 나머지  -> 가장 마지막 방부터 채워넣기
			binary[idx] = rest;
			idx--;
			n = share; // 몫을 다시 n으로 만들자
		} // while
		
		System.out.println(Arrays.toString(binary));
		// String.replaceAll()메서드
		System.out.println(Arrays.toString(binary).replaceAll(",\\s", "")); // 모든 , + 공백 => 빈문자열로 바꿔라
		
	} // main

} // class

 

2-1. 10진수를 16진수로 출력하기

import java.util.Arrays;
import java.util.Scanner;

public class Ex02_03 {

	public static void main(String[] args) {
	      int n ;
	      Scanner scanner = new Scanner(System.in);
	      System.out.print("> 10진수 정수 입력 ? ");  // 10
	      n = scanner.nextInt();

	      // 10진수 10을 -> 16진수로 출력   a
	      char [] hex = new char[4];
	      Arrays.fill(hex, '0');
	      
	      int share = n; // 몫 변수
	      int rest;      // 나머지 변수
	      
	      int idx = hex.length-1;
	      while( share != 0 ) {
	         share = n / 16;  // 5
	         rest  = n % 16;   // 0
	         
	         // 나머지(rest) 값을 문자로 변환해서 char[] hex에 저장하겠다.
	         // 1 + 48 -> '1'
	         // 10+87 -> 'a'
	         char value =  (char)(  rest += rest >= 10 ? 87 : 48 );
	         // System.out.printf("[%d]", rest); // [0][1][0][1]   1010
	         hex[idx--] = value;
	         n = share;
	      }
	      System.out.println("0x"+ Arrays.toString(hex).replaceAll(",\\s", ""));


	} // main

} // class

 

3. 돈을 최적의 화폐단위로 계산하여 출력하기

코드1)

import java.util.Scanner;

public class Ex03 {

	public static void main(String[] args) {
		int money;
		Scanner sc = new Scanner(System.in);
		
		System.out.println("> 머니를 입력하세요?"); // 125,760 엔터
		money = sc.nextInt();
		// 화폐단위 : 5만원, 1만원, 5천원, 1천원, 5백원, 1백원, 5십원, 1십원, 5원, 1원
		
		// 5만원 : 2장     25,760원
		// 1만원 : 2장      5,760원
		// 5천원 : 1장        760원
		// 5백원 : 1개        260원
		// 1백원 : 2개         60원
		// 5십원 : 1개         10원
		// 1십원 : 1개          0원
		
 		
		int share, rest;
		// 풀이2)
		int[] unit = {50000, 10000, 5000, 1000, 500, 100, 50, 10, 5, 1};
		String[] s_unit = {"5만원", "1만원", "5천원", "1천원", "5백원", "1백원", "5십원", "1십원", "5원", "1원"};
		// 반복문 사용 처리 : 5만원 ~ 1십원까지 10개이니까 for문 사용
		for (int i = 0; i < unit.length; i++) { // 범위는 수정할 수도 있으니 배열의 길이로 설정
			share = money / unit[i]; // 몫
			rest = money % unit[i];  // 나머지(잔액)
			System.out.printf("%s : %d개        %d\n", s_unit[i], share, rest);
			money = rest;
		} // i for end
		
		/*
		// 풀이1) 로직 파악하는 코딩
		share = money / 50000; // 몫
		rest = money % 50000;  // 나머지(잔액)
		System.out.printf("5만원 : %d개        %d\n", share, rest);
		
		money = rest;
		share = money / 10000; // 몫
		rest = money % 10000;  // 나머지(잔액)
		System.out.printf("1만원 : %d개        %d\n", share, rest);
		
		money = rest;
		share = money / 5000; // 몫
		rest = money % 5000;  // 나머지(잔액)
		System.out.printf("5천원 : %d개        %d\n", share, rest);
		
		money = rest;
		share = money / 1000; // 몫
		rest = money % 1000;  // 나머지(잔액)
		System.out.printf("1천원 : %d개        %d\n", share, rest);
		*/
		

	} // main

} // class

코드2) boolean sw를 사용하여 푼 코드

 

4. 배열

/*
 * 1. 배열의 정의? 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것
 *     동일한 자료형이 메모리 상에 연속적으로 놓이게 한 것
 * 
 * 2. 배열 선언 형식
 *    자료형[] 배열명; // 배열명을 변수, 참조변수(주소 값을 참조하기때문에)이라고 한다. 
 *    자료형 배열명[];
 *    
 * 3. 배열 생성 형식 

 *    new 연산자를 사용해서 힙(동적)영역에 실제 기억공간이 할당되고 그 시작 주소를 배열명이 참조한다.
 *    배열명 = new 자료형[배열크기];
 * 
 * 4. 예) []인덱스(index) 연산자를 설명 - 배열
 *    1000명의 국어점수를 저장할 변수를 선언
 *    int[] kors   -> 스택영역에 생성
 *    kors = "new int[1000]" -> new를 통해 힙(동적)영역에 있는 주소를 kors가 참조 
 * 
 * 5. 배열의 요소
 *  첨자값 == index(인덱스)
 *      0번째 요소      배열명[0]
 *      1번째 요소
 *      2번째 요소
 *      
 *      999번째 요소    배열명[999] == 배열명[배열명.length-1]
 * 
 * 6. 배열크기 == 배열명.length
 * 
 * 7. 배열의 길이 변경 p189   Ex04_02.java
 * 
 * 8. 배열의 초기화   p189
 * 
 * 9. 배열을 초기화하지 않으면 각 자료형의 기본값으로 초기화가 되어져 있다.
 *    ex) int[] m = new int[3];
 *    int의 기본값인 0으로 초기화 되어져 있다.
 *        m[0] = 0;
 *        m[1] = 0;
 *        m[2] = 0;
 */

 

4-1. 배열 선언 및 생성 / 배열 출력 / 배열을 사용할 때 가장 많이 발생하는 에러 메시지

 

4-2. 배열의 길이 변경(증가) 메서드 만들기 ***

public class Ex04_04 {

	public static void main(String[] args) {
		int[] m = new int[3];
		m[0] = 100;
		m[1] = 85;
		m[2] = 93;

		// 2개의 정수를 더 저장을 해야 된다.
		// m 배열의 크기(길이)를 2개 더 증가(변경)
		m = increaseArraySize(m, 5);

		m[3] = 80;

		disp(m);

	} // main

	public static int[] increaseArraySize(int[] m, int n) { // increaseArraySize 메서드로 인해 스택영역에 m 배열 생성, main()의 m과 같은 힙영역 주소를 참조

		int[] temp = new int[m.length + n];  // 원래 배열크기(main과 동일한 m이 참조하는 주소를 가짐) + n 만큼 증가한 것을 스택영역에 temp를 생성하여 저장 
		for (int i = 0; i < m.length; i++) { 
			temp[i] = m[i]; // temp에 m이 가지고 있는 요소의 값을 복사
		}
		
		// increaseArraySize = temp;
		// m = temp;
		
		return temp; // 스택영역에 생긴 temp가 참조하는 힙영역에 있는 m을 main에 리턴

	} // increaseArraySize

	private static void disp(int[] m) {
		for (int i = 0; i < m.length; i++) {
			System.out.printf("m[%d] = %d\n", i, m[i]);
		}
	} // disp

} // class

 

* 배열의 단점

  배열의 크기를 설정한 후에는 배열의 크기가 자동으로 변경되지 않는다.

  -> 컬렉션(Collection) 사용  -> 배울 예정

 

코드) 배열의 크기가 부족하다면 위에서 만든 increaseArraySize 메서드를 사용하여 배열 크기를 증가시키기

 

5. 한 반에 30명의 학생 이름, 국어, 영어, 수학, 총점, 평균, 등수 처리하기

-> 내일 이어서 마무리 할 예정

 

현재까지 작성된 코드)

package days11;

import java.util.Scanner;

/**
 * @author Yelin
 * @date 2022. 3. 3. - 오후 5:11:27
 * @subject
 * @content
 */
public class Ex07 {

	public static void main(String[] args) {
		// 한 반에 30명의 학생
		// 이름, 국어, 영어, 수학, 총점, 평균 등수를 처리하는 코딩
		Scanner sc = new Scanner(System.in);
		final int STUDENT_COUNT = 30;
		String[] names = new String[STUDENT_COUNT];
		int[] kors = new int[STUDENT_COUNT];
		int[] engs = new int[STUDENT_COUNT];
		int[] mats = new int[STUDENT_COUNT];
		int[] tots = new int[STUDENT_COUNT];
		double[] avgs = new double[STUDENT_COUNT];
		int[] ranks = new int[STUDENT_COUNT];
		
		// 입력받은 학생의 수 + 각 배열의 채워넣을 위치(인덱스)
		int count = 0;
		char con = 'y';
		
		do {
			System.out.printf("> [%d]번 이름 국어 영어 수학 입력하세요?", count+1);
			String name = sc.next();
			int kor = sc.nextInt();
			int eng = sc.nextInt();
			int mat = sc.nextInt();
			int tot = kor + eng + mat;
			double avg = (double)tot / 3;
			int rank = 1;  // 전체 학생의 점수를 받아야 등수를 매길 수 있으니 기초값 1로 설정
			
			names[count] = name;
			kors[count] = kor;
			engs[count] = eng;
			mats[count] = mat;
			tots[count] = tot;
			avgs[count] = avg;
			ranks[count] = rank;
			
			count++; // 입력받은 학생수 1증가 + 채워넣을 인덱스 값도 1증가
			
			System.out.println("> 계속 하시겠습니까?");
			con = sc.next().charAt(0);
		} while (Character.toUpperCase(con) == 'Y');
		
		System.out.println("> 입력받은 학생 수 : " + count + "명");
		
		// 입력받은 학생 정보 출력
		for (int i = 0; i < count; i++) {
			System.out.printf("%s\t%d\t%d\t%d\t%d\t%.2f\t%d\n", names[i], kors[i], engs[i], mats[i], tots[i], avgs[i], ranks[i]);
		}
		
		
	} // main

} // class
728x90
반응형