2008年4月27日
// 格林威治时间转换为北京时间(2000年以后)
// 输入参数 年(2位),月,日,时,分,秒
void Calc( int y, int m, int d, int hh, int mm, int ss )


{
int w; // 星期
hh += 8; // 格林威治时间 + 8 小时 = 北京时间

if( hh < 24 ) goto l_out; // 没有跨天,则计算完成


/**////////////// 下面是跨天后的计算 /////////////////////////////
hh -= 24;
d ++; // 日期加一天

switch( m ) // 按月判断

{
case 4: case 6: // 跨小月的判断
case 9: case 11:
if( d > 30 )

{
d = 1; m ++;
}
break;

case 1: case 3: // 跨大月的判断
case 5: case 7:
case 8: case 10:
if( d > 31 )

{
d = 1; m ++;
}
break;

case 12: // 12 月,要判断是否跨年
if( d > 31 )

{
y ++; d = 1; m = 1;
}
break;

case 2: // 2 月,要判断是否是闰年
if( ( (y+2000)%400 == 0 ) || // 能被400整除,一定是闰年
( (y+2000)%4 ==0 ) && ( (y+2000)%100 !=0 ) ) // 能被4整除,但不能被100整除,一定是闰年

{
if( d>29 ) // 闰年2月,可以有29号

{
m = 3; d = 1;
}
}
else if( d>28 ) // 非闰年2月,可以有28号

{
m = 3; d = 1;
}
break;
}

l_out: // 计算完成,开始输出
printf( "%04d.%02d.%02d - %02d:%02d:%02d", y+2000, m, d, hh, mm, ss);
if( 1 == m )

{
y --;
m = 13;
}
else if( 2 == m )

{
y --;
m = 14;
}

w = y + y/4 + 26 * ( m + 1 ) / 10 + d - 1;
w %= 7; // 0 表示星期日

printf ( " week=%d ", w );
}
2007年11月18日
CComQIPtr< ISpecifyPropertyPages > spSpecify( m_ax.GetControlUnknown() );
if( !spSpecify ) return;

CAUUID pages;
HRESULT hResult = spSpecify->GetPages( &pages );
if( FAILED( hResult ) ) return;

CLSID * pclsidPages = (CLSID*)_alloca( pages.cElems * sizeof( CLSID ) );
for( int i=0; i<(int)pages.cElems; i++ )
pclsidPages[i] = pages.pElems[i];

::CoTaskMemFree( pages.pElems );

IUnknown * pObject = m_ax.GetControlUnknown();

OleCreatePropertyFrame( m_hWnd, 0, 0, L"属性",
1, &pObject,
pages.cElems, pclsidPages,
GetUserDefaultLCID(), 0, NULL );
2007年10月7日
VC 2003 版本,UNICODE 编译,居然不支持 wsprintf( buf,_T(“%2.1f”),fValue ) 浮点数格式化?!
由于是 API 函数,估计其它版本的编译器可能也会有问题。
2007年4月21日
一个C/S程序,我自己写的SERVER,我自己写的CLIENT,他们之间使用TCP通讯。某用户使用CLIENT的时候,服务器经常莫名其妙地崩溃,我自己和同事测试,又总找不到问题。今天终于被我逮到了BUG,在我自己的通讯数据中,居然被BT插入了他的数据:“......我的数据......\rBitTorrent Protocol.......我的数据......”导致我服务程序的崩溃。我的天呀!!!!!TNND,BT真变态!!!和某用户联系询问他是否安装了BT下载软件,回答是“yes”。建议他删除BT后,一切正常了。
代码改进后,程序终于健壮了。
友情提示:不要想当然地认为TCP数据就能100%地正确地传递到了对方。
2007-04-21
2006年11月11日
就这个破程序居然浪费了我4个小时来调试! 奉献出来免得大家再走弯路。
SendMMS()


{
HANDLE hCom = CreateFile( _T("COM1"),
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL );
if( NULL == hCom ) return false;

DCB dcb;
::GetCommState( hCom, &dcb );
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;

if( !::SetCommState( hCom, &dcb ) ) return false;
if( !::PurgeComm( hCom, PURGE_RXCLEAR ) ) return false;
DWORD dw;
::WriteFile( hCom, "AT\r", 3, &dw, NULL );
// 读串口,判断是否正常
// 切换到中文短信方式
::WriteFile( hCom, "AT+WSCL=6,4\r", 12, &dw, NULL );
// 读串口,判断是否正常

::WriteFile( hCom, "AT+CMGF=1\r", 10, &dw, NULL );
// 读串口,判断是否正常

WCHAR wszTxt[500];
::wcscpy( wszTxt, L"hello 你好" );

int len = (int)::wcslen(wszTxt);// 字符长度
for( int i=0; i<len; i++ ) // 交换高低字节
wszTxt[i] = MAKEWORD( HIBYTE(wszTxt[i]), LOBYTE(wszTxt[i]) );

char szNumber[50]; // 手机号码,内容长度
::sprintf( szNumber, "AT+CMGS=\"13901112233\",%d\r", len*2 );
::WriteFile( hCom, szNumber, (DWORD)::strlen( szNumber ), &dw, NULL );
::Sleep(500);

::WriteFile( hCom, wszTxt, len*2, &dw, NULL );
::WriteFile( hCom, "\x00\x1a\r", 3, &dw, NULL ); // 结束符
// 读串口,判断是否正常
::CloseHandle( hCom );
return true;
}
2006年11月1日
#include <Winsock2.h>
#include <mstcpip.h>

#pragma comment(lib,"WS2_32.lib")

typedef struct _iphdr


{
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;

typedef struct _tcphdr //定义TCP首部


{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;//4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;

typedef struct _udphdr //定义UDP首部


{
unsigned short uh_sport;
unsigned short uh_dport;
unsigned short uh_len;
unsigned short uh_sum;
} UDP_HEADER;

typedef struct _icmphdr //定义ICMP首部


{
BYTE i_type; //8位类型
BYTE i_code; //8位代码
USHORT i_cksum; //16位校验和
USHORT i_id; //识别号(一般用进程号作为识别号)
USHORT i_seq; //报文序列号
ULONG timestamp; //时间戳
}ICMP_HEADER;

bool DecodeIpPack(const char *,int); // IP 解包
bool DecodeTcpPack(const char *); // TCP 解包
bool DecodeUdpPack(const char *); // UDP 解包
bool DecodeIcmpPack(const char *); // ICMP 解包
const char * CheckProtocol(int);// 查询协议

int _tmain(int argc, _TCHAR* argv[])


{
// 初始化SOCKET
WSADATA wsaData;
int iErrorCode = ::WSAStartup( MAKEWORD(2,1), &wsaData );
if( SOCKET_ERROR == iErrorCode )

{
printf( "WSAStartup() error. " );
return -1;
}
SOCKET sock = ::socket( AF_INET, SOCK_RAW, IPPROTO_IP );
if( INVALID_SOCKET == sock )

{
printf( "socket() error. " );
return -1;
}

//获取本机IP地址
char szHostName[200];
iErrorCode = ::gethostname( szHostName, sizeof(szHostName) );
if( SOCKET_ERROR == iErrorCode )

{
printf( "gethostname() error. " );
return -1;
}

PHOSTENT pHostent = ::gethostbyname( szHostName );
if( NULL == pHostent )

{
printf( "gethostbyname() error. " );
return -1;
}

SOCKADDR_IN sa;
sa.sin_family = AF_INET;
memcpy( &sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length );
sa.sin_port = htons( 60000 );

iErrorCode = ::bind( sock, (PSOCKADDR)&sa, sizeof(sa) );
if( SOCKET_ERROR == iErrorCode )

{
printf( "bind() error. " );
return -1;
}

// 设置 SOCK_RAW 为 SIO_RCVALL,接收所有的 IP 包
DWORD dwBufferLen[10];
DWORD dwBufferInLen = 1;
DWORD dwBytesReturned = 0;
iErrorCode = ::WSAIoctl( sock, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen,
sizeof( dwBufferLen ), &dwBytesReturned, NULL, NULL );
if( SOCKET_ERROR == iErrorCode )

{
printf( "Ioctl() error. " );
return -1;
}

//侦听IP报文
while( 1 )

{

char package[8 * 1024] =
{ 0 }; // 数据缓冲区
iErrorCode = ::recv( sock, package, sizeof(package), 0 );
if( SOCKET_ERROR == iErrorCode )
printf( "recv() error. " );
else if( !DecodeIpPack( package, iErrorCode ) ) // 解析 IP 包
printf( "DecodeIpPack() error. " );
}

// ::Closesocket( sock );
// ::WSACleanup();
return 0;
}

// 解析 IP 包
bool DecodeIpPack(const char *buf, int iBufSize)


{
IP_HEADER *pIpheader;
int iProtocol, iTTL;
char szProtocol[12];
char szSourceIP[16];
char szDestIP[16];
SOCKADDR_IN saSource, saDest;
pIpheader = (IP_HEADER *)buf;

//Check Proto
iProtocol = pIpheader->proto;
::strcpy( szProtocol, CheckProtocol(iProtocol) );

//Check Source IP
saSource.sin_addr.s_addr = pIpheader->sourceIP;
::strcpy( szSourceIP, inet_ntoa(saSource.sin_addr) );

//Check Dest IP
saDest.sin_addr.s_addr = pIpheader->destIP;
::strcpy( szDestIP, inet_ntoa(saDest.sin_addr) );
iTTL = pIpheader->ttl;

//Output
printf( "%s ", szProtocol );
printf( "%s->%s ", szSourceIP, szDestIP );
printf( "bytes=%d TTL=%d ",iBufSize,iTTL );

//Calculate IP Header Length
int iIphLen = sizeof(unsigned long) * ( pIpheader->h_lenver & 0x0f );

//Decode Sub Protocol:TCP, UDP, ICMP, etc
switch( iProtocol )

{
case IPPROTO_TCP: DecodeTcpPack( buf + iIphLen ); break;
case IPPROTO_UDP: DecodeUdpPack( buf + iIphLen ); break;
case IPPROTO_ICMP: DecodeIcmpPack( buf + iIphLen ); break;
default: break;
}
printf( " " );

int col = 0;
char ascii[17];
for( int i=0; i<iBufSize; i++ )

{
printf( "%02X ", (unsigned char)buf[i] );

ascii[ col++ ] = ( unsigned char )buf[i] < 0x20 ? '.' : buf[i];

if( 15 == i%16 )

{
ascii[ col ] = 0;
printf( "%s ", ascii );
col = 0;
}
else if( 7 == i%8 ) printf( "- " );
}
if( col )

{
for( int i=col; i<16; i++ )

{
printf( " " );
if( 15 == i%16 )

{
ascii[ col ] = 0;
printf( "%s ", ascii );
}
else if( 7 == i%8 ) printf( "- " );
}
}

return true;
}

//协议识别程序
const char * CheckProtocol(int iProtocol)


{
typedef struct _protomap //定义子协议映射表

{
int ProtoNum;
char ProtoText[12];
}PROTOMAP;


static PROTOMAP ProtoMap[]=
{ //为子协议映射表赋值

{ IPPROTO_IP, "IP" },

{ IPPROTO_ICMP, "ICMP" },

{ IPPROTO_IGMP, "IGMP" },

{ IPPROTO_GGP, "GGP" },

{ IPPROTO_IPV4, "IPV4" },

{ IPPROTO_TCP, "TCP" },

{ IPPROTO_PUP, "PUP" },

{ IPPROTO_UDP, "UDP" },

{ IPPROTO_IDP, "IDP" },

{ IPPROTO_IPV6, "IPV6" },

{ IPPROTO_ROUTING, "ROUTING" },

{ IPPROTO_FRAGMENT, "FRAGMENT" },

{ IPPROTO_ESP, "ESP" },

{ IPPROTO_AH, "AH" },

{ IPPROTO_ICMPV6, "ICMPV6" },

{ IPPROTO_NONE, "NONE" },

{ IPPROTO_DSTOPTS, "DSTOPTS" },

{ IPPROTO_ND, "ND" },

{ IPPROTO_ICLFXBM, "ICLFXBM" },

{ IPPROTO_RAW, "RAW" },

{ IPPROTO_MAX, "MAX" },
};
const int nProtoCount = sizeof(ProtoMap)/sizeof(PROTOMAP);

for(int i=0; i<nProtoCount; i++)

{
if(ProtoMap[i].ProtoNum==iProtocol)
return ProtoMap[i].ProtoText;
}
return "";
}

//TCP解包程序
bool DecodeTcpPack(const char * TcpBuf)


{
TCP_HEADER * pTcpHeader;
int i;
pTcpHeader = (TCP_HEADER * )TcpBuf;
printf("Port:%d->%d ", ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport));
unsigned char FlagMask = 1;
for( i=0; i<6; i++ )

{
static char * TcpFlag = "FSRPAU"; //定义TCP标志位
if( ( pTcpHeader->th_flag ) & FlagMask )
printf( "%c", TcpFlag[i] );
else printf( "-" );

FlagMask = FlagMask << 1;
}
return true;
}

//UDP解包程序
bool DecodeUdpPack(const char * UdpBuf)


{
UDP_HEADER *pUdpHeader;
pUdpHeader = (UDP_HEADER * )UdpBuf;
printf("Port:%d->%d ", ntohs(pUdpHeader->uh_sport), ntohs(pUdpHeader->uh_dport));
printf("Len=%d", ntohs(pUdpHeader->uh_len));
return true;
}

//ICMP解包程序
bool DecodeIcmpPack(const char * IcmpBuf)


{
ICMP_HEADER *pIcmpHeader;
pIcmpHeader = (ICMP_HEADER * )IcmpBuf;
printf("Type:%d,%d ", pIcmpHeader->i_type,pIcmpHeader->i_code);
printf("ID=%d SEQ=%d", pIcmpHeader->i_id, pIcmpHeader->i_seq);
return true;
}
2006年10月16日
两天前我解答 [shutle] 网友计算闰年方法的时候,回答错误,在这里一并更正并致歉。后来查阅了资料,现把计算方法和原理粘贴一下:
我们知道地球自转一圈为1天,地球围绕太阳公转一圈为1年。那1年到底等于多少天哪?答案是:1年=365天5小时48分46秒,即 365.242199[074] 天(注:用[xxx]表示无限循环)
因此,4年 = 4*365.242199[074] = 4*365 + 0.9687[962] 天
显然,每隔4年,就要多出了将近1天,因此公元历法就定义㈠:每4年加一天,即闰年(366天)
那么,也就是说4年就多算了:1-0.9687[962] = 0.0312[037]天
照这样算下去,100年中有25次闰年,那么就会多计算了 25*0.0312[037]=0.7800[925] 天,这又太接近1天了,因此公元历法就定义㈡:每100年的那年不算闰年。
于是:
100年中就又会少算 1-0.7800[925]=0.2199[074] 天
200年会少算 2*0.2199[074] = 0.439[814] 天
300年会少算 3*0.2199[074] = 0.6597[2] 天
400年会少算 4*0.2199[074] = 0.87[962] 天
停!400年后的误差又接近1天了,于是公元历法进行修正㈢:400年的那年(虽然是100年的倍数),但又算闰年啦。于是,400年的时候,由于多算了一次闰年,那么,
每隔400年就会多算:1-0.87[962] = 0.12[037] 天
显然,等到4000年的时候(那时,看到这个帖子的人都死了2000年了),误差又到1天多了,也许那个时候公元历法有会进行修改了“每4000年少一个闰年”。哈哈,反正不管我们的事了。但也不尽然,因为地球的自转很不稳定,但总的趋势是每年要慢一丁点(大家是否还记得今年2006年元旦,全世界的人都要把表拨慢1秒钟?)由于阴差阳错,也许4000年后并不需要少算一个闰年也不一定呐。总结一下闰年的算法:
㈠ 每4年一闰 ㈡ 每100年的那年不闰 ㈢ 每400年的那年又闰
真罗嗦,用咱们IT人的话说,就是能被4整除但不能被100整除,可是却能被400整除的年是闰年
2006年9月23日
void main()
{
long a=10000,b=0,c=2800,d=0,e=0,f[2801],g=0;
for( ; b-c; )
f[ b++ ]=a/5;
for( ;d=0, g=c*2; c-=14, printf( "%.4d",e+d/a ), e = d%a )
for( b=c; d += f[b] * a, f[b] = d%--g, d /= g--, --b; d *=b );
}
运行一下吧,猜猜是什么结果。
2006年4月2日
本人在一个工程任务中,需要完成“在9个整数中,找到中值”。
比如:1,3,5,7,9,2,4,6,8 的中值是5。
看似非常简单的一个小问题,但由于每秒钟需要调用大约10万多次,因此我需要一个快速算法,不考虑空间浪费,只要求比较语句尽可能的少。
有好的想法吗?欢迎抛砖引玉......
2005年12月28日
Y = 0.299R + 0.587G + 0.114B
U = -0.1684R - 0.3316G + 0.5B + 128
V = 0.5R - 0.4187G - 0.0813B + 128
--------------------------------------------------
保留小数后6位:
R = Y - 0.000037U + 1.401988V - 179.449700
G = Y - 0.344078U - 0.713885V + 135.419284
B = Y + 1.771795U - 0.001259V - 226.628590
--------------------------------------------------
保留小数后2位:
R = Y + 1.4V - 179.45
G = Y - 0.34U - 0.71V + 135.42
B = Y + 1.77U - 226.63