这是以相关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