数字时钟【转载】
这是以相关WIN API封装成控制台功能增强版函数库为基础,编写出的一个简单的时钟。
此程序的目标是展示一点美感,比如结果上的、设计上的、代码格式上的。俗话说功夫在诗外,以美学为导向,为道,算是一种探索。
不同领域中的不同的人对美的理解不一样,而且一般在多数时候无法言表,只能综合感受。在软件工程的表示层中美的共性定义有:简洁、精确、一致等等关键字。
开始做了,首先以需求为导向,采用传统的面向过程设计,概括出这个程序的主体流程:先取得系统当前的细分时间,再通过光标定位、色彩控制和处理器延时,循环执行画出数字。
因为想表现得更贴近在问题域上编程之意、体现简洁思想,所以统一地,提取了"数字时钟" 这个主题中的词汇,来概括整个程序的抽象层次,具体到命名及规范。
然后在上面问题上进行合适地拆分。
修饰细节后,最后表达出一个整体。
系统中有些不易变的数据定义为宏,变成一套问题边界的参数,区分易变的部分,便于以后集中的修改控制,这里把它放在所有代码最上层,是为表示为所有过程共享,为工程级。
如何画出一个数字?为了展示出C的底层知识的魅力,这个小程序的核心数据结构-表示数字方块形状的抽象表格(5x3的地图),用16位二进制位编码来映射表示,被压缩转换为十六进制存储。对此一维数组的操作算法,是个简单的位与运算的应用之一即判断指定位是否为1。
这里数据驱动编程的运用,是这一模式的概念的狭义定义:把if、switch这类结构化的等值判断的且较长的逻辑语句转换成数据表示,创建表结构,再设计出访问算法,隔离开变与不变的部分。
转载地址:
http://blog.csdn.net/blue123abc/article/details/8241749
代码如下:
- /* * * * * * * * * * * * * * * * * * * * * * * *
- // Project: DigitalClock(数字时钟)
- // Author: ProBlue
- // Notes: Some functions about Win32 Console Control.
- // Date: 2012.11.20 00:10
- * * * * * * * * * * * * * * * * * * * * * * * */
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include "pcc32.h"
- #define APP_TITLE "数字时钟"
- #define APP_HEIGHT 7
- #define APP_WIDTH 38
- #define DIS_BASE_X 2
- #define DIS_BASE_Y 0
- #define TEXT_COLOR LIGHT_GREEN
- #define GotoMap(x,y) gotoTextPos((x)*2,(y))
- #define PRINT_BOX(s) printf("%2s",s)
- #define GET_BIT(v,b) ((v)>>(b)&1)
- PCCOLOR COLORS[] = {BLACK, LIGHT_GREEN};
- char LIGHT[][3] = {" ", "■"};
- // 各数字的形状方块的码表
- static uint16 digitTable[10] =
- { 0x7B6F, 0x2492, 0x73E7, 0x79E7, 0x49ED, 0x79CF, 0x7BCF, 0x4927, 0x7BEF, 0x79EF };
- void drawDigit(int digit, int hx);
- void drawSeptor(int color, int hx);
- void initTime(int* hou, int* min, int* sec);
- void delayMS(float secs);
- int main()
- {
- int h,m,s;
- int sepcx = 0;
- fixConsoleSize(APP_WIDTH*2, APP_HEIGHT);
- setConsoleTitle(APP_TITLE);
- setCursorVisible(0);
- initTime(&h, &m, &s);
- while (1)
- {
- delayMS(0.97);
- drawSeptor(COLORS[sepcx = !sepcx], DIS_BASE_X + 22);
- drawSeptor(TEXT_COLOR, DIS_BASE_X + 10);
- drawDigit(h / 10, DIS_BASE_X + 0);
- drawDigit(h % 10, DIS_BASE_X + 4);
- drawDigit(m / 10, DIS_BASE_X + 12);
- drawDigit(m % 10, DIS_BASE_X + 16);
- drawDigit(s / 10, DIS_BASE_X + 24);
- drawDigit(s % 10, DIS_BASE_X + 28);
- if (s >= 59)
- {
- ++m;
- s = 0;
- }
- else
- ++s;
- if (m >= 59)
- {
- ++h;
- m = 0;
- }
- }
- return 0;
- }
- void drawDigit(int digit, int hx)
- {
- int b;
- int px = hx, py = DIS_BASE_Y;
- setTextColor(TEXT_COLOR);
- for (b = 0; b <= 15; ++b)
- {
- GotoMap(px, py);
- PRINT_BOX(LIGHT[ GET_BIT(digitTable[digit], b-1) ]);
- if (b % 3 == 0)
- {
- py++;
- px = hx;
- }
- px++;
- }
- }
- void drawSeptor(int color, int hx)
- {
- setTextColor(color);
- GotoMap(hx, DIS_BASE_Y + 2);
- PRINT_BOX(LIGHT[1]);
- GotoMap(hx, DIS_BASE_Y + 4);
- PRINT_BOX(LIGHT[1]);
- }
- void initTime(int* hou, int* min, int* sec)
- {
- time_t t = time(NULL);
- struct tm* cur = localtime(&t);
- *hou = cur->tm_hour;
- *min = cur->tm_min;
- *sec = cur->tm_sec;
- }
- void delayMS(float secs)
- {
- clock_t start = clock();
- while (clock() - start < (secs * CLOCKS_PER_SEC))
- NULL;
- }
/* * * * * * * * * * * * * * * * * * * * * * * * // Project: DigitalClock(数字时钟) // Author: ProBlue // Notes: Some functions about Win32 Console Control. // Date: 2012.11.20 00:10 * * * * * * * * * * * * * * * * * * * * * * * */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include "pcc32.h" #define APP_TITLE "数字时钟" #define APP_HEIGHT 7 #define APP_WIDTH 38 #define DIS_BASE_X 2 #define DIS_BASE_Y 0 #define TEXT_COLOR LIGHT_GREEN #define GotoMap(x,y) gotoTextPos((x)*2,(y)) #define PRINT_BOX(s) printf("%2s",s) #define GET_BIT(v,b) ((v)>>(b)&1) PCCOLOR COLORS[] = {BLACK, LIGHT_GREEN}; char LIGHT[][3] = {" ", "■"}; // 各数字的形状方块的码表 static uint16 digitTable[10] = { 0x7B6F, 0x2492, 0x73E7, 0x79E7, 0x49ED, 0x79CF, 0x7BCF, 0x4927, 0x7BEF, 0x79EF }; void drawDigit(int digit, int hx); void drawSeptor(int color, int hx); void initTime(int* hou, int* min, int* sec); void delayMS(float secs); int main() { int h,m,s; int sepcx = 0; fixConsoleSize(APP_WIDTH*2, APP_HEIGHT); setConsoleTitle(APP_TITLE); setCursorVisible(0); initTime(&h, &m, &s); while (1) { delayMS(0.97); drawSeptor(COLORS[sepcx = !sepcx], DIS_BASE_X + 22); drawSeptor(TEXT_COLOR, DIS_BASE_X + 10); drawDigit(h / 10, DIS_BASE_X + 0); drawDigit(h % 10, DIS_BASE_X + 4); drawDigit(m / 10, DIS_BASE_X + 12); drawDigit(m % 10, DIS_BASE_X + 16); drawDigit(s / 10, DIS_BASE_X + 24); drawDigit(s % 10, DIS_BASE_X + 28); if (s >= 59) { ++m; s = 0; } else ++s; if (m >= 59) { ++h; m = 0; } } return 0; } void drawDigit(int digit, int hx) { int b; int px = hx, py = DIS_BASE_Y; setTextColor(TEXT_COLOR); for (b = 0; b <= 15; ++b) { GotoMap(px, py); PRINT_BOX(LIGHT[ GET_BIT(digitTable[digit], b-1) ]); if (b % 3 == 0) { py++; px = hx; } px++; } } void drawSeptor(int color, int hx) { setTextColor(color); GotoMap(hx, DIS_BASE_Y + 2); PRINT_BOX(LIGHT[1]); GotoMap(hx, DIS_BASE_Y + 4); PRINT_BOX(LIGHT[1]); } void initTime(int* hou, int* min, int* sec) { time_t t = time(NULL); struct tm* cur = localtime(&t); *hou = cur->tm_hour; *min = cur->tm_min; *sec = cur->tm_sec; } void delayMS(float secs) { clock_t start = clock(); while (clock() - start < (secs * CLOCKS_PER_SEC)) NULL; }
运行效果:
//pcc32 -About Win32 Console Control 's Simple Library:
- #ifndef PCC32_H
- #define PCC32_H
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <windows.h>
- typedef unsigned char uint8;
- typedef unsigned short uint16;
- typedef unsigned long uint32;
- /* 控制台尺寸定义 */
- #define MIN_CONSOLE_WIDTH 14
- #define MIN_CONSOLE_HEIGHT 1
- /* 颜色定义 */
- typedef enum _PCCOLOR
- {
- BLACK = 0, // 黑色
- BLUE = 1, // 蓝色
- GREEN = 2, // 绿色
- CYAN = 3, // 青色
- RED = 4, // 红色
- MAGENTA = 5, // 紫色
- BROWN = 6, // 褐色
- LIGHT_GRAY = 7, // 浅灰
- DARK_GRAY = 8, // 深灰
- LIGHT_BLUE = 9, // 亮蓝
- LIGHT_GREEN = 10, // 亮绿
- LIGHT_CYAN = 11, // 浅蓝
- LIGHT_RED = 12, // 亮红
- LIGHT_MAGENTA = 13, // 亮紫
- YELLOW = 14, // 黄色
- WHITE = 15 // 白色
- }PCCOLOR;
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- /* 延时,以毫秒计 */
- void delay(uint32 d);
- /* 清除文字 */
- void clearText(void);
- /* 设置文本颜色,0~15 */
- int setTextColor(uint8 fColor);
- /* 屏幕光标定位,x为列(横),y为行(纵) */
- int gotoTextPos(uint8 x, uint8 y);
- /* 设置光标的可见性 */
- int setCursorVisible(int b);
- /* 设置控制台的标题字符串 */
- int setConsoleTitle(char *title);
- /* 设置一个没有滚动条的控制台窗口尺寸 */
- int fixConsoleSize(uint16 width, uint16 height);
- /* 输出控制台的相关信息(仅作调试用) */
- int showConsoleInfo();
- #ifdef __cplusplus
- }
- #endif
- #endif // PCC32_H
#ifndef PCC32_H #define PCC32_H #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned long uint32; /* 控制台尺寸定义 */ #define MIN_CONSOLE_WIDTH 14 #define MIN_CONSOLE_HEIGHT 1 /* 颜色定义 */ typedef enum _PCCOLOR { BLACK = 0, // 黑色 BLUE = 1, // 蓝色 GREEN = 2, // 绿色 CYAN = 3, // 青色 RED = 4, // 红色 MAGENTA = 5, // 紫色 BROWN = 6, // 褐色 LIGHT_GRAY = 7, // 浅灰 DARK_GRAY = 8, // 深灰 LIGHT_BLUE = 9, // 亮蓝 LIGHT_GREEN = 10, // 亮绿 LIGHT_CYAN = 11, // 浅蓝 LIGHT_RED = 12, // 亮红 LIGHT_MAGENTA = 13, // 亮紫 YELLOW = 14, // 黄色 WHITE = 15 // 白色 }PCCOLOR; #ifdef __cplusplus extern "C" { #endif /* 延时,以毫秒计 */ void delay(uint32 d); /* 清除文字 */ void clearText(void); /* 设置文本颜色,0~15 */ int setTextColor(uint8 fColor); /* 屏幕光标定位,x为列(横),y为行(纵) */ int gotoTextPos(uint8 x, uint8 y); /* 设置光标的可见性 */ int setCursorVisible(int b); /* 设置控制台的标题字符串 */ int setConsoleTitle(char *title); /* 设置一个没有滚动条的控制台窗口尺寸 */ int fixConsoleSize(uint16 width, uint16 height); /* 输出控制台的相关信息(仅作调试用) */ int showConsoleInfo(); #ifdef __cplusplus } #endif #endif // PCC32_H
- #include "pcc32.h"
- void delay(uint32 d)
- {
- Sleep(d);
- return ;
- }
- void clearText(void)
- {
- system("cls");
- return ;
- }
- int setTextColor(uint8 fColor)
- {
- HANDLE hd = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO csbInfo;
- GetConsoleScreenBufferInfo(hd, &csbInfo);
- return SetConsoleTextAttribute(hd, fColor | (csbInfo.wAttributes&~0x0F));
- }
- int gotoTextPos(uint8 x, uint8 y)
- {
- COORD cd;
- cd.X = x;
- cd.Y = y;
- return SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cd);
- }
- int setCursorVisible(int b)
- {
- HANDLE hd = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO ccInfo;
- GetConsoleCursorInfo(hd, &ccInfo);
- ccInfo.bVisible = !!b;
- return SetConsoleCursorInfo(hd, &ccInfo);
- }
- int setConsoleTitle(char *title)
- {
- return SetConsoleTitle(title);
- }
- int fixConsoleSize(uint16 width, uint16 height)
- {
- int ret = 0;
- int fixX = 0, fixY = 0;
- COORD cd;
- SMALL_RECT srctWindow;
- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
- HANDLE hWin = GetStdHandle(STD_OUTPUT_HANDLE);
- if (!hWin)
- return 0;
- // 调整最小范围
- fixX = (width < MIN_CONSOLE_WIDTH) ? MIN_CONSOLE_WIDTH : width;
- fixY = (height < MIN_CONSOLE_HEIGHT) ? MIN_CONSOLE_HEIGHT : height;
- // 先将BUF尺寸扩大到最大
- cd.X = 512;
- cd.Y = 512;
- ret = SetConsoleScreenBufferSize(hWin, cd);
- if (!ret)
- return ret;
- //puts("Set Max Buf Error.");
- // 测试屏幕允许的最大尺寸
- GetConsoleScreenBufferInfo(hWin, &csbiInfo);
- cd = csbiInfo.dwMaximumWindowSize;
- //printf("Max Win Size[%d, %d].\n", cd.X, cd.Y);
- fixX = (fixX > cd.X) ? cd.X : fixX;
- fixY = (fixY > cd.Y) ? cd.Y : fixY;
- //printf("Fix Win Size[%d, %d].\n", fixX, fixY);
- // 确定适当的窗口尺寸
- srctWindow.Left = 0;
- srctWindow.Right = fixX - 1;
- srctWindow.Top = 0;
- srctWindow.Bottom = fixY - 1;
- ret = SetConsoleWindowInfo(hWin, 1, &srctWindow);
- if (!ret)
- return ret;
- //puts("Set Size Error.");
- // 确定适当的BUF尺寸
- cd.X = fixX;
- cd.Y = fixY;
- ret = SetConsoleScreenBufferSize(hWin, cd);
- if (!ret)
- return ret;
- //printf("Fix Win Size[%d, %d]: %d.\n", fixX, fixY, ret);
- Sleep(100);
- return ret;
- }
- int showConsoleInfo()
- {
- int ret;
- HANDLE hWin = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
- ret = GetConsoleScreenBufferInfo(hWin, &csbiInfo);
- if (ret)
- {
- printf("Buffer Size: [X]%d - [Y]%d\n", csbiInfo.dwSize.X, csbiInfo.dwSize.Y);
- printf("Cursor Pos : [X]%d - [Y]%d\n",
- csbiInfo.dwCursorPosition.X, csbiInfo.dwCursorPosition.Y);
- printf("Attributes : %d\n", csbiInfo.wAttributes);
- printf("Current Win: [L]%d - [R]%d - [T]%d - [B]%d\n", \
- csbiInfo.srWindow.Left, csbiInfo.srWindow.Right,
- csbiInfo.srWindow.Top, csbiInfo.srWindow.Bottom);
- printf("Maximum Win: [X]%d - [Y]%d\n",
- csbiInfo.dwMaximumWindowSize.X, csbiInfo.dwMaximumWindowSize.Y);
- puts("Over.");
- }
- return ret;
- }
- //End of pcc32.c
#include "pcc32.h" void delay(uint32 d) { Sleep(d); return ; } void clearText(void) { system("cls"); return ; } int setTextColor(uint8 fColor) { HANDLE hd = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbInfo; GetConsoleScreenBufferInfo(hd, &csbInfo); return SetConsoleTextAttribute(hd, fColor | (csbInfo.wAttributes&~0x0F)); } int gotoTextPos(uint8 x, uint8 y) { COORD cd; cd.X = x; cd.Y = y; return SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cd); } int setCursorVisible(int b) { HANDLE hd = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO ccInfo; GetConsoleCursorInfo(hd, &ccInfo); ccInfo.bVisible = !!b; return SetConsoleCursorInfo(hd, &ccInfo); } int setConsoleTitle(char *title) { return SetConsoleTitle(title); } int fixConsoleSize(uint16 width, uint16 height) { int ret = 0; int fixX = 0, fixY = 0; COORD cd; SMALL_RECT srctWindow; CONSOLE_SCREEN_BUFFER_INFO csbiInfo; HANDLE hWin = GetStdHandle(STD_OUTPUT_HANDLE); if (!hWin) return 0; // 调整最小范围 fixX = (width < MIN_CONSOLE_WIDTH) ? MIN_CONSOLE_WIDTH : width; fixY = (height < MIN_CONSOLE_HEIGHT) ? MIN_CONSOLE_HEIGHT : height; // 先将BUF尺寸扩大到最大 cd.X = 512; cd.Y = 512; ret = SetConsoleScreenBufferSize(hWin, cd); if (!ret) return ret; //puts("Set Max Buf Error."); // 测试屏幕允许的最大尺寸 GetConsoleScreenBufferInfo(hWin, &csbiInfo); cd = csbiInfo.dwMaximumWindowSize; //printf("Max Win Size[%d, %d].\n", cd.X, cd.Y); fixX = (fixX > cd.X) ? cd.X : fixX; fixY = (fixY > cd.Y) ? cd.Y : fixY; //printf("Fix Win Size[%d, %d].\n", fixX, fixY); // 确定适当的窗口尺寸 srctWindow.Left = 0; srctWindow.Right = fixX - 1; srctWindow.Top = 0; srctWindow.Bottom = fixY - 1; ret = SetConsoleWindowInfo(hWin, 1, &srctWindow); if (!ret) return ret; //puts("Set Size Error."); // 确定适当的BUF尺寸 cd.X = fixX; cd.Y = fixY; ret = SetConsoleScreenBufferSize(hWin, cd); if (!ret) return ret; //printf("Fix Win Size[%d, %d]: %d.\n", fixX, fixY, ret); Sleep(100); return ret; } int showConsoleInfo() { int ret; HANDLE hWin = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbiInfo; ret = GetConsoleScreenBufferInfo(hWin, &csbiInfo); if (ret) { printf("Buffer Size: [X]%d - [Y]%d\n", csbiInfo.dwSize.X, csbiInfo.dwSize.Y); printf("Cursor Pos : [X]%d - [Y]%d\n", csbiInfo.dwCursorPosition.X, csbiInfo.dwCursorPosition.Y); printf("Attributes : %d\n", csbiInfo.wAttributes); printf("Current Win: [L]%d - [R]%d - [T]%d - [B]%d\n", \ csbiInfo.srWindow.Left, csbiInfo.srWindow.Right, csbiInfo.srWindow.Top, csbiInfo.srWindow.Bottom); printf("Maximum Win: [X]%d - [Y]%d\n", csbiInfo.dwMaximumWindowSize.X, csbiInfo.dwMaximumWindowSize.Y); puts("Over."); } return ret; } //End of pcc32.c