[DigitalClock 클래스의 Class Diagram]


앞에서, Util.h 와 Util.c 파일에 대해서 설명드렸으니, 이번 시간에는, DigitalClock.h 와 DigitalClock.c 를 분석해 보겠습니다.


[DigitalClock.h]

#ifndef _DIGITAL_CLOCK_H
#define _DIGITAL_CLOCK_H

// ex) 12:24:36
enum{
	HOUR_LEFT, // left digit of hour  
	HOUR_RIGHT, // right digit of hour
	DELIMITER_BETWEEN_HOUR_AND_MINUTE, // colon between hour and minute 
	MINUTE_LEFT, // left digit of minute
	MINUTE_RIGHT, // right digit of minute
	DELIMITER_BETWEEN_MINUTE_AND_SECOND, // colon between minute and second
	SECOND_LEFT, // left digit of second
	SECOND_RIGHT // right digit of second
};

typedef struct _digitalClock{
	int year;
	int month;
	int dayOfMonth;
	int dayOfWeek; // Sunday (0), Monday (1), ...
	int hour;
	int minute;
	int second;
}DigitalClock;

#define ONE_SECOND 1000
#define INITIAL_X_POSITION_FOR_TIME 2
#define INITIAL_Y_POSITION_FOR_TIME 3
#define Y_OFFSET_FOR_TIME 8
#define INITIAL_X_POSITION_FOR_DATE 22
#define INITIAL_Y_POSITION_FOR_DATE 1

#define TRUE 1
#define FALSE 0

DigitalClock DigitalClock_GetTime();
void DigitalClock_Print(DigitalClock digitalClock);

#endif


1, 2, 39 라인

헤더파일 중복 삽입을 방지하기 위한 전처리기문입니다.


5 ~ 14 라인

시간을 출력하기 위해서, 시의 왼쪽 부분 (십의 자리), 시의 오른쪽 부분 (일의 자리), 시와 분 사이의 콜론, 분의 왼쪽 부분 (십의 자리), 분의 오른쪽 부분 (일의 자리), 분과 초 사이의 콜론, 초의 왼쪽 부분 (십의 자리), 초의 오른쪽 부분 (일의 자리) 의 순서를 정하고, 이 순서를 바탕으로 순서대로 일정 간격씩 커서를 이동하여 화면에 출력을 합니다.


16 ~ 24 라인

DigitalClock 이라는 구조체를 정의하는데, 멤버변수로 년도, 월, 일, 요일, 시, 분, 초를 갖고 있습니다. 단, 요일정보는 정수값으로, 일요일은 0 부터 시작합니다.


26 라인

Sleep 함수에서 향후 사용될 1 초를 나타내는 상수를 정의합니다.


27 ~ 28 라인

시간 출력시 사용될 시작 좌표의 위치 x, y 를 나타내는 상수를 정의합니다.


29 라인

시간 출력시 사용될 각 디지털 간의 간격을 상수로 정의합니다.


30 ~ 31 라인

날짜 출력시 사용될 시작 좌표의 위치 x, y 를 나타내는 상수를 정의합니다.


33 ~ 34 라인

참 (1), 거짓 (0) 을 나타내는 상수를 정의합니다.


36 ~ 37 라인

DigitalClock 과 관련된 함수들의 선언부입니다. 


[DigitalClock.c]

#include <stdio.h>
#include <time.h>
#include <windows.h>
#include "DigitalClock.h"
#include "Util.h"

#define DAY_OF_WEEK_SIZE 7

const static char* DAY_OF_WEEK[DAY_OF_WEEK_SIZE] = {
	" Sun ", " Mon ", " Tue ", " Wed ", " Thu ", " Fri ", " Sat "
};

#define PATTERNS_TO_PRINT_LENGTH 11
#define PATTERNS_TO_PRINT_ROW 5
#define PATTERNS_TO_PRINT_COL 3

const static char patternsToPrint[PATTERNS_TO_PRINT_LENGTH][PATTERNS_TO_PRINT_ROW][PATTERNS_TO_PRINT_COL] = {
	{ // 0
		{ 1, 1, 1 },
		{ 1, 0, 1 },
		{ 1, 0, 1 },
		{ 1, 0, 1 },
		{ 1, 1, 1 }
	},
	{ // 1
		{ 0, 1, 0 },
		{ 0, 1, 0 },
		{ 0, 1, 0 },
		{ 0, 1, 0 },
		{ 0, 1, 0 }
	},
	{ // 2
		{ 1, 1, 1 },
		{ 0, 0, 1 },
		{ 1, 1, 1 },
		{ 1, 0, 0 },
		{ 1, 1, 1 }
	},
	{ // 3
		{ 1, 1, 1 },
		{ 0, 0, 1 },
		{ 1, 1, 1 },
		{ 0, 0, 1 },
		{ 1, 1, 1 }
	},
	{ // 4
		{ 1, 0, 1 },
		{ 1, 0, 1 },
		{ 1, 1, 1 },
		{ 0, 0, 1 },
		{ 0, 0, 1 }
	},
	{ // 5
		{ 1, 1, 1 },
		{ 1, 0, 0 },
		{ 1, 1, 1 },
		{ 0, 0, 1 },
		{ 1, 1, 1 }
	},
	{ // 6
		{ 1, 0, 0 },
		{ 1, 0, 0 },
		{ 1, 1, 1 },
		{ 1, 0, 1 },
		{ 1, 1, 1 }
	},
	{ // 7
		{ 1, 1, 1 },
		{ 1, 0, 1 },
		{ 1, 0, 1 },
		{ 0, 0, 1 },
		{ 0, 0, 1 }
	},
	{ // 8
		{ 1, 1, 1 },
		{ 1, 0, 1 },
		{ 1, 1, 1 },
		{ 1, 0, 1 },
		{ 1, 1, 1 }
	},
	{ // 9
		{ 1, 1, 1 },
		{ 1, 0, 1 },
		{ 1, 1, 1 },
		{ 0, 0, 1 },
		{ 0, 0, 1 }
	},
	{ // :
		{ 0, 0, 0 },
		{ 0, 1, 0 },
		{ 0, 0, 0 },
		{ 0, 1, 0 },
		{ 0, 0, 0 }
	}
};

static void _DigitalClock_PrintDate(DigitalClock digitalClock);
static void _DigitalClock_PrintTime(DigitalClock digitalClock);

static void _PrintPattern(int pattern, int type);

DigitalClock DigitalClock_GetTime(){
	DigitalClock digitalClock = {0, };
	time_t now = time(NULL);
	struct tm* time = localtime(&now);
	digitalClock.year = time->tm_year + 1900;
	digitalClock.month = time->tm_mon + 1;
	digitalClock.dayOfMonth = time->tm_mday;
	digitalClock.dayOfWeek = time->tm_wday;
	digitalClock.hour = time->tm_hour;
	digitalClock.minute = time->tm_min;
	digitalClock.second = time->tm_sec;
	return digitalClock;
}

void DigitalClock_Print(DigitalClock digitalClock){
	_DigitalClock_PrintDate(digitalClock);
	_DigitalClock_PrintTime(digitalClock);
	Sleep(ONE_SECOND - 20);
}

static void _DigitalClock_PrintDate(DigitalClock digitalClock){
	CursorUtil_GotoXY(INITIAL_X_POSITION_FOR_DATE, INITIAL_Y_POSITION_FOR_DATE);
	printf("%d. %d. %d (%s)\n", digitalClock.year, digitalClock.month,
		digitalClock.dayOfMonth, DAY_OF_WEEK[digitalClock.dayOfWeek]);
}

static void _DigitalClock_PrintTime(DigitalClock digitalClock){
	_PrintPattern(digitalClock.hour / 10, HOUR_LEFT);
	_PrintPattern(digitalClock.hour % 10, HOUR_RIGHT);
	_PrintPattern(':', DELIMITER_BETWEEN_HOUR_AND_MINUTE);
	_PrintPattern(digitalClock.minute / 10, MINUTE_LEFT);
	_PrintPattern(digitalClock.minute % 10, MINUTE_RIGHT);
	_PrintPattern(':', DELIMITER_BETWEEN_MINUTE_AND_SECOND);
	_PrintPattern(digitalClock.second / 10, SECOND_LEFT);
	_PrintPattern(digitalClock.second % 10, SECOND_RIGHT);
}

static void _PrintPattern(int pattern, int type){
	int i = 0;
	int j = 0;
	int x = INITIAL_X_POSITION_FOR_TIME;
	int y = INITIAL_Y_POSITION_FOR_TIME;
	for (i = 0; i < type; i++){
		x += Y_OFFSET_FOR_TIME;
	}
	if (!(pattern >= 0 && pattern <= 9)){
		pattern = PATTERNS_TO_PRINT_LENGTH - 1;
	}
	CursorUtil_GotoXY(x, y++);
	for (i = 0; i < PATTERNS_TO_PRINT_ROW; i++){
		for (j = 0; j < PATTERNS_TO_PRINT_COL; j++){
			if (patternsToPrint[pattern][i][j]){
				printf("■");
			}
			else{
				printf("  ");
			}
		}
		CursorUtil_GotoXY(x, y++);
	}
	CursorUtil_GotoXY(0, y);
}


1 ~ 5 라인

DigitalClock.c 파일에서 필요한 함수나 변수를 위한 헤더파일 include 문입니다.


7 ~ 11 라인

요일을 문자열 상수 배열로 저장하여 전역 변수로 가지고 있습니다. const 를 사용한 이유는 상수화 하기 위함이고, static 을 붙인 이유는 현재 파일 내에서만 사용될 것이기 때문입니다.


13 ~ 95 라인

시간 출력시 사용될 디지털 패턴을 저장한 2 차원 배열입니다. 0 부터 9 까지의 숫자, 그리고 콜론을 나타내기 위해서 1 과 0 을 이용하여 표현하였습니다.


97 ~ 100 라인

DigitalClock.c 파일 내에서만 사용되는 내부 함수들의 선언부입니다.


102 라인

DigitalClock_GetTime 함수의 정의부입니다. 현재 시각을 가져와서 반환하는 역할을 합니다.


103 ~ 113 라인

현재 시각을 가져와서 DigitalClock 에 저장하고 이를 반환합니다.

(현재 시각 가져와서 출력하기 참고)

http://kkikkodev.tistory.com/25


116 라인

DigitalClock_Print 함수의 정의부입니다. 매개변수로 digitalClock 을 받아서 화면에 출력합니다.


117 라인

digitalClock 을 매개변수로 넘기면서 _DigitalClock_PrintDate 함수를 호출합니다.


118 라인

digitalClock 을 매개변수로 넘기면서 _DigitalClock_PrintTime 함수를 호출합니다.


119 라인

117, 118 라인에서 날짜, 시각을 출력했으니, 다음 1 초가 될 때까지 멈춥니다. 하지만, 정확히 1 초를 멈추게 되면 시간을 가져와서 가공해서 출력하는 처리시간이 걸리기 때문에, 엄밀히 따지면 이는 1 초를 넘기게 됩니다. 따라서 이러한 처리 시간이 누적되어 쌓여서, 초를 다시 가져왔을 때, 1 초가 아닌, 한 번에 2 초가 지나가버리는 경우가 발생하여, 실제로는 1 초보다 조금 작은 0.98 초를 Sleep 함수의 매개변수로 넘겨줍니다.


122 라인

_DigitalClock_PrintDate 함수의 정의부입니다. 매개변수로 digitalClock 을 받아서 날짜 부분만 화면에 출력합니다.


123 라인

날짜를 출력하기 위해서, 날짜 출력용 시작 위치로 커서를 이동시킵니다.


124 ~ 125 라인

digitalClock 의 멤버변수들을 이용해서 날짜 및 요일을 출력합니다.


129 라인

_PrintPattern 함수를 호출하면서, digitalClock 의 시의 왼쪽 부분의 값과 그 타입 (HOUR_LEFT) 를 넘겨줍니다.


130 라인

_PrintPattern 함수를 호출하면서, digitalClock 의 시의 오른쪽 부분의 값과 그 타입 (HOUR_RIGHT) 를 넘겨줍니다.


131 라인

_PrintPattern 함수를 호출하면서, 시와 분 사이에서 시와 분을 구분해 주기 위한 콜론 (:) 문자와 그 타입 (DELIMITER_BETWEEN_HOUR_AND_MINUTE) 를 넘겨줍니다.


132 라인

_PrintPattern 함수를 호출하면서, digitalClock 의 분의 왼쪽 부분의 값과 그 타입 (MINUTE_LEFT) 를 넘겨줍니다.


133 라인

_PrintPattern 함수를 호출하면서, digitalClock 의 분의 오른쪽 부분의 값과 그 타입 (MINUTE_RIGHT) 를 넘겨줍니다.


134 라인

_PrintPattern 함수를 호출하면서, 분과 초 사이에서 분과 초를 구분해 주기 위한 콜론 (:) 문자와 그 타입 (DELIMITER_BETWEEN_MINUTE_AND_SECOND) 를 넘겨줍니다.


135 라인

_PrintPattern 함수를 호출하면서, digitalClock 의 시의 왼쪽 부분의 값과 그 타입 (SECOND_LEFT) 를 넘겨줍니다.


136 라인

_PrintPattern 함수를 호출하면서, digitalClock 의 시의 오른쪽 부분의 값과 그 타입 (SECOND_RIGHT) 를 넘겨줍니다.


139 라인

_PrintPatter 함수의 정의부입니다. 매개변수로 pattern (출력될 모양의 패턴) 과 type (출력 위치를 구하기 위한 offset 을 계산하기 위한 변수) 를 받아서, 실제 디지털 패턴을 출력합니다.


142 ~ 146 라인

매개변수로 받은 타입에 따라서 출력될 좌표 위치를 결정합니다. 타입의 정수값이 클 수록 오른쪽에 출력됩니다.


147 ~ 149 라인

만약 매개변수로 받은 패턴이 콜론인 경우 (숫자가 아닌 경우), 패턴에는 10 을 저장합니다. 이는 미리 출력 패턴들이 0 과 1 로 저장되어 있는 patternToPrint 배열에서 콜론에 해당되는 패턴을 가져오기 위함입니다. (0 부터 9 까지는 숫자 패턴이 저장되어 있고, 10 번째는 콜론 패턴이 저장되어 있습니다.)


150 라인

142 ~ 146 라인에서 구한 패턴에 해당하는 출력 시작 위치로 커서를 이동시킵니다.


151 ~ 162 라인

patternToPrint 2 차원 배열에서 해당되는 패턴 위치 (숫자 or 콜론) 의 값이 0 이면 빈 칸을, 1 이면 ■ 를 출력하고, 다음 줄로 이동하면서 계속 패턴을 출력합니다.


by kkikkodev 2015. 4. 10. 22:59