袁瑞 的个人资料袁瑞的共享空间照片日志留言簿更多 ![]() | 帮助 |
|
|
动态创建的TIdTime控件无法获取准确时间的问题在BCB2009内测试发现,使用代码动态创建的TIdTime获取到的服务器时间,总是比服务器的实际时间少两天。于是创建一个测试程序,将TIdTiime控件直接拖放到窗口中,测试发现获取到的时间是正确的。一切都是默认设置,代码中和界面中都只是设置了Host属性而已,到底区别在哪里呢? 我开始怀疑BaseDate属性,这个属性在拖放到界面上后会自动设置为一个默认值,如下图:1900/1/1,由于我使用的是英文操作系统,在其他系统上也许不是用/来分隔的。 查看TIdTime类的头文件,发现其属性BaseTime并没有默认值 __property System::TDateTime BaseDate = {read=FBaseDate, write=FBaseDate}; 在IDE属性编辑器中的默认值也许是在窗口内创建控件时加入的,而通过代码动态创建时似乎未设置。 RFC868中要求的时间是从00:00 (midnight) 1 January 1900 GMT开始,而TDateTime是从12/30/1899 12:00开始计算,恰好是2天! 于是我在动态创建TIdTime后,再设置BaseDate,测试获取时间正常了。 这里需要提醒一下,BaseDate是TDateTime类型,如果要将字符串“1900-1-1”转换为TDateTime类型,也许会出现错误,原因是日期分隔符不一定是"-",日期格式也不一定是YYYY-MM-DD,需要设置日期格式和分隔符,再进行转换: DateSeparator = '-'; 值得注意的是,似乎TIdTime控件在BCB6下的版本无此问题,BCB2009的TIdTime版本存在这个问题。 1月11日 bcb.exe.manifest 引发的“血案”升级到英文Vista后,最近发现BCB6中一些使用了ImageList类的程序会启动失败报Failed to read ImageList data的错误,让人很是费解。还有的程序可以在Vista下正常运行,但是在Xp下启动却会出现这个错误。一怒之下只能怪罪于TImageList,不曾想却是一桩冤案。 在使用Xp系统时,我就为了让BCB6.0的IDE也具有XP界面风格,将bcb.exe.manifest拷贝到安装目录下,这样可以强制BCB使用XP界面风格,即启用COMCTL32.DLL版本6(Vista下应该是更高版本)支持。这样界面在IDE的设计期内使用的是新版本,但是程序运行时如果不设置启用新版本支持就出现TImageList运行时无法正常读取数据的问题。 为了反向验证,将BCB目录下的bcb.exe.manifest文件删除,再打开问题程序时,打开界面时同样开始报错了。 同样也可以解释Vista下运行正常的程序,返回到Xp下运行失败的问题。Vista下程序内支持了更高版本的界面特性,导致TImageList在XP下运行无法读取数据,程序仍然遇到了类似的问题。 1月8日 setlocale同mbstowcs函数的关系程序中,如果要将ASCII码字符串转换为宽字符(Unicode),可以利用标准C的mbstowcs函数。 微软在MSDN中有示例,如下: 然而,这段代码在处理含有汉字的字符串时就会出现问题。比如将: 查看运行结果就会发现,mbstowcs函数将汉字视作两个ASCII字符,这样一个汉字就变成了两个wchar_t。原因是mbstowcs需要我们明确的告诉他要转换的字符语言。这里需要使用setlocale函数。在网上发现不少人遇到这个问题,微软的MSDN也是,为什么这里就不说明一下呢? 只要在调用前,使用setlocale(LC_ALL, "chs")设置,结果就正常了。 我测试在英文Vista操作系统内,Visual Studio 2008下setlocale(LC_ALL, "chs")可以执行成功。 但是在Borland C++Builder 6、CodeGear RAD Studio 2009下执行都失败,BCB提供的帮助文件内也未找到,反复测试使用setlocale(LC_ALL, "Chinese (Simplified)_People's Republic of China")可以奏效(这么大一个长串,BCB对搞中文编码的程序员也够狠)。 更讽刺的是,在BCB内使用setlocale(LC_ALL, "jpn"),或"cht"都可以成功。唯独就不支持"chs",对BCB的做法彻底无语了。我相信在大多数unix或linux上也还是支持"chs"的。如果有时间,我再搞一个MinGW试试看。 另外如果程序运行在非中文操作系统内,使用setlocale修改运行时字符集环境,会影响当前应用程序的编码方式,因此使用前需要保留一下老的编码,使用后再恢复。
for 在linux上coding的兄弟们,locale别名表大概在 /usr/lib/X11/locale/locale.alias 11月29日 判断是否为数字型字符串周六早晨睡醒,看见CSDN上有人求判断字符串是否为数字的代码,给出一个方法
bool __fastcall CheckIsNumber(AnsiString InputStr) { for(int i=1;i<=InputStr.Length();i++) { if( InputStr[i]<'0' || InputStr[i]>'9') return false; } return true; } 9月9日 C++Builder 2009 的一个Bug编译ActiveX control时,按照原来在CBuilder中的做法,将控件的GUID改成一个固定的GUID值(因为不想每次升级控件后,注册表中出现一堆无用的GUID) 一切看起来都很正常,编译成功。注册ocx控件时,却出现了0x8002802b错误。意思应该是找不到元素。 我开始并没有怀疑是修改了GUID的问题。反复定位才发现不修改GUID时是好的。 可不修改GUID以后怎么玩啊!这个2009也太扯了吧!很多使用控件的地方可都是用GUID实例化的。
我反复尝试,最终发现原因。 在 ridl接口设计器上修改接口时,ridl文件内容都是同步修改的,但只有修改GUID时,貌似ridl文件是修改了,但是最终的rtl文件CBuilder似乎没同步。即使你选择全部保存,单独保存都没有用。汗!这样就出现编译出来的内容跟接口对不上。 解决办法是,修改了GUID后,必须在ridl文件的设计界面上点击刷新按键,问题才能解决。
看来C++Builder2009,在很多细节上还有问题。 9月5日 使用C++Builder2009编写ActiveX控件的Unicode问题以前使用C++Builder6编写ActiveX控件, Event中的参数如果有字符串,编译总是有问题。 如果参数类型是AnsiString,创建ActiveX控件时,CBuiler根本就不会为你创建这个事件接口。 如果参数类型是char*,生成的ActiveX控件的参数类型则变成short,我是修改生成的代码,将参数手工变为LPSTR解决的问题。
而现在的2009,默认使用的是unicode,参数如果是UnicodeString,CBuilder创建的事件参数则是BSTR,不过我试验了很多次,编译出来的ActiveX控件在微软的测试容器中运行时,触发该事件都会引起内存访问错误。 另外一种方式,将参数声明为wchar_t*,生成的ActiveX控件的参数会变成short,这次改换成LPWSTR,手工修改CBuilder生成的实现类的cpp和h文件,修改TLB文件的h文件,将所有wchar_t类型替换成wchar_t*,同时将short也替换成wchar_t*,编译通过。 不过问题又出现了,在容器中运行,字符串会出现被截断的情况。 比如点燃事件中的字符串本来是"test",作为CBuilder控件进行测试是正常的,但编译成ActiveX控件到了容器里收到的却是"te"。
翻了翻2009的帮助文件,其中有这么一段: WideString WideString was previously used for multibyte character data. Its format is essentially the same as a Windows BSTR. WideString is still appropriate for use in COM applications. WideString is not reference counted, and so UnicodeString is more flexible and efficient in other types of applications. New String Type: UnicodeString The new default for the type string in RAD Studio is the UnicodeString type. This type can contain either Unicode or ANSI string data. For Delphi, Char and PChar types still "float" to WideChar and PWideChar, respectively. For C++, the _TCHAR maps to option controls the floating definition of _TCHAR, which can be either wchart_t or char. Format of UnicodeString Data Type
Both UnicodeString and AnsiString have this format, though UnicodeString prefers multibyte data and AnsiString prefers single byte data.
总的来说,新的UnicodeString为了跟AnsiString兼容做了部分处理,而WideString是纯粹的多字节字符串。
我看看我的点燃函数: if(FOnTextEvent) FOnTextEvent(this, Edit->Text.w_str());
这里的Edit->Text是UnicodeString类型,w_ctr()返回类型虽然是wchar_t*但是我怀疑问题就是出在这里。
于是改成如下代码: if(FOnTextEvent) FOnTextEvent(this, WideString(Edit->Text).c_bstr());
重新测试,一切正常了。这里不禁要提出疑问,2009在转换ActiveX控件时究竟让UnicodeString做了什么工作?是否出现了问题? 8月26日 A simple Design.A designer knows he has arrived at perfection not when there is no longer anything to add, but when there is no longer anything to take away. 8月4日 如何处理算数表达式今天看CSDN上有人问如何计算算数表达式的结果,比如"(2+3)*6" 原帖见:http://topic.csdn.net/u/20080731/11/50de3417-53d4-4228-99e6-505f64f8edde.html?seed=1989390904 我的算法是利用后缀表达式进行计算。后缀表达式的好处是在O(N)时间内完成表达式计算。 比如 "(2+3)*6" 转换为 " 2 3 + 6 * " 如果不清楚什么是后缀表达式,我就无语了。 得到后续表达式后,就是一个顺序压入堆栈执行的问题了 比如先获取第一个2入堆栈 ,然后是3入堆栈,然后发现是运算符+,这时执行运算符+,将2和3弹出,相加后入堆栈,然后是6,6入堆栈,然后是*,执行*,将堆栈中的两个数弹出执行,得到最后结果。
下面代码是我用BCB写的中缀转后缀表达式代码。图省事用了AnsiString,有空改成String就通用了。 //--------------------------------------------------------------------------- int __fastcall OperatorLevel(char Opt) AnsiString __fastcall InfixToPostFix(AnsiString inputString) //将表达式改为后缀表达式 if(tmpChar == ')') // 如果是闭括号,需要一直弹出到开括号 if(thePopOpt == '(') // 同操作符堆栈栈顶元素比较,如果优先级高,就入栈,否则直到弹出所有元素 if(OperatorLevel(thePopOpt)>OperatorLevel(tmpChar)) OperatorStack.push_back(tmpChar); if(tmpChar!='\0') if(i == inputString.Length()-1) while(!OperatorStack.empty()) return PostFixString; 7月16日 研究散列(Hashing)算法的体会散列,虽然只支持二叉查找树所允许的一部分操作,但是散列具有以常数平均时间执行插入、删除和查找的特点。 散列无法有效支持元素间排序的操作,因此像findMax、findMin以及在线性时间内按顺序打印所有元素的操作都无法支持。 为了解决散列冲突问题,普遍存在两种方式,
探测散列表又有三种解决冲突的方法,一种是线性探测,即逐个探测f(i)=i。优点是算法简单,缺点是存在"一次聚集"问题(Primary Clustering)。另一种是平方探测,即f(i)=i2。对于平方探测,表的大小是素数,那么当表至少有一半是空的时候,总能插入一个新的元素。虽然平方探测排除了一次聚集,但是散列到同一位置上的那些元素将探测相同的备选单元,即"二次聚集"(Secondary Clustering)。最后一种是双散列(double hashing),一种流行的选择是f(i)=i*hash2(x)。这个公式表明需要用到第二个散列函数用来解决冲突。诸如hash2(x)=R-(x mod R),R是小于TableSize的素数这样的函数将起到良好的作用,它可以尽可能做到在第一次散列到同样单元的元素,第二次散列到不同的其他元素上,即使会发生最坏的情况,但是非常少。
研究散列算法让我联系到另外一个应用,就是产生不重复的随机数,例如卡管理系统。都需要产生不规则的随机数作为卡号或密码,记得遇到一个类似的系统是通过产生可以重复的随机数(20位左右),利用数据库唯一索引检查,避免出现重复。不过运行时间长后,由于数据量越来越大,执行效率低的可怕。现在想起来,其实就是一个解决插入冲突的问题,分段的hashing算法就是一个解决办法不是。 5月23日 操作符“=”的巧妙用法和陷阱写程序久了,一直习惯了a=b=c的代码方式。今天才发现其中也有玄机。 模仿STL的list写了一个list的迭代器 其中的插入方法如下: Iterator insert(iterator itr, const Object &x) { ListNode* p= itr.current; ListNode* newnd = new ListNode(x, p->prev, p); //创建一个新的节点,参数分表为:节点数据、上一个节点、下一个节点 p->prev->next = newnd; p->prev = newnd; return iterator(newnd); } 我将此段代码简化后为: Iterator insert(iterator itr, const Object &x) { ListNode* p= itr.current; return iterator(p->prev->next = p->prev = new ListNode(x, p->prev, p) ); } 执行结果错误。 分析后才发现,a=b=c的代码,分解后是b=c;a=c ,导致以上错误出现。
正确代码应该是: Iterator insert(iterator itr, const Object &x) { ListNode* p= itr.current; return iterator(p->prev = p->prev->next = new ListNode(x, p->prev, p) ); } 11月30日 TCP中的状态说明From RFC793
A connection progresses through a series of states during its lifetime. The states are: LISTEN, SYN-SENT, SYN-RECEIVED, ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT, and the fictional state CLOSED. CLOSED is fictional because it represents the state when there is no TCB, and therefore, no connection. Briefly the meanings of the states are: LISTEN - represents waiting for a connection request from any remote TCP and port. SYN-SENT - represents waiting for a matching connection request after having sent a connection request. SYN-RECEIVED - represents waiting for a confirming connection request acknowledgment after having both received and sent a connection request. ESTABLISHED - represents an open connection, data received can be delivered to the user. The normal state for the data transfer phase of the connection. FIN-WAIT-1 - represents waiting for a connection termination request from the remote TCP, or an acknowledgment of the connection termination request previously sent. FIN-WAIT-2 - represents waiting for a connection termination request from the remote TCP. CLOSE-WAIT - represents waiting for a connection termination request from the local user. CLOSING - represents waiting for a connection termination request acknowledgment from the remote TCP. LAST-ACK - represents waiting for an acknowledgment of the connection termination request previously sent to the remote TCP(which includes an acknowledgment of its connection termination request). TIME-WAIT - represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request. CLOSED - represents no connection state at all. A TCP connection progresses from one state to another in response to events. The events are the user calls, OPEN, SEND, RECEIVE, CLOSE, ABORT, and STATUS; the incoming segments, particularly those containing the SYN, ACK, RST and FIN flags; and timeouts. The state diagram in figure 6 illustrates only state changes, together with the causing events and resulting actions, but addresses neither error conditions nor actions which are not connected with state changes. In a later section, more detail is offered with respect to the reaction of the TCP to events. NOTE BENE: this diagram is only a summary and must not be taken as the total specification.
+---------+ ---------\ active OPEN | CLOSED | \ ----------- +---------+<---------\ \ create TCB | ^ \ \ snd SYN passive OPEN | | CLOSE \ \ ------------ | | ---------- \ \ create TCB | | delete TCB \ \ V | \ \ +---------+ CLOSE | \ | LISTEN | ---------- | | +---------+ delete TCB | | rcv SYN | | SEND | | ----------- | | ------- | V +---------+ snd SYN,ACK / \ snd SYN +---------+ | |<----------------- ------------------>| | | SYN | rcv SYN | SYN | | RCVD |<-----------------------------------------------| SENT | | | snd ACK | | | |------------------ -------------------| | +---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+ | -------------- | | ----------- | x | | snd ACK | V V | CLOSE +---------+ | ------- | ESTAB | | snd FIN +---------+ | CLOSE | | rcv FIN V ------- | | ------- +---------+ snd FIN / \ snd ACK +---------+ | FIN |<----------------- ------------------>| CLOSE | | WAIT-1 |------------------ | WAIT | +---------+ rcv FIN \ +---------+ | rcv ACK of FIN ------- | CLOSE | | -------------- snd ACK | ------- | V x V snd FIN V +---------+ +---------+ +---------+ |FINWAIT-2| | CLOSING | | LAST-ACK| +---------+ +---------+ +---------+ | rcv ACK of FIN | rcv ACK of FIN | | rcv FIN -------------- | Timeout=2MSL -------------- | | ------- x V ------------ x V \ snd ACK +---------+delete TCB +---------+ ------------------------>|TIME WAIT|------------------>| CLOSED | +---------+ +---------+ 11月14日 函数调用的区别左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。
11月13日 CTI的主要标准协议从20世纪80年代起,在用户三方通讯应用需求的推动下,欧洲计算机制造协会(ECMA)发起了制定计算机和电信平台间的通讯标准运动。从那时起,产生了两个CTI标准:计算机支持的电话应用(CSTA)和交换机计算机应用接口(SCAI),随后,又有众多的厂商制定了相关的接口协议。下面对主要的CTI标准进行介绍。
1. CSTA标准 为了响应ECMA关于建立CTI标准的运动,包括AT&T、北电、Aicatel、Siemens、IBM、HP等电信设备制造商专门成立了一个委员会。该委员会制定了标准的ECMA-179-计算机支持的电信应用服务(CSTA)和标准ECMA-180-计算机支持的电信应用协议,CSTA协议是计算机与电信网间的OSI第7层通讯协议。 CSTA获得了大多数交换机制造商和呼叫中心开发公司的支持,目前的版本有CSTAI(1992)、CSTAII(1994)、CSTAIII(1998)。 CSTA为集成计算机和电信网平台定义了总体结构、要求和协议。这项技术标准强调了计算机和交换的灵活性、双向通讯和分布模型。由于CSTA起初是针对专用网的,因此它关注的是基于交换的对象,比如电话、中继线和队列等。CSTA服务是独立于交换平台的,它并不知道交换机是如何完成CSTA服务请求的特殊细节。
2. SCAI标准 交换机计算机应用接口(SCAI)标准是由美国国家标准协会(ANSI)制定的。SCAI详述了一种结构和OSI应用协议,以便在计算机和交换机应用程序间进行对等的数据通讯,从而实现计算机和电话交换平台的集成。 SCAI受其他标准的影响,包括受ISDN和智能网(IN)的影响。新一版的SCAI的目标是实现在公众网和专用网上的呼叫中心的应用。与CSTA不同的是,CSTA强调通讯集成而不是应用集成。由于CSTA提供了更多的事件报告能力,因此吸引了更多的应用开发者。
3. Versit标准 Versit是有四家主导计算机通讯产品的生产商——Apple公司、AT&T、IBM和Siemens Rolm组成的,目的是签署使计算机、电话及其他网络应用能共同工作的标准。该协会将保证那些获得其批准的产品能够互相作用。 Versit的另一个目标是定义技术规范,而且也已选择了一些现有的标准作为技术规范基础。Novell的TSAPI、IBM的CallPath交换正规化方案、单方呼叫功能以及下一代电话应用的一系列目标都由Versit支持。 电话和计算机目录接口方面的不统一会导致CTI产业分裂成两个阵营的危险。Versit选择了Aplle的GeoPort作为计算机到电话的物理链接。而Intel则提出了另一个接口,称为高速串行接口。而且拥有Compaq、Microsoft和北电诸多公司的支持。 Intel和其竞争对手Versit正在为完成多媒体通讯的标准展开竞争。如果谁的标准被标准化组织选用,谁就会扩展的更远。双方起初使用同一个宏结构,该结构的顶层的5Mbit/s串行总线用以同步数据,该结构的API层及其上的格式规范为各种PC应用提供数据。
4. CallPath标准 IBM的CallPath是20世纪80年代后期引入的主机CTI结构,是为了给从PBX到大呼叫中心环境中的IBM的主要链接提供接口。随后软件被扩展为能够容纳诸如OS/2和AIX的附加的IBM操作系统。最近,IBM宣布了一个CallPath的客户/服务器版本,反映了此环境的普遍性和重要性。 客户/服务器CallPath是一个几乎服务器的软件包。IBM将其产品定位在通用CTI服务器的概念上,而不是定位于特定的LAN环境(应与Novell为Netware LAN对TSAPI所做的处理一样)。PC、工作站及主机都可以与支持CallPath的服务器相连接,具有同时支持多达4个PBX的能力。该标准可以在一系列操作系统上允许,包括Windows、Solaris、SCO UNIX、IBM的AIX和OS/2系统。 从应用方面来说,IBM鼓励三方连接的开发者开发与CallPath兼容的应用程序,但IBM的方法没有Novell和Microsoft的那样富有攻击性。IBM的软件开发者工具箱的价格相当高,而且IBM也提供客户软件产品。 另外,IBM正在为它的将CallPath消息转换为指定电话系统形式的网关软件申请许可证。这个软件可以使交换机与现有的CallPath应用程序一同工作,而且方便了这些应用程序从一个主机到另一个主机的可移动性。ACD的主导生产商——Aspect Telecommunication,是第一个可以发放CallPath服务结构(CSA)许可证的电话系统销售商,并获得了IBM的确认。虽然正在向更大的呼叫中心环境迈进,但是从未来的趋势看这个做法在整个CTI工业界是相当恰当的。 5. SCSA MVIP标准 有两种主要方法将PC电话模块接口与其他设备相关联:一种是信号计算系统结构(SCSA),另一种是多厂家集成协议(MVIP)。这两个标准都是数字电话总线,使电话数据流的传输和交换在PC内或PC与其他设备之间进行。其他的设备可以是任一种已经存在的电话系统,包括PBX、Key系统、混合系统、IVR、预拨号机、ACD等。两个标准都有相似的目标:使集成者用不同的来自不同厂家的基于PC的应用卡创建一个终极用户解决办法。因此,客户可以从一个由语音卡、传真卡、视频卡、会议卡、语音辨认卡及其他卡构成的多资源系统获得好处,所有这些都使用同一条总线和软件接口。 MVIP是由一群电话卡厂商倡导的,包括Natural MicroSystems、Rhetorex和Pika。Dialogic(基于PC的语音模块的市场领导者)则引入了SCSA总线。这两类总线是互不兼容的,因此应用程序提供者和集成者需要在二者之间做出选择。
6. TAPI标准 Windows电话API被称为TAPI,Microsoft的TAPI提供单方连接。TAPI的目的是为Windows平台提供“个人电话”,它包含在Windows95及以后的各种Windows版本中。Windows95/98/Me系列产品支持TAPI2.0;Windows2000/XP系列则支持TAPI3.0。 Windows电话是由Windows电话动态链接库和两个标准组成的。第一个标准是服务提供者接口(SPI)。SPI被发送给那些希望遵从Windows电话的硬件生产商。如果硬件生产商的产品遵从SPI,就可以与Windows电话的DLL对话。第二个标准称为应用编程接口(API),它被发送给编写应用程序的软件开发者。如果这些开发者的软件遵守API,就可以利用Windows电话DLL的便利驱动任何电话设备或遵从SPI的服务。
7. TSAPI标准 TSAPI在电话和PC之间提供三方连接。CTI应用使用TSAPI控制任何一个呼叫,即使该呼叫进入了公司内部任何一条电话线。可以实现一些功能,比如转移呼叫,交互式语音应答(IVR)以及自动呼叫分配(ACD)等。Novell和AT&T发展TSAPI是为了给Netware操作系统增加电话服务。其结果是电话服务API需要使用LAN,不在每个电话和PC上建立直接的连接。而是在服务器电话系统间建立一个连接。这个连接称为PBX-to-Server连接,它在物理上可以由几种方式建立。
除了以上的标准外,Apple公司的MTA(将Mac机定位于多目的可处理电话应用的计算机系统)、北电的T-MAP(在TAPI和TSAPI之间提供转换功能)、Sun的XTL远程服务和ITU制定的TASC标准也是比较重要的。 11月12日 注册一个文件类型,并指定打开该类型的程序//--------------------------------------------------------------------------- windows下进程间通信的手段有哪些?1 进程与进程通信 进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码、数据以及它可利用的系统资源(如文件、管道等)组成。多进程/多线程是Windows操作系统的一个基本特征。Microsoft Win32应用编程接口(Application Programming Interface, API)提供了大量支持应用程序间数据共享和交换的机制,这些机制行使的活动称为进程间通信(InterProcess Communication, IPC),进程通信就是指不同进程间进行数据共享和数据交换。 2 进程通信方法 2.1 文件映射 |
|
|