달력 프로그램 구성
사용자에게 출력하고 싶은 년도와 달을 입력하도록 하고, 달력을 출력해준다.
여러 개의 함수로 구성되어 있으며 긴 코드를 작성하는 연습을 할 수 있다.
여러 함수 설명 다음 맨 마지막에 총 코드를 합쳐 놓았다.
예시
만약 함수에대해 궁금하면 간단히 정리한 이 글을 참고하면 된다.
[문제]
year와 month를 전달 받아 해당 달을 출력하는 printMonth함수,
year와 month를 전달 받아 해당 월의 타이틀을 출력하는 printMonthTitle함수,
month를 전달 받아 해당 월을 출력하는 printMonthName함수,
year와 month를 전달 받아 요일과 일을 출력하는 printMonthBody함수,
year와 month를 전달 받아 시작하는 요일을 정수로 반환하는 getStartDay함수,
year와 month를 전달 받아 1800 혹은 1900년도부터 해당 월까지의 일을 더하여 반환하는 getTotalNumberOfDays함수,
year와 month를 전달 받아 해당월에 몇일이 있는지 반환하는 getNumberOfDaysInMonth함수,
year를 전달받아 윤년인지 확인하는 isLeapYear함수를 구현하세요.
(단, 1800년 1월 1일은 수요일)
main함수는 다음과 같다. (수정 시 0점처리)
int main(void){
int year, month;
scanf("%d", &year);
scanf("%d", &month);
printMonth(year, month);
return 0;
}
(단, 입력 받는 년도는 1900보다 큽니다.)
[풀이]
먼저 문제에 적힌대로 각 함수의 원형을 적어준다. 작성해야 할 함수가 많으면 일다 문제에 맞게 원형들을 적은 뒤에 생각하면 접근하기 편한 경우도 있다. 나는 이런 방식이 편해서 일단은 원형을 쭉 적어준 다음에 하나씩 접근하면서 함수를 작성하는 편이다.
//함수의 원형
//해당 월을 출력하는 함수
void printMonth(int year, int month);
//월과 년도(ex. April, 1998)를 출력하는 함수
void printMonthTitle(int year, int month);
//달의 영어 이름을 출력하는 함수
void printMonthName(int month);
//해당 월을 출력하는 함수
void printMonthBody(int year, int month);
//해당 월의 시작하는 날을 찾는 함수
int getStartDay(int year, int month);
//1800년 1월 1일 부터 며칠이 되는지 계산하는 함수
int getTotalNumberOfDays(int year, int month);
//해당 월에 며칠이 있는지 확인하는 함수
int getNumberOfDaysInMonth(int year, int month);
//윤년인지 확인하는 함수
int isLeapYear(int year);
우선 main함수를 보자.
int main(void){
int year, month;
scanf("%d", &year);
scanf("%d", &month);
printMonth(year, month);
return 0;
}
main함수(문제에 주어짐)에서 보면 작성해야 할 함수는 printMonth(year, month)함수이다.
이 함수는 해당 월을 출력하는 함수이다. 다음과 같이 달력의 title과 body로 함수 안의 내용을 나눌 수 있다.
void printMonth(int year, int month) {
// 달의 Title부분
printMonthTitle(year, month);
// 달의 Body부분
printMonthBody(year, month);
}
그러면 우리가 작성해야할 함수는 보다싶이 printMonthTitle함수와 printMonthBody함수이다.
우선 printMonthTitle 함수부터 생각해보자.
이 부분은 입력 받는 year와 month에 따라 다른 월과 년도를 출력하면 되는 부분이다. 그 외에 다른 부분은 같다.
예를 들면, April, 1998을 출력하는 부분이다.
//월과 년도를 출력하는 함수
void printMonthTitle(int year, int month) {
//월을 이름으로 바꿔주는 부분 ex. 4 -> April
printMonthName(month);
printf(" %d\n", year); // 년도 출력
printf("-----------------------------\n"); // 변하지 않는 부분 (title과 body를 나누는 부분)
printf(" Sun Mon Tue Wed Thu Fri Sat\n"); // 변하지 않는 부분 (요일)
}
여기서 또 작성해야 할 함수가 보이는데 printMonthName 함수이다.
이 함수는 달의 영어이름을 출력하는 함수이다. ex. 4 -> April
그렇다면 숫자에 따라 출력하는 이름이 달라지니 switch함수를 이용해서 작성하는 것이 편하다.
void printMonthName(int month) {
switch (month) {
case 1: printf("January"); break;
case 2: printf("February"); break;
case 3: printf("March"); break;
case 4: printf("April"); break;
case 5: printf("May"); break;
case 6: printf("June"); break;
case 7: printf("July"); break;
case 8: printf("August"); break;
case 9: printf("September"); break;
case 10: printf("October"); break;
case 11: printf("November"); break;
case 12: printf("December"); break;
}
}
여기까지해서 title부분의 함수 작성은 끝났다. 이제 body부분을 작성해보자.
printMonthBody 함수는 해당 월을 출력하는 함수이다. 해당 월의 시작하는 날로부터 요일에 맞게 해당 월의 끝까지 출력이 되는 것이다. 따라서 해당 월의 시작 날의 요일을 을 알아햐 하고 첫 날을 해당하는 요일에 맞게 출력하기 위해 공간을 채워야 한다.
void printMonthBody(int year, int month) {
// 해당 월의 시작하는 날
int startday = getStartDay(year, month);
// 1800년 1월 1일 부터 며칠이 되는지 계산
int numberofdaysinmonth = getNumberOfDaysInMonth(year, month);
// 첫 날 이전의 공간 채우기
for (int i = 0; i < startday; i++) printf(" "); // 공백 4칸
// 첫 날부터 마지막 날까지 출력
for (int i = 1; i <= numberofdaysinmonth; i++) {
printf("%4d", i); // 요일 별 공백은 4칸임
if ((i + startday) % 7 == 0) printf("\n"); // 요일의 한 줄을 채웠으면 그 다음줄로 넘어가야 함
}
}
그러면 여기서 또 작성해줘야 하는 함수가 getStartDay와 getNumberOfDaysInMonth가 있다.
getStartDay부터 봐보자. 이 함수는 해당 월의 시작하는 날의 요일을 찾는 함수이다. 1800년 1월 1일이 수요일인 것을 참고하면 다음과 같이 요일에 해당하는 숫자를 얻을 수 있다.
즉, 1800년 1월 1일로부터 총 며칠이 지났는지 알면 해당 월의 시작하는 날이 몇요일인지 알 수 있다.
int getStartDay(int year, int month) {
int startday1800 = 3; // 1800년 1월 1일은 수요일
int totalnumberofdays = getTotalNumberOfDays(year, month); // 1800년 1월 1일로부터 해당하는 년도와 월까지 날의 합
return (startday1800 + totalnumberofdays) % 7;
}
이 함수에서 또 필요한 것이 1800년 1월 1일 부터 며칠이 되는지 계산하는 getTotalNumberOfDays함수가 필요하다.
int getTotalNumberOfDays(int year, int month) {
int total = 0; // 총 합을 담아줄 변수 선언
// 해당하는 년도 이전해까지의 모든 날의 합 ex. 1998년이라면 1800년 1월 1일 부터 1997년 12월 31일까지
for (int i = 1800; i < year; i++) {
if (isLeapYear(i)) total += 366; // 윤년일 경우 366일
else total += 365; // 평년일 경우 365일
}
// 해당하는 달의 이전까지의 모든 날의 합 ex. 4월이라면 1월 1일 부터 3월 31일까지
for (int i = 1; i < month; i++) total = total + getNumberOfDaysInMonth(year, i);
return total; // 1800년 1월 1일 부터 며칠이 되는지 계산한 값을 반환
}
그러면 또 작성해줘야 하는 함수가 보이는데 바로 윤년인지 확인해주는 함수이다.
isLeapYear는 윤년인지 확인하는 함수인데 윤년은 다음과 같다.
4로 나누어 떨어지는 년도는 윤년,
4로 나누어 떨어지더라도 100으로 나누어 떨어지면 평년,
4로 나누어 떨어지고, 100으로 나누어 떨어지나, 400으로 나누어 떨어지면 윤년이다.
즉, 윤년인 경우만 정리하면 다음과 같이 쓸 수 있다.
((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
이 조건식을 이용하여 isLeapYear 함수를 다음과 같이 나타낼 수 있다. 윤년이면 1을 평년이면 0을 반환하게 했는데, 이는 윤년이 평년보다 하루가 많은 것과 1은 참을 뜻하고 0은 거짓을 뜻하는 것을 참고했다.
int isLeapYear(int year) {
// 윤년일 경우 1을 반환
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) return 1;
// 평년일 경우 0을 반환
else return 0;
}
이제 또 작성해야 할 함수를 보면 getNumberOfDaysInMonth 함수가 남았다.
getNumberOfDaysInMonth 함수는 해당 월에 며칠이 있는지 확인하는 함수이다.
int getNumberOfDaysInMonth(int year, int month) {
// 1, 3, 5, 7, 8, 10, 12 월의 경우 31일까지 있다.
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) return 31;
// 4, 6, 9, 11 월의 경우 30일까지 있다.
if (month == 4 || month == 6 || month == 9 || month == 11) return 30;
// 2월인 경우 윤년이면 29일, 평년이면 28일까지 있다.
if (month == 2) {
if (isLeapYear(year) == 1) return 29;
else return 28;
}
}
여기까지해서 달력 프로그램에 사용될 함수들을 적어봤다.
정리할겸 printMonthBody 함수를 다시 보면 이해가 완벽히 될 것이다.
void printMonthBody(int year, int month) {
// 해당 월의 시작하는 날
int startday = getStartDay(year, month);
// 1800년 1월 1일 부터 며칠이 되는지 계산
int numberofdaysinmonth = getNumberOfDaysInMonth(year, month);
// 첫 날 이전의 공간 채우기
for (int i = 0; i < startday; i++) printf(" "); // 공백 4칸
// 첫 날부터 마지막 날까지 출력
for (int i = 1; i <= numberofdaysinmonth; i++) {
printf("%4d", i); // 요일 별 공백은 4칸임
if ((i + startday) % 7 == 0) printf("\n"); // 요일의 한 줄을 채웠으면 그 다음줄로 넘어가야 함
}
}
코드를 총 합치면 다음과 같다.
#include<stdio.h>
//함수의 원형
void printMonth(int year, int month);
void printMonthTitle(int year, int month);
void printMonthName(int month);
void printMonthBody(int year, int month);
int getStartDay(int year, int month);
int getTotalNumberOfDays(int year, int month);
int getNumberOfDaysInMonth(int year, int month);
int isLeapYear(int year);
//year와 month를 전달 받아 해당 월을 출력 -> title, body
void printMonth(int year, int month) {
printMonthTitle(year, month);
printMonthBody(year, month);
}
//월과 년도를 출력
void printMonthTitle(int year, int month) {
printMonthName(month);
printf(" %d\n", year);
printf("-----------------------------\n");
printf(" Sun Mon Tue Wed Thu Fri Sat\n");
}
//month를 전달 받아 해당 달의 영어 이름을 출력
void printMonthName(int month) {
switch (month) {
case 1: printf("January"); break;
case 2: printf("February"); break;
case 3: printf("March"); break;
case 4: printf("April"); break;
case 5: printf("May"); break;
case 6: printf("June"); break;
case 7: printf("July"); break;
case 8: printf("August"); break;
case 9: printf("September"); break;
case 10: printf("October"); break;
case 11: printf("November"); break;
case 12: printf("December"); break;
}
}
//year와 month를 전달 받아 요일과 일을 출력
void printMonthBody(int year, int month) {
int startday = getStartDay(year, month);
int numberofdaysinmonth = getNumberOfDaysInMonth(year, month);
for (int i = 0; i < startday; i++) printf(" ");
for (int i = 1; i <= numberofdaysinmonth; i++) {
printf("%4d", i);
if ((i + startday) % 7 == 0) printf("\n");
}
}
// 해당 월의 시작하는 날이 몇 요일인지 찾는 함수
int getStartDay(int year, int month) {
int startday1800 = 3;
int totalnumberofdays = getTotalNumberOfDays(year, month);
return (startday1800 + totalnumberofdays) % 7;
}
// 1800년 1월 1일 부터 며칠이 되는지 계산
int getTotalNumberOfDays(int year, int month) {
int total = 0;
for (int i = 1800; i < year; i++) {
if (isLeapYear(i)) total += 366;
else total += 365;
}
for (int i = 1; i < month; i++) total = total + getNumberOfDaysInMonth(year, i);
return total;
}
//year와 month를 전달 받아 해당월에 몇일이 있는지
int getNumberOfDaysInMonth(int year, int month) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) return 31;
if (month == 4 || month == 6 || month == 9 || month == 11) return 30;
if (month == 2) {
if (isLeapYear(year) == 1) return 29;
else return 28;
}
}
//year를 전달받아 윤년인지 확인
int isLeapYear(int year) {
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) return 1;
else return 0;
}
int main(void) {
int year, month;
// 년도 입력
printf("year : ");
scanf("%d", &year);
// 월 입력
printf("month : ");
scanf("%d", &month);
printMonth(year, month);
return 0;
}
'C언어_VisualStudio_실습' 카테고리의 다른 글
369게임 박수치기; while문, if문 (0) | 2021.06.11 |
---|---|
주문한 카페 메뉴 총 금액 출력하기; while문, switch문 (0) | 2021.06.10 |
[C언어] 조건문 예제: 절대값 출력, 학점 프로그램 (0) | 2021.05.31 |
[C언어] 사용자 정의 함수의 예제 : 큰 값 출력 함수, 구구단 출력 함수, 양수 입력 받는 함수, 아스키코드 출력 함수 (0) | 2021.05.27 |
[C 언어] 표준함수 사용해보기 : 수학함수, 랜덤함수, 외부 프로그램 실행 (0) | 2021.05.25 |