??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV永久无码精品一福利,亚洲一级免费毛片,亚洲黄色免费电影http://www.tkk7.com/tingfeng/category/38486.html在Ԓ望,在远眺,在思烦Q在彷L~zh-cnTue, 11 Apr 2017 21:10:01 GMTTue, 11 Apr 2017 21:10:01 GMT60【{】Zlib库的安装与?/title><link>http://www.tkk7.com/tingfeng/articles/432445.html</link><dc:creator>听风</dc:creator><author>听风</author><pubDate>Tue, 11 Apr 2017 08:30:00 GMT</pubDate><guid>http://www.tkk7.com/tingfeng/articles/432445.html</guid><wfw:comment>http://www.tkk7.com/tingfeng/comments/432445.html</wfw:comment><comments>http://www.tkk7.com/tingfeng/articles/432445.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tingfeng/comments/commentRss/432445.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tingfeng/services/trackbacks/432445.html</trackback:ping><description><![CDATA[     摘要: 在实际应用中l常会遇到要压羃数据的问题,常见的压~格式有zip和rar,?Linux下那更多了,bz2,gz,xz什么的都有Q单单Linux下的解压和压~命令就有好多呢Q没有什么好不好的。查了资料,应该是zlibq个 比较单好用。应用也q,所以就准备用这个了?   下蝲Zlib库,地址: http://zlib.net /zlib128.zip 用wget下蝲Q然后再...  <a href='http://www.tkk7.com/tingfeng/articles/432445.html'>阅读全文</a><img src ="http://www.tkk7.com/tingfeng/aggbug/432445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tingfeng/" target="_blank">听风</a> 2017-04-11 16:30 <a href="http://www.tkk7.com/tingfeng/articles/432445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Socketd通信http://www.tkk7.com/tingfeng/articles/411469.html听风听风Tue, 25 Mar 2014 14:45:00 GMThttp://www.tkk7.com/tingfeng/articles/411469.htmlhttp://www.tkk7.com/tingfeng/comments/411469.htmlhttp://www.tkk7.com/tingfeng/articles/411469.html#Feedback0http://www.tkk7.com/tingfeng/comments/commentRss/411469.htmlhttp://www.tkk7.com/tingfeng/services/trackbacks/411469.html #include #pragma comment(lib,"WS2_32.lib") void main() { WSADATA wsd; SOCKET server; //服务器socket SOCKADDR_IN addrSrv; char sendBuf[100]; char recvBuf[100]; SOCKADDR_IN addrClient; SOCKET client; //q接的客Lsocket int len; if(WSAStartup(MAKEWORD(2,2),&wsd)!=0) { printf("start up failed!\n"); return ; } server=socket(AF_INET,SOCK_STREAM,0); //创徏socket addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); //讄地址 addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); //讄端口? bind(server,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //l定 listen(server,5); //讄最多连接数 len=sizeof(SOCKADDR); while(1) { client=accept(server,(SOCKADDR*)&addrClient,&len); //接收客户端连? sprintf(sendBuf,"Welcome %s ", inet_ntoa(addrClient.sin_addr)); send(client,sendBuf,strlen(sendBuf)+1,0); //发送信息客L recv(client,recvBuf,100,0); //接收客户端数? printf("%s\n",recvBuf); closesocket(client); } closesocket(client); //关闭q接 WSACleanup(); } client.cpp #include #include #pragma comment(lib,"WS2_32.lib") void main() { int call = 0; int result = 0; while(1) { printf("\n\n误入命令:\n"); printf("\t1:发vq接\n"); printf("\t2:发送数据\n"); printf("\t3:关闭q接\n"); printf("\t4:重新q接\n"); printf("\t0:关闭E序\n"); scanf("%d",&call); try{ switch(call) { case 1: printf("发vq接\n"); WSADATA wsd; SOCKET sockClient; //客户端socket SOCKADDR_IN addrSrv; char recvBuf[100]; char sendbuf[100]; if(WSAStartup(MAKEWORD(2,2),&wsd)!=0) { printf("start up failed!\n"); return ; } sockClient=socket(AF_INET,SOCK_STREAM,0); //创徏socket addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //q接服务器端 recv(sockClient,recvBuf,100,0); //接收服务器端数据 printf("%s\n",recvBuf); break; case 2: printf("误入要发送的文字\n"); scanf("%s",&sendbuf); printf("%s\n",sendbuf); result = send(sockClient,sendbuf,50,0); //向服务器端发送数? printf("操作l果Q?d\n",result); break; case 3: result = closesocket(sockClient); printf("操作l果Q?d\n",result);//关闭q接 WSACleanup(); printf("q接已经关闭\n"); break; case 4: printf("重新q接\n");//此处功能暂未实现 break; case 0: return; default: break; } }catch(Exception e) { } } }

听风 2014-03-25 22:45 发表评论
]]>
windows vc++6.0 目录操作函数http://www.tkk7.com/tingfeng/articles/262793.html听风听风Sun, 29 Mar 2009 16:00:00 GMThttp://www.tkk7.com/tingfeng/articles/262793.htmlhttp://www.tkk7.com/tingfeng/comments/262793.htmlhttp://www.tkk7.com/tingfeng/articles/262793.html#Feedback0http://www.tkk7.com/tingfeng/comments/commentRss/262793.htmlhttp://www.tkk7.com/tingfeng/services/trackbacks/262793.html

//Author : cppgp
//Email   : cppgp@163.com
//Time    : 2007 03 30
//按照字母序排列

1 . int _access( const char *path, int mode );
功 ??: 定文g/目录存取权限.
头文?: #include <io.h>
参 ??: path:文g或者目?br />    mode:权限讑֮,其值如?
   00 Existence only
   02 Write permission
   04 Read permission
   06 Read and write permission

q回?: 拥有该权限返?
   没有权限q回-1Q且讄errno为如下?br />    ENOENT 路径/文g不存?br />    EACCES 没有相应权限

2 . int _chdir( const char *dirname );
功 ??: 更改当前工作目录.
头文?: #include <direct.h>
q回?: 成功q回0
   p|q回-1Q且讄errno如下:
   ENOENT 该\径不存在

3 . int _chdrive( int drive );
功 ??: 更改当前工作驱动?
头文?: #include <direct.h>
q回?: 成功q回0
   p|q回-1
注 ??: 参数说明
     drive =1<==> A?br />      drive =2<==> B?br />      drive =3<==> C?br />    如此{等,该函数可以由_chdir代替

4 . int _findclose( long handle );
功 ??: 关闭搜寻句柄q攄应资?br /> 头文?: #include <io.h>
参 ??: long handle 搜烦句柄(通常q靠其前的_findfirst()q回,_findfirst()见下)
   fileinfo 文g信息buffer
q回?: 成功q回0
   出错q回-1,且设|errno为如下?br />    ENOENT 没有更多的符合该泛式的文?/p>

5 . long _findfirst( char *filespec, struct _finddata_t *fileinfo );
功 ??: 提供与filespec指定入口泛式匚w的第一个文?通常后用_findnext函数后箋使用来完成某泛式下的文g遍历.
头文?: #include <io.h>
参 ??: filespec 目标文g规范,可以包含通配W?br />    fileinfo 文g信息buffer
q回?: 成功q回唯一的搜索句?br />    出错q回-1,且设|errno为如下?br />    ENOENT 该泛式无法匹?br />    EINVAL 无效文g?/p>

6 . int _findnext( long handle, struct _finddata_t *fileinfo );
功 ??: 按照前面_findfirst中的泛式规则Q查找下一个符合该泛式的文Ӟq以 此ؓ依据修改fileinfo中的?br /> 头文?: #include <io.h>
参 ??: long handle 搜烦句柄(通常q靠其前的_findfirst()q回)
   fileinfo 文g信息buffer
q回?: 成功q回0
   出错q回-1,且设|errno为如下?br />    ENOENT 没有更多的符合该泛式的文?/p>


7 . char *_getcwd( char *buffer, int maxlen );
功 ??: 获得当前工作目录.
头文?: #include <direct.h>
q回?: 成功q回指向buffer的pointer
   p|q回NULLQ且讄errnoZ下三个g一:
   ENODEV 无该讑֤
   ENOMEM 内存不够
   ERANGE l果出范围
注 ??: 当第一个参Cؓ NULL ?W二个参?maxlen 长度讄无效,且函C用malloc分配_内存,需要将函数q回g递给free()函数来释攑ֆ?
   当第一个参C?NULL ?maxlen 指定长度不够函数q回?讄errno为ERANGE

8 . char *_getdcwd( int drive, char *buffer, int maxlen );
功 ??: 获得指定驱动器的当前工作路径.
头文?: #include <direct.h>
q回?: 成功q回指向buffer的pointer
   p|q回NULLQ且讄errnoZ下三个g一:
   ENODEV 无该讑֤
   ENOMEM 内存不够
   ERANGE l果出范围
注 ??: 当第一个参Cؓ NULL ?该函数设|errno为ERANGE

9 . int _getdrive( void );
功 ??: 获得当前盘驱动?
头文?: #include <direct.h>
q回?: q回驱动器?1<==>A 2<==>B 如此{等;函数不会出错!

10 . unsigned long _getdrives(void);
功 ??: 获得当前所有驱动器.
头文?: #include <direct.h>
q回?: 各个位代表对应驱动器,
   bit 0 <==> A
   bit 1 <==> B
   bit 2 <==> C
   ... ...
注:bit x 表示unsigned long的第x?/p>

11 . int _mkdir( const char *dirname );
功 ??: 创徏一个新目录,目录名ؓdirname.
头文?: #include <direct.h>
q回?: 成功q回0
   p|q回-1Q且讄errnoZ下三个g一
   EACCESS 权限不允?br />    EEXIST   该目录已存在
   ENOENT   无该文g或目?/p>

12 . int _rmdir( const char *dirname );
功 ??: 删除名ؓdirname的目?
头文?: #include <direct.h>
q回?: 成功q回0
   p|q回-1Q且讄errnoZ下三个g一
   EACCESS    权限不允?br />    ENOTEMPTY dirname不是文g?
      或者该文g夹不I?
      或者dirname为当前工作文件夹;
      或者dirname为当Ҏ件夹;
   ENOENT     无该文g或目?/p>

//--end--

//如有错误Q希望指?

//联系 : cppgp@163.com



听风 2009-03-30 00:00 发表评论
]]>
用Visual C++实现注册表简单操?/title><link>http://www.tkk7.com/tingfeng/articles/262259.html</link><dc:creator>听风</dc:creator><author>听风</author><pubDate>Thu, 26 Mar 2009 15:59:00 GMT</pubDate><guid>http://www.tkk7.com/tingfeng/articles/262259.html</guid><wfw:comment>http://www.tkk7.com/tingfeng/comments/262259.html</wfw:comment><comments>http://www.tkk7.com/tingfeng/articles/262259.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tingfeng/comments/commentRss/262259.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tingfeng/services/trackbacks/262259.html</trackback:ping><description><![CDATA[一、实现方?br /><br />   Ҏ册表的编E要用到句柄Q我们需要通过一个句柄访问注册表键|当打开或创Z个键值的时候,会返回一个该键的句柄Qƈ且调用和分析键和创徏键| 在分析和创徏的同旉要传递句柄到函数。WINDOWS提供预定义的用语---根一U键的保留句柄,? HKEY_CLASS_ROOT,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USER{,q些都是与注册表 的根键相对应q且同名的句柄。当讉K一个根键的时候,传递这些通用句柄。这׃用打开栚w啦,因ؓ他们L在打开状态下Q可使用默认键的句柄讉K?br /><br />   Win32 API提供了大U?5个有x册表的函敎ͼ他提供了Ҏ册表的读取,写入Q删除,以及打开注册表的所有函敎ͼq且可以实现Ҏ册表备䆾Q连接和对远端注? 表进行查看等功能。但是在~程的时候首先需要考虑你是在什么操作系l编辑此cȝ序,虽然微Y的操作系l,如NT和Windows98都是32位操作系l, 但是有些API函数中ƈ不支?8Q这Ҏ要注意的。APIl历和发展了很多q_有些函数已经重复Q比如RegSetValue()? RegSetValueEx()都是用来讄注册表键值的Q两者的区别在于前者是讄注册表键的默认|仅支持作为数据类型的字符?而后者不仅承了? 者的所有功能而且q能对多值或cdq行操作。一般APIҎ较新的函数都会在后缀q加"Ex"的同样名U函敎ͼ在编E中均应可能的使用高函数。下 面介l一些比较常用的操作注册表的API函数Q?br /><br />   1、RegCloseKey()<br /><br />   原型QRegCloseKey(HKEY hKey)<br /><br />   解释Q关闭指定的d表键Q释攑֏柄。当对一个或多个键或值操作完成以后,需要关闭其键来q行保存操作l果Q关闭一个键后,句柄变ؓ非法Q此时应释放句柄?br /><br />   2、RegCreateKeyEx()<br /><br />   原型QLONG RegCreateKeyEx( HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved,<br /> LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes,<br /> PHKEY phkResult, LPDWORD lpdwDisposition );<br /><br />   解释Q打开指定的键或子键。如果要打开的键不存在的话,本函C试图建立它。提供该函数是ؓ了向后兼宏V所有的WIN32应用E序应用函数RegCreateKeyExQ)。各参数及返回值的含义如下Q?br /><br />   各参数及q回值的含义如下Q?br /><br />   ·hKeyZ键|可以取下面的一些数|HKEY_CLASSES_ROOT、HKEY_CURRENT_CONFIG、   HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USER? HKEY_PERFORMANCE_DATA(WINNT操作pȝ)、HKEY_DYN_DATAQWIN9X操作pȝQ;<br /><br />   ·参数lpSubKeyZ个指向以零结字符串的指针Q其中包含将要创建或打开的子键的名称。子键不可以用反斜线Q\Q开始。该参数可以为NULLQ?br /><br />   ·参数ReservedZ留|必须讄?Q?br /><br />   ·参数lpClassZ个指向包含键cd的字W串。如果该键已l存在,则忽略该参数Q?br /><br />   ·参数dwOptions为新创徏的键讄一定的属性。可以取下面的一些数|  REG_OPTION_NON_VOLATILE Q表C新创徏的键Z个非短暂性的键(数据信息保存在文件中Q当pȝ重新启动Ӟ数据信息恢复Q;REG_OPTION_VOLATILEQ表C新创徏? 键ؓ一个短暂性的键(数据信息保存在内存中Q,Windows95忽略该数|REG_OPTION_BACKUP_RESTORE 仅在WINNT中支持,可以提供优先U支持;<br /><br />   ·参数samDesired用来讄寚w讉K的权限,可以取下面的一些数|KEY_CREATE_LINKQ表C准许生成符号键QKEY_CREATE_SUB_KEY 表示准许生成子键QKEY_ENUMERATE_SUB_KEYS 表示准许生成枚D子键QKEY_EXECUTE 表示准许q行L作;KEY_NOTIFY表示准许更换通告Q   KEY_QUERY_VALUE 表示准许查询子键QKEY_ALL_ACCESS 提供完全讉KQ是上面数值的l合Q?br /><br />   KEY_READ 是下面数值的l合QKEY_QUERY_VALUE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFYQ  KEY_SET_VALUE 表示准许讄子键的数|KEY_WRITE 是下面数值的l合QKEY_SET_VALUE、KEY_CREATE_SUB_KEYQ?br /><br />   ·参数lpSecurityAttributesZ个指向SECURITY_ATTRIBUTESl构的指针,定q回的句柄是否被子处理过Eѝ如果该参数为NULLQ则句柄不可以被l承。在WINNT中,该参数可以ؓ新创建的键增加安全的描述Q?br /><br />   ·参数phkResultZ个指向新创徏或打开的键的句柄的指针Q?br /><br />   ·参数lpdwDispition指明键是被创是被打开的,可以是下面的一些数|  REG_CREATE_NEW_KEY 表示键先前不存在Q现在被创徏QREG_OPENED_EXISTING_KEY 表示键先前已存在Q现在被打开?br /><br />   如果该函数调用成功,则返回ERROR_SUCCESS。否则,q回gؓ文gWINERROR.h中定义的一个非零的错误代码Q可以通过讄 FORMAT_MESSAGE_FROM_SYSTEM标识调用FormatMessageQ)函数来获取一个对错误的M描述?br /><br />   3、RegOpenKeyExQ)<br /><br />   原型QLONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions,<br /> REGSAM samDesired, PHKEY phkResult );<br /><br />   解释Q打开一个指定的键,q返回打开键的句柄?br /><br />   各参数及q回值的含义如下Q?br /><br />   ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数Q?br /><br />   ·参数lpSubKeyZ个指向以零结字符串的指针Q其中包含子键的名称Q可以利用反斜线Q\Q分隔不同的子键名。如果字W串为空Q则ҎhKey参数创徏一个新的句柄。在q种情况下,q不关闭先前打开的句柄;<br /><br />   ·参数ulOption保留Q通常必须讄?Q?br /><br />   ·参数samDesired的含义同RegCreateKeyEx函数中的samDesired参数Q?br /><br />   ·参数phkResultZ个指针,用来指向打开的键的句柄。可以通过RegCloseKey函数关闭q个句柄Q?br /><br />   ·函数的返回值同RegCreateKeyEx函数的返回倹{?br /><br />   4?查询某一个键|RegQueryValueExQ)<br /><br />   原型QLONG RegQueryValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD pReserved, LPDWORD lpType,<br /> LPBYTE lpData, LPDWORD lpcbData );<br /><br />   解释Q根据要查询的键的句柄,要返回的查询的数据?br /><br />   各个参数及返回值的含义如下Q?br /><br />   ·参数hKey为当前的一个打开的键的句柄,具体数值同RegCreateKeyEx函数的hKey参数Q?br /><br />   ·参数lpVauleNameZ个指向非I的包含查询值的名称的字W串指针Q?br /><br />   ·参数lpReserved保留Q必MؓNULLQ?br /><br />   ·参数lpTypeZ个指向数据类型的指针Q数据类型ؓ下列cd之一QREG_BINARY 二进制数据、REG_DWORD 32位整数、REG_DWORD_LITTLE_ENDIAN littleQendian格式的数据,例如0X12345678以(0X78 0X56 0X34 0X12Q方式保存、REG_DWORD_BIG_ENDIAN bigQendian格式的数据,例如0X12345678以(0X12 0X34 0X56 0X78Q方式保存、REG_EXPAND_SZ 一个包含未扩展环境变量的字W串、REG_LINK 一个Unicodecd的链接、REG_MULIT_SZ 以两个零l尾的字W串、REG_NONE 无类型数倹{REG_RESOURCE_LIST 讑֤驱动资源列表、REG_SZ 一个以零结字符串根据函C用的字符集类型的不同而设|ؓUnicode或ANSIcd的字W串Q?br /><br />   ·参数lpDataZ个指向保存返回值的变量的指针。如果不需要返回|该参数可以ؓNULLQ?br /><br />   ·参数lpcbDataZ个指向保存返回值长度的变量的指针。其中长度以字节为单位。如果数据类型ؓREG_SZ、REG_MULTI_SZ? REG_EXPAND_SZQ那么长度也包括l尾的零字符Q只有在参数lpData为NULLӞ参数lpcbData才可以ؓNULLQ返回值同 RegCreateKeyEx函数的返回|<br /><br />   5、RegSetValueExQ)<br /><br />   原型QLONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, DWORD dwType,<br /> const BYTE *lpData, DWORD cbData);<br /><br />   解释Q设|注册表中的一个键倹{?br /><br />   各个参数及返回值的含义如下Q?br /><br />   ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数Q?br /><br />   ·参数lpValueNameZ个指向包含值名的字W串指针QReserved保留Q通常必须讄?Q?br /><br />   ·参数dwType定了设|的值的cd同RegQueryValueKeyEx的lyType参数Q?br /><br />   ·参数lpDataZ个指向包含数据的~冲区的指针Q?br /><br />   ·参数cbData以字节ؓ单位Q指定数据的长度Q?br /><br />   q回值同RegCreateKeyEx函数的返回倹{?br /><br />   6、RegDeketeKeyQ)<br /><br />   原型QLONG RegDeleteKeyQHKEY hKeyQLPCTSTR lpSubKEYQ;<br /><br />   解释Q函数RegDeketeKey删除一个键及所有的子键?br /><br />   各个参数及返回值的含义如下Q?br /><br />   ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数Q?br /><br />   ·参数lpSubKey的含义同RegCreateKeyEx函数中的lpSubKey参数。  <img src ="http://www.tkk7.com/tingfeng/aggbug/262259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tingfeng/" target="_blank">听风</a> 2009-03-26 23:59 <a href="http://www.tkk7.com/tingfeng/articles/262259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开机启动项http://www.tkk7.com/tingfeng/articles/262189.html听风听风Thu, 26 Mar 2009 10:25:00 GMThttp://www.tkk7.com/tingfeng/articles/262189.htmlhttp://www.tkk7.com/tingfeng/comments/262189.htmlhttp://www.tkk7.com/tingfeng/articles/262189.html#Feedback0http://www.tkk7.com/tingfeng/comments/commentRss/262189.htmlhttp://www.tkk7.com/tingfeng/services/trackbacks/262189.html【启动项目就是开机的时候系l会在前台或者后台运行的E序?br />   当WindowsQ操作系l)完成dq程Q进E表中出C很多的进E!Windows在启动的时候,自动加蝲了很多程序?br />   许多E序的自启动Q给我们带来了很多方便,q是不争的事实,但不是每个自启动的程序对我们都有用;更甚者,也许有病毒或木马在自启动行列Q?br />   其实Windows2000/XP中的自启动文Ӟ除了从以前系l中遗留下来的Autoexec.bat文g中加载外Q按照两个文件夹?个核心注册表子键来自动加载程序的?br />   【启动项分解】 
  1Q“启动”文件夹──最常见的自启动E序文g夏V?br />   它位于系l分区的“documents and SettingsQ->UserQ->〔开始〕菜单-Q?gt;E序”目录下。这时的User指的是登录的用户名?br />   2Q“All Users”中的自启动E序文g夹──另一个常见的自启动程序文件夹?br />   它位于系l分区的“documents and SettingsQ->All UserQ->〔开始〕菜单-Q?gt;E序”目录下。前面提到的“启动”文件夹q行的是d用户的自启动E序Q而“All Users”中启动的程序是在所有用户下都有效(不论你用什么用L录)?br />   3Q“Load”键值── 一个埋藏得较深的注册表键倹{?br />   位于〔HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\load〕主键下?br />   4Q“Userinit”键值──用户相关
  它则位于〔HKEY_LOCAL_MACHINE\Software\Microsoft \Windows NT\CurrentVersion\Winlogon\Userinit〕主键下Q也是用于系l启动时加蝲E序的。一般情况下Q其默认gؓ “userinit.exe”,׃该子键的g可用逗号分隔开多个E序Q因此,在键值的数g可加入其它程序?br />   5Q“Explorer\Run”键值──与“load”和“Userinit”两个键g同的是,“Explorer\Run”同时位于〔HKEY_CURRENT_USER〕和〔HKEY_LOCAL_MACHINE〕两个根键中?br />   它在两个中的位置分别为(HKEY_CURRENT_USER\Software \Microsoft\Windows\CurrentVersion\Policies\Explorer\Run〕和 〔HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies \Explorer\Run〕下?br />   6Q“RunServicesOnce”子键──它在用户d前及其它注册表自启动E序加蝲前面加蝲?br />   q个键同时位于〔HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\RunServicesOnce〕和〔HKEY_LOCAL_MACHINE\Software \Microsoft\Windows\CurrentVersion\RunServicesOnce〕下?br />   7Q“RunServices”子键──它也是在用户d前及其它注册表自启动E序加蝲前面加蝲?br />   q个键同时位于〔HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\RunServices〕和〔HKEY_LOCAL_MACHINE\Software \Microsoft\Windows\CurrentVersion\RunServices〕下?br />   8Q“RunOnce\Setup”子键──光认值是在用L录后加蝲的程序?br />   q个键同时位于〔HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\RunOnce\Setup〕和〔HKEY_LOCAL_MACHINE\Software \Microsoft\Windows\CurrentVersion\RunOnce\Setup〕下?br />   9Q“RunOnce”子键──许多自启动程序要通过RunOnce子键来完成第一ơ加载?br />   q个键同时位于〔HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\RunOnce〕和〔HKEY_LOCAL_MACHINE\Software\Microsoft \Windows\CurrentVersion\RunOnce〕下。位于〔HKEY_CURRENT_USER〕根键下的RunOnce子键在用L 录扣及其它注册表的Run键值加载程序前加蝲相关E序Q而位于〔HKEY_LOCAL_MACHINE〕主键下的Runonce子键则是在操作系l处理完 其它注册表Run子键及自启动文g夹内的程序后再加载的。在Windows XP中还多出一个〔HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion \RunOnceEX〕子键,光理相同?br />   10Q“Run”子键──目前最常见的自启动E序用于加蝲的地斏V?br />   q个键同时位于〔HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\Run〕和〔HKEY_LOCAL_MACHINE\Software\Microsoft \Windows\CurrentVersion\Run〕下?br />   其中位于〔HKEY_CURRENT_USER〕根键下的Run键值紧接着〔HKEY_LOCAL_MACHINE〕主键下的Run键值启动,但两个键值都是在“启动”文件夹之前加蝲?br />   11Q再者就是Windows中加载的服务了,它的U别较高Q用于最先加载?br />   其位于〔HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services〕下Q看C吗,你所有的pȝ服务加蝲E序都在q里了!
  12QWindows Shell──pȝ接口
  它位于〔HKEY_LOCAL_MACHINE\Software\Microsoft \Windows NT\CurrentVersion\Winlogon\〕下面的Shell字符串类型键gQ基默认gؓExplorer.exeQ当然可能木马程序会 在此加入自nq以木马参数的Ş式调用资源管理器Q以辑ֈƺ骗用户的目的?br />   13QBootExecute──属于启动执行的一个项?
  可以通过它来实现启动NatviceE序QNativeE序在驱动程序和pȝ核心加蝲后将被加载,此时会话理?smss.exe)q行windowsNT用户模式q开始按序启动nativeE序
  它位于注册表中〔HKEY_LOCAL_MACHINE\System \ControlSet001\Session Manager\〕下面,有一个名为BootExecute的多字符串值键Q它的默认值是"autocheck autochk *"Q用于系l启动时的某些自动检查。这个启动项目里的程序是在系l图形界面完成前p执行的,所以具有很高的优先U?br />   14Q策略组加蝲E序──打开Gpedit.mscQ展开“用户配|——管理模李쀔—系l——登录”,可以看到“在用户d时运行这些程序”的目Q你可以在里面添加?br />   在注册表中[HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\Group Policy Objects\本地User\Software\Microsoft\Windows\CurrentVersion\Policies \Explorer\Run]你也可以看到相对应的键倹{?br />   备注Q?br />   Home版的XP中没有提供gpedit工具Q可到网上搜索ƈ下蝲补丁?br />   快速进入启动项
  快速进入启动项的方法是在运行中输入 msconfig Q即可看到窗口下的启动项q行目?br />   [~辑本段]从系l的启动可以看C?br />   俗话说“万事开头难”, 俗话也说“良好的开头是成功的一半”,那么XPpȝ“开头”也是“启动”能告诉我们什么那?br />   1、msconfig
  ?开始?“运行”对话框中输入“msconfig”就打开“系l配|实用程序”?br />   msconfig是Windowspȝ中的“系l配|实用程序”,它可以自动执行诊断xppȝ 的配|问题时所用的常规解决步骤。它的斚w可够宽,包括:一般(常规Q、system.ini、win.ini、BOOT.INI、服务、启动。它? xppȝ底层最先启动的E序Q可见它的重要性了。这里面可是自启动程序非常喜Ƣ呆的地斏V?br />   q里我们只介l一下“启动?br />   pȝ配置实用E序中的“启动”选项和我们在下面讲的"启动"文g夹ƈ不是同一个东西,在系l配|实用程序中的这个启动项目是Windowspȝ启动目的集合地Q几乎所有的启动目部能在这里找?---当然Q经q特D编E处理的E序可以通过另外的方法不在这里显C?br />   打开“启动”标{,“启动项目”中|列的是开机启动程序的名称Q“命令”下是具体的E序附加命oQ最后的"位置"是该程序在注册表中的相应位|了Q你可以对可疑的E序q行详细的\径、命令检查,一旦发现错误,可以用下方?用"来禁止该E序开机时候的加蝲?br />   一般来讲所有我们可见的E序的列表,你完全可以通过它来理你的启动E序Q换句话Q这里可以全部是I的?br />   2、注册表中相应的启动加蝲目
  注册表的启动目是病毒和木马E序的最爱,非常多的病毒木马的顽固性就是通过注册表来实现的,特别是在安装了新的Y件程序,一定不要被E序漂亮的外表迷惑,一定要看清楚它的实质是不是木马的伪装外x者是捆绑E序Q必要的时候可以根据备份来恢复注册表?br />   我们也可以通过手动的方法来查注册表中相应的位置Q注意同安全、清z的pȝ注册表相应键q行比较Q如果发C一致的地方Q一定要弄清楚它是什么东?不要怿写在外面?“system”?br />   “windows”、“programfiles”等名称Q尤其是如果你仔l观察的话,有些字符是不一LQ比?和o的区别,1和l的区别等Q如果经q详l的比较Q可以确定它是不明程序的话,不要手YQ马上删除?br />   主要的启动加载键值有
  “Explorer\Run”键值──在HKEY_CURRENT_USER \Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run〕和 〔HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies \Explorer\Run〕下?br />   “RunServicesOnce”子键──? 〔HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion \RunServicesOnce〕和〔HKEY_LOCAL_MACHINE\Software\Microsoft\Windows \CurrentVersion\RunServicesOnce〕下?br />   “RunServices”子键──? 〔HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion \RunServices〕和〔HKEY_LOCAL_MACHINE\Software\Microsoft\Windows \CurrentVersion\RunServices〕下?br />   “RunOnce”子键──在〔HKEY_CURRENT_USER\Software \Microsoft\Windows\CurrentVersion\RunOnce〕和〔HKEY_LOCAL_MACHINE\Software \Microsoft\Windows\CurrentVersion\RunOnce〕下?br />   “Run”子键──?br />   〔HKEY_CURRENT_USER\Software\Microsoft \Windows\CurrentVersion\Run〕和〔HKEY_LOCAL_MACHINE\Software\Microsoft \Windows\CurrentVersion\Run〕下?br />   3、“启动”项?br />   在windows的“开始”中有自带的启动文g夹,它是最常见的启动项目。如果在安装E序时设|成开机既启动Q这个程序就装入到这个文件夹中,pȝ启动׃自动地加载相应程序?br />   具体的位|是“开始”菜单中的“所有程序?“启动”选项?br />   在硬盘上的位|是QC:\Documents and Settings\你的用户名\「开始」菜单\E序\启动?
  在注册表中的位置是:
  HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run?br />   q里最好ؓI,而且用户要不时地查一下这里有什么不明的东西?
  4、boot.ini
  当用L电脑有ghost备䆾、dos工具或者是双系l时Q在开机后出C让用户选择Q如果不选择׃默认的启动的H口Q?屏幕底部是F8高启动Q,boot.ini控制这个地斏V?br />   里边的内容一般是
  timeout=x Qx一般在1-5可以了Q?br />   default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
  [operating systems]
  multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect………?
  BOOT.INI是一个非帔R要的pȝ文gQ是pȝ启动Ӟ需要查询的一个系l文Ӟ它告诉启 动程序本计算机有几个操作pȝ、各pȝ的位|在哪里{信息。没有它或者误删了Q系l还能进行引|但是一个是只能引导默认的系l,不在有你的备份系l的? 导选择Q在一个是每次开机重启时都显CZ行字Q“boot.ini文g是非法的Q现在正从C:/Windows/下启动”,但是速度明显慢了。所以我们^ 旉了要对其作必要的备䆾之外Q还要编辑它的方法。特别是在安装多pȝӞ如果没有按照从低到高(Windows 98、Windows 2000、Windows XP、Windows 2003)的安装顺序,该文件往往会被损坏。如果我们掌握修改和~辑它的办法Q就不会到时候无计可施了?br />   5、非法关Z后的“启动?br />   怿很多人都到q电脑开机后出现
  “Checking file system on E:
  The type of the file system is NTFS……然后是一些数字的变化Q最后一行是cM的??Q问号代表数字) allocation units available on disk”,然后p入系l桌面了”的情况吧?br />   q就是非正常x,如断c按热启动键启动、或强制按电源键x在开机造成的?br />   ׃x的时候E盘里面的E序q在q行Q每ơ开机硬盘都会自动自Q消除错误信息等Q而如果非正常xq些E序没有正常退出,那么下次在开机电脑就要从新执行自Q以便消除消除错误信息,正常的电脑有一ơ就好了Q下ơ启动就不会出现q种情况了?br />   如果每次开机都出现q样的情冉|2个可能:一个是盘出现坏道了,盘在工作时H然关闭甉|Q? 可能会导致磁头与盘片猛烈擦而损坏硬盘,q会使磁头不能正复位而造成盘的划伤,从而在盘留下了坏道,但是电脑q能勉强使用Q出现这U情况一般只? 更换盘了。一个是盘没有问题Q但是留下了记忆的信息,l果每次都自Q消除的办法是Q开?q行中输入chkdsk E: /x/f 回RQ然后就出现个自动运行的dosH口Q等他运行完毕就没有问题了?br />   chkdsk E: /x /f的意思是Windows发现在E盘里文gpȝ有问?Q运行CHKDSK <使用选项/x /f> 来更正这些问??br />   对于FAT文gpȝQ可以用win自己的磁盘修复来操作Q方法是Q右M要操作的盘符Q属?工具Q选择查错Q把自动修复错误的勾打上Q点d始就可以了?br />   6、其他情늚“启动?br />   当用h开甉|开兛_从“启动”到q入桌面以及可以d|络后,如果p的时间很长,而且? 开、关闭、拖动一个程序文件的时候显得拖拖拉拉的Q有时候还有莫名其妙的从“启动”,q样的“启动”往往说明Q(1Q加载的启动目q多Q(2Q电脑中? 了,(3)pȝ盘的I间不了,Q?Q机p打扫一下了Q(5Q有关的g性能Ơ佳了…?br />


听风 2009-03-26 18:25 发表评论
]]>
文gdhttp://www.tkk7.com/tingfeng/articles/261578.html听风听风Mon, 23 Mar 2009 13:08:00 GMThttp://www.tkk7.com/tingfeng/articles/261578.htmlhttp://www.tkk7.com/tingfeng/comments/261578.htmlhttp://www.tkk7.com/tingfeng/articles/261578.html#Feedback0http://www.tkk7.com/tingfeng/comments/commentRss/261578.htmlhttp://www.tkk7.com/tingfeng/services/trackbacks/261578.htmlfseek   函数? fseek
  ?? 重定位流上的文g指针
  ?? int fseek(FILE *stream, long offset, int fromwhere);
  ?q? 函数讄文g指针stream的位|。如果执行成功,stream指向以fromwhere为基准,偏移offset个字节的位置。如果执行失?比如offset过文g自n大小)Q则不改变stream指向的位|?br />   q回? 成功Q返?Q否则返回其他倹{?br />   E序?
  #include <stdio.h>
  long filesize(FILE *stream);
  int main(void)
  {
  FILE *stream;
  stream = fopen("MYFILE.TXT", "w+");
  fprintf(stream, "This is a test");
  printf("Filesize of MYFILE.TXT is %ld bytes\n", filesize(stream));
  fclose(stream);
  return 0;
  }
  long filesize(FILE *stream)
  {
  long curpos, length;
  curpos = ftell(stream);
  fseek(stream, 0L, SEEK_END);
  length = ftell(stream);
  fseek(stream, curpos, SEEK_SET);
  return length;
  }
  int fseek( FILE *stream, long offset, int origin );
  W一个参数stream为文件指?br />   W二个参数offset为偏U量Q整数表C正向偏U,负数表示负向偏移
  W三个参数origin讑֮从文件的哪里开始偏U?可能取gؓQSEEK_CUR?SEEK_END ?SEEK_SET
  SEEK_CURQ?当前位置
  SEEK_ENDQ?文gl尾
  SEEK_SETQ?文g开?br />   其中SEEK_CURQSEEK_END和SEEK_SET依次?Q???br />

fread

  C语言库函数名: fread
  ?? 从一个流中读数据
  函数原型: int fread(void *ptr, int size, int nitems, FILE *stream);
  ?敎ͼ用于接收数据的地址Q字W型指针Q(ptrQ?
  单个元素的大(sizeQ?
  元素个数QnitemsQ?br />   提供数据的文件指针(streamQ?br />   q回|成功d的元素个?br />   E序?
  #include <string.h>
  #include <stdio.h>
  int main(void)
  {
  FILE *stream;
  char msg[] = "this is a test";
  char buf[20];
  if ((stream = fopen("DUMMY.FIL", "w+"))
  == NULL)
  {
  fprintf(stderr,
  "Cannot open output file.\n");
  return 1;
  }
  /* write some data to the file */
  fwrite(msg, strlen(msg)+1, 1, stream);
  /* seek to the beginning of the file */
  fseek(stream, 0, SEEK_SET);
  /* read the data and display it */
  fread(buf, strlen(msg)+1, 1,stream);
  printf("%s\n", buf);
  fclose(stream);
  return 0;
  }


听风 2009-03-23 21:08 发表评论
]]>
fopen()和fclose()的用?/title><link>http://www.tkk7.com/tingfeng/articles/261323.html</link><dc:creator>听风</dc:creator><author>听风</author><pubDate>Sun, 22 Mar 2009 09:10:00 GMT</pubDate><guid>http://www.tkk7.com/tingfeng/articles/261323.html</guid><wfw:comment>http://www.tkk7.com/tingfeng/comments/261323.html</wfw:comment><comments>http://www.tkk7.com/tingfeng/articles/261323.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tingfeng/comments/commentRss/261323.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tingfeng/services/trackbacks/261323.html</trackback:ping><description><![CDATA[fopen()和fclose()的用?br />1Qfopen()函数的用?br />fopen函数用于打开文g, 其调用格式ؓ:<br />FILE *fopen(char *filename, *type);<br />fopen()函数中第一个Ş式参数表C文件名, 可以包含路径和文件名两部分。如:"B:TEST.DAT" "C:\\TC\\TEST.DAT"<br />注意Q如果将路径写成"C:\TC\TEST.DAT"是不正确? q一点要特别注意。fopen函数用来打开一个文Ӟ其调用的一般Ş式ؓQ?文g指针?fopen(文g名,使用文g方式)其中Q“文件指针名”必L被说明ؓFILE cd的指针变量,“文件名”是被打开文g的文件名。“用文件方式”是指文件的cd和操作要求。“文件名”是字符串常量或字符串数l。例如: <br />FILE *fpQ?br />fp=("file a","r");<br />其意义是在当前目录下打开文gfile aQ?只允许进行“读”操作,qfp指向该文件?br />又如Q?br />FILE *fphzk<br />fphzk=("c:\\hzk16',"rb")<br />其意义是打开C驱动器磁盘的根目录下的文件hzk16Q?q是一个二q制文gQ只允许按二q制方式q行L作?br />两个反斜U쀜\\ ”中的第一个表C{义字W,W二个表C根目录。用文件的方式共有12U,下面l出了它们的W号和意义?br />W二个Ş式参数表C打开文g的类型。关于文件类型的规定参见下表?<br />?文g操作cd<br />━━━━━━━━━━━━━━━━━━━━━━━━━━━━<br />字符                含义<br />────────────────────────────<br />"r"           打开文字文g只读<br />"w"           创徏文字文g只写<br />"a"           增补, 如果文g不存在则创徏一?br />"r+"          打开一个文字文件读/?br />"w+"          创徏一个文字文件读/?br />"a+"         打开或创Z个文件增?br />"b"           二进制文?可以和上面每一合?<br />"t"           文这文g(默认?<br />━━━━━━━━━━━━━━━━━━━━━━━━━━━━<br />文g使用方式        ??br />“rt”      只读打开一个文本文Ӟ只允许读数据 <br />“wt”      只写打开或徏立一个文本文Ӟ只允许写数据<br />“at”      q加打开一个文本文Ӟq在文g末尾写数?br />“rb”      只读打开一个二q制文gQ只允许L?br />“wb”       只写打开或徏立一个二q制文gQ只允许写数?br />“ab?      q加打开一个二q制文gQƈ在文件末ֆ数据<br />“rt+”      d打开一个文本文Ӟ允许d?br />“wt+”      d打开或徏立一个文本文Ӟ允许d<br />“at+”      d打开一个文本文Ӟ允许读,或在文g末追加数 ?br />“rb+”      d打开一个二q制文gQ允许读和写 <br />“wb+”      d打开或徏立一个二q制文gQ允许读和写<br />“ab+?     d打开一个二q制文gQ允许读Q或在文件末q加数据<br /><br />对于文g使用方式有以下几点说明:<br />1. 文g使用方式由r,w,a,t,bQ?六个字符拼成Q各字符的含义是Q?br />r(read): ?br />w(write): ?br />a(append): q加<br />t(text): 文本文gQ可省略不写<br />b(banary): 二进制文?br />+: d?br /><br />2. 凡用“r”打开一个文件时Q该文g必须已经存在Q?且只能从该文件读出?br />3. 用“w”打开的文件只能向该文件写入?若打开的文件不存在Q则以指定的文g名徏立该文gQ若打开的文件已l存在,则将该文件删去,重徏一个新文g?br />4. 若要向一个已存在的文件追加新的信息,只能用“a ”方式打开文g。但此时该文件必L存在的,否则会出错?br />5. 在打开一个文件时Q如果出错,fopen返回一个空指针值NULL。在E序中可以用q一信息来判别是否完成打开文g的工作,q作相应的处理。因此常用以下程序段打开文gQ?br />if((fp=fopen("c:\\hzk16","rb")==NULL)<br />{<br />printf("\nerror on open c:\\hzk16 file!");<br />getch();<br />exit(1);<br />}<br />q段E序的意义是Q如果返回的指针为空Q表CZ能打开C盘根目录下的hzk16文gQ则l出提示信息“error on open c:\ hzk16file!”,下一行getch()的功能是从键盘输入一个字W,但不在屏q上昄。在q里Q该行的作用是等待, 只有当用户从键盘敲Q一键时Q程序才l箋执行Q?因此用户可利用这个等待时间阅d错提C。敲键后执行exit(1)退出程序?br /><br />6. 把一个文本文件读入内存时Q要ASCII码{换成二进制码Q?而把文g以文本方式写入磁盘时Q也要把二进制码转换成ASCII码,因此文本文g的读写要p较多的{换时间。对二进制文件的d不存在这U{换?br /><br />7. 标准输入文g(键盘)Q标准输出文?昄?)Q标准出错输?出错信息)是由pȝ打开的,可直接用。文件关闭函敎ͽclose文件一旦用完毕,应用关闭文g函数把文件关闭, 以避免文件的数据丢失{错误?br />如果要打开一个CCDOS子目录中, 文g名ؓCLIB的二q制文g, 可写?<br />fopen("c:\\ccdos\\clib", "rb");<br />如果成功的打开一个文? fopen()函数q回文g指针,   否则q回I指?NULL)。由此可判断文g打开是否成功?br />2. fclose()函数<br />fclose()函数用来关闭一个由fopen()函数打开的文?, 其调用格式ؓ:<br />nt fclose(FILE *stream);<br />该函数返回一个整型数。当文g关闭成功? q回0, 否则q回一个非零倹{可以根据函数的q回值判断文件是否关闭成功?br />例子Q?br />FILE *fpOut=fopen(“c:\\a.txt?”wt+?;<br />Int a=1;<br />Fprintf(fpOut,?d?a);<br />Fclose(fpOut);<br />                <br /><br /><img src ="http://www.tkk7.com/tingfeng/aggbug/261323.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tingfeng/" target="_blank">听风</a> 2009-03-22 17:10 <a href="http://www.tkk7.com/tingfeng/articles/261323.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++字符串处理函?/title><link>http://www.tkk7.com/tingfeng/articles/261266.html</link><dc:creator>听风</dc:creator><author>听风</author><pubDate>Sat, 21 Mar 2009 14:55:00 GMT</pubDate><guid>http://www.tkk7.com/tingfeng/articles/261266.html</guid><wfw:comment>http://www.tkk7.com/tingfeng/comments/261266.html</wfw:comment><comments>http://www.tkk7.com/tingfeng/articles/261266.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/tingfeng/comments/commentRss/261266.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/tingfeng/services/trackbacks/261266.html</trackback:ping><description><![CDATA[ <p> <b>1、strcpy(char destination[], const char source[]);</b> </p> <p> <strong>strcpyQ?/strong>字W串source拯到字W串destination中?br /> strcpy函数应用举例<br /> 原型Qstrcpy(char destination[], const char source[]);<br /> 功能Q将字符串source拯到字W串destination?br /> 例程Q?</p> <p> #include <iostream.h><br /> #include <string.h><br /> void main(void)<br /> {<br />   char str1[10] = { "TsinghuaOK"};<br />   char str2[10] = { "Computer"};<br />   cout <<strcpy(str1,str2)<<endl;<br /> }</p> <p>q行l果?Computer</p> <p>W二个字W串覆盖掉W一个字W串的所有内容!</p> <p>注意Q在定义数组Ӟ字符数组1的字W串长度必须大于或等于字W串2的字W串长度。不能用赋D句将一个字W串帔R或字W数l直接赋l一个字W数l。所有字W串处理函数都包含在头文件string.h中?/p> <p> <b> <br /> 2、strncpy(char destination[], const char source[], int numchars);</b> </p> <p> <strong>strncpyQ?/strong>字W串source中前numchars个字W拷贝到字符串destination中?br /> strncpy函数应用举例<br /> 原型Qstrncpy(char destination[], const char source[], int numchars);<br /> 功能Q将字符串source中前numchars个字W拷贝到字符串destination?br /> 例程Q?</p> <p>#include <iostream.h><br /> #include <string.h><br /> void main(void)<br /> {<br />   char str1[10] = { "Tsinghua "};<br />   char str2[10] = { "Computer"};<br />   cout <<strncpy(str1,str2,3)<<endl;<br /> }</p> <p>q行l果QComnghua</p> <p>注意Q字W串source中前numchars个字W将覆盖掉字W串destination中前numchars个字W!</p> <p> <b>3、strcat(char target[], const char source[]);</b> </p> <p> <strong>strcat:</strong>字W串source接到字符串target的后面?br /> strcat函数应用举例<br /> 原型Qstrcat(char target[], const char source[]);<br /> 功能Q将字符串source接到字符串target的后?br /> 例程Q?/p> <p>#include <iostream.h><br /> #include <string.h><br /> void main(void)<br /> {<br />   char str1[] = { "Tsinghua "};<br />   char str2[] = { "Computer"};<br />   cout <<strcpy(str1,str2)<<endl;<br /> }</p> <p>q行l果QTsinghua Computer</p> <p>注意Q在定义字符数组1的长度时应该考虑字符数组2的长度,因ؓq接后新字符串的长度Z个字W串长度之和。进行字W串q接后,字符?的结自动被LQ在l尾串末保留新字符串后面一个结?<br /><br /><b>4、strncat(char target[], const char source[], int numchars);</b></p> <p> <strong>strncat:</strong>字W串source的前numchars个字W接到字W串target的后面?br /> strncat函数应用举例Q?br /> 原型Qstrncat(char target[], const char source[], int numchars);<br /> 功能Q将字符串source的前numchars个字W接到字W串target的后?br /> 例程Q?/p> <p>#include <iostream.h><br /> #include <string.h><br /> void main(void)<br /> {<br />   char str1[] = { "Tsinghua "};<br />   char str2[] = { "Computer"};<br />   cout <<strncat(str1,str2,3)<<endl;<br /> }</p> <p>q行l果QTsinghua Com</p> <p> <br /> <b>5、int strcmp(const char firststring[], const char secondstring);</b> </p> <p> <strong>strcmpQ?/strong>比较两个字符串firststring和secondstring?br /> strcmp函数应用举例<br /> 原型Qint strcmp(const char firststring[], const char secondstring);<br /> 功能Q比较两个字W串firststring和secondstring<br /> 例程Q?</p> <p>#include <iostream.h><br /> #include <string.h><br /> void main(void)<br /> {<br />   char buf1[] = "aaa";<br />   char buf2[] = "bbb";<br />   char buf3[] = "ccc";<br />   int ptr; <br />   ptr = strcmp(buf2,buf1); <br />   if(ptr > 0)<br />    cout <<"Buffer 2 is greater than buffer 1"<<endl;<br />   else <br />    cout <<"Buffer 2 is less than buffer 1"<<endl;<br />   ptr = strcmp(buf2,buf3); <br />   if(ptr > 0)<br />    cout <<"Buffer 2 is greater than buffer 3"<<endl;<br />   else <br />    cout <<"Buffer 2 is less than buffer 3"<<endl;<br /> }</p> <p>q行l果?Buffer 2 is less than buffer 1 <br />                   Buffer 2 is greater than buffer 3</p> <p> <b>6、strlen( const char string[] );</b> </p> <p> <strong>strlenQ?/strong>l计字符串string中字W的个数。  <br /> strlen函数应用举例<br /> 原型Qstrlen( const char string[] );<br /> 功能Q统计字W串string中字W的个数<br /> 例程Q?</p> <p>#include <iostream.h><br /> #include <string.h><br /> void main(void)<br /> {<br />   char str[100]; <br />   cout <<"误入一个字W串:";<br />   cin >>str;<br />   cout <<"The length of the string is :"<<strlen(str)<<"?<<endl;<br /> }</p> <p>q行l果The length of the string is x (xZ输入的字WL?</p> <p>注意Qstrlen函数的功能是计算字符串的实际长度Q不包括'\0'在内。另外,strlen函数也可以直接测试字W串帔R的长度,如:strlen("Welcome")? </p> <img src ="http://www.tkk7.com/tingfeng/aggbug/261266.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/tingfeng/" target="_blank">听风</a> 2009-03-21 22:55 <a href="http://www.tkk7.com/tingfeng/articles/261266.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CString 操作指南http://www.tkk7.com/tingfeng/articles/261265.html听风听风Sat, 21 Mar 2009 14:49:00 GMThttp://www.tkk7.com/tingfeng/articles/261265.htmlhttp://www.tkk7.com/tingfeng/comments/261265.htmlhttp://www.tkk7.com/tingfeng/articles/261265.html#Feedback0http://www.tkk7.com/tingfeng/comments/commentRss/261265.htmlhttp://www.tkk7.com/tingfeng/services/trackbacks/261265.html
译Q?a href="mailto:littleloach@sina.com">littleloach

原文出处Q?a target="_blank" >codeprojectQCString Management


通过阅读本文你可以学习如何有效地使用 CString?br />
  CString 是一U很有用的数据类型。它们很大程度上化了MFC中的许多操作Q得MFC在做字符串操作的时候方便了很多。不怎样Q用CString有很多特D? 的技巧,特别是对于纯C背景下走出来的程序员来说有点难以学习。这文章就来讨些技巧?br />   使用CString可以让你对字W串的操作更加直截了当。这文章不是CString的完全手册,但囊括了大部分常见基本问题?br />
q篇文章包括以下内容Q?/p>

  1. CString 对象的连?/a>

  2. 格式化字W串Q包?int 型{化ؓ CString Q?/a>
  3. CString 型{化成 int ?/a>
  4. CString 型和 char* cd的相互{?/a>
  5. char* 转化?CString
  6. CString 转化?char* 之一Q用LPCTSTR强制转化
  7. CString 转化?char* 之二Q用CString对象的GetBufferҎ
  8. CString 转化?char* 之三: 和控件的接口
  9. CString 型{化成 BSTR ?/a>Q?/li>
  10. BSTR 型{化成 CString ?/a>Q?/li>
  11. VARIANT 型{化成 CString ?/a>Q?/li>
  12. 载入字符串表资源Q?/li>
  13. CString 和时对?/a>Q?/li>
  14. CString 的效?/a>Q?/li>
  15. ȝ

下面我分别讨论?br />
1?b>CString cat("Cat");
CString graycat = gray + cat;

要比用下面的Ҏ好得多:

char gray[] = "Gray";
char cat[] = "Cat";
char * graycat = malloc(strlen(gray) + strlen(cat) + 1);
strcpy(graycat, gray);
strcat(graycat, cat);

2?b>格式化字W串

  与其?sprintf() 函数?wsprintf() 函数来格式化一个字W串Q还不如?CString 对象的Format()ҎQ?/p>

CString s;
s.Format(_T("The total is %d"), total);

  用这U方法的好处是你不用担心用来存放格式化后数据的缓冲区是否_大,q些工作由CStringcL你完成?br />   格式化是一U把其它不是字符串类型的数据转化为CStringcd的最常用技巧,比如Q把一个整数{化成CStringcdQ可用如下方法:

CString s;
s.Format(_T("%d"), total);

  我LҎ的字W串使用_T()宏,q是Z让我的代码至有Unicode的意识,当然Q关于Unicode的话题不在这文章的讨论范围。_T()宏在8位字W环境下是如下定义的Q?/p>

#define _T(x) x // 非Unicode版本Qnon-Unicode versionQ?/pre>

而在Unicode环境下是如下定义的:

#define _T(x) L##x // Unicode版本QUnicode versionQ?/pre>

所以在Unicode环境下,它的效果q当于Q?/p>

s.Format(L"%d", total);

   如果你认Z的程序可能在Unicode的环境下q行Q那么开始在意用 Unicode ~码。比如说Q不要用 sizeof() 操作W来获得字符串的长度Q因为在Unicode环境下就会有2倍的误差。我们可以用一些方法来隐藏Unicode的一些细节,比如在我需要获得字W长? 的时候,我会用一个叫做DIM的宏Q这个宏是在我的dim.h文g中定义的Q我会在我写的所有程序中都包含这个文Ӟ

#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )
  q个宏不仅可以用来解决Unicode的字W串长度的问题,也可以用在编译时定义的表gQ它可以获得表格的项敎ͼ如下Q?br />
class Whatever { ... };
Whatever data[] = {
{ ... },
...
{ ... },
};
for(int i = 0; i < DIM(data); i++) // 扫描表格L匚wV?br />
  q里要提醒你的就是一定要注意那些在参C需要真实字节数的API函数调用Q如果你传递字W个数给它,它将不能正常工作。如下:
TCHAR data[20];
lstrcpyn(data, longstring, sizeof(data) - 1); // WRONG!
lstrcpyn(data, longstring, DIM(data) - 1); // RIGHT
WriteFile(f, data, DIM(data), &bytesWritten, NULL); // WRONG!
WriteFile(f, data, sizeof(data), &bytesWritten, NULL); // RIGHT

造成以上原因是因为lstrcpyn需要一个字W个C为参敎ͼ但是WriteFile却需要字节数作ؓ参数?br /> 同样需要注意的是有时候需要写出数据的所有内宏V如果你仅仅只想写出数据的真实长度,你可能会认ؓ你应该这样做Q?/p>

WriteFile(f, data, lstrlen(data), &bytesWritten, NULL); // WRONG

但是在Unicode环境下,它不会正常工作。正的做法应该是这P

WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &bytesWritten, NULL); // RIGHT

  因ؓWriteFile需要的是一个以字节为单位的长度。(可能有些Z想“在非Unicode的环境下q行q行代码Q就意味着L在做一个多余的? 1操作Q这样不会降低程序的效率吗?”这U想法是多余的,你必要了解~译器实际上做了什么,没有哪一个C或C++~译器会把这U无聊的?操作留在代码 中。在Unicode环境下运行的时候,你也不必担心那个?操作会降低程序的效率Q记住,q只是一个左UM位的操作而已Q编译器也很乐意Z做这U替 换。)
  使用_T宏ƈ不是意味着你已l创Z一个Unicode的程序,你只是创Z一个有Unicode意识的程序而已。如果你在默认的8-bit模式下编 译你的程序的话,得到的将是一个普通的8-bit的应用程序(q里?-bit指的只是8位的字符~码Qƈ不是?位的计算机系l)Q当你在 Unicode环境下编译你的程序时Q你才会得到一个Unicode的程序。记住,CString ?Unicode 环境下,里面包含的可都是16位的字符哦?br />
3?b>CString decimal = _T("4011");
ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));

4?b>

或者这P

CString graycat("Gray" + "Cat");

  事实上,~译器将抱怨上面的q些试。ؓ什么呢Q因为针对CString ?LPCTSTR数据cd的各U各Ll合Q?+?q算W? 被定义成一个重载操作符。而不是两?LPCTSTR 数据cdQ它是底层数据类型。你不能对基本数据(?int、char 或?char*Q类型重?C++ 的运符。你可以象下面这样做Q?/p>

CString graycat = CString("Gray") + CString("Cat");

或者这P

CString graycat = CString("Gray") + "Cat";

研究一番就会发玎ͼ?+”L使用在至有一?CString 对象和一? LPCSTR 的场合?br />
注意Q编写有 Unicode 意识的代码L一件好事,比如Q?/p>

CString graycat = CString(_T("Gray")) + _T("Cat");

q将使得你的代码可以直接UL?br />
char* 转化?CString

  现在你有一?char* cd的数据,或者说一个字W串。怎么样创?CString 对象呢?q里有一些例子:

char * p = "This is a test";

或者象下面q样更具?Unicode 意识Q?/p>

TCHAR * p = _T("This is a test")

?/p>

LPTSTR p = _T("This is a test");

你可以用下面Q意一U写法:

CString s = "This is a test"; // 8-bit only
CString s = _T("This is a test"); // Unicode-aware
CString s("This is a test"); // 8-bit only
CString s(_T("This is a test")); // Unicode-aware
CString s = p;
CString s(p);

  用这些方法可以轻村ְ帔R字符串或指针转换?CString。需要注意的是,字符的赋值L被拷贝到 CString 对象中去的,所以你可以象下面这h作:

TCHAR * p = _T("Gray");
CString s(p);
p = _T("Cat");
s += p;

l果字符串肯定是“GrayCat”?br />
CString c还有几个其它的构造函敎ͼ但是q里我们不考虑它,如果你有兴趣可以自己查看相关文档?br />
事实上,CString cȝ构造函数比我展C的要复杂,比如Q?/p>

CString s = "This is a test"; 

  q是很草率的~码Q但是实际上它在 Unicode 环境下能~译通过。它在运行时调用构造函数的 MultiByteToWideChar 操作?8 位字W串转换?16 位字W串。不怎样Q如?char * 指针是网l上传输?8 位数据,q种转换是很有用的?br />
CString 转化?char* 之一Q?/b>强制cd转换?LPCTSTRQ?br />
  q是一U略微硬性的转换Q有关“正”的做法Qh们在认识上还存在许多混ؕQ正的使用Ҏ有很多,但错误的使用Ҏ可能与正的使用Ҏ一样多?br />   我们首先要了?CString 是一U很Ҏ?C++ 对象Q它里面包含了三个|一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字W记C及一个缓冲区长度? 有效字符数的大小可以是从0到该~冲最大长度值减1之间的Q何数Q因为字W串l尾有一个NULL字符Q。字W记数和~冲区长度被巧妙隐藏?br />   除非你做一些特D的操作Q否则你不可能知道给CString对象分配的缓冲区的长度。这P即你获得了?~冲的地址Q你也无法更改其中的内容Q不能截短字W串Q也 l对没有办法加长它的内容Q否则第一旉׃看到溢出?br />   LPCTSTR 操作W(或者更明确地说是 TCHAR * 操作W)?CString cM被重载了Q该操作W的定义是返回缓冲区的地址Q因此,如果你需要一个指?CString ? 字符串指针的话,可以q样做:

CString s("GrayCat");
LPCTSTR p = s;

  它可以正地q行。这是由C语言的强制类型{化规则实现的。当需要强制类型{化时QC++规测容许q种选择。比如,你可以将QQҎQ定义ؓ某个复? Q有一ҎQҎQ进行强制类型{换后只返回该复数的第一个QҎQ也是其实部)。可以象下面q样Q?/p>

Complex c(1.2f, 4.8f);
float realpart = c;

如果(float)操作W定义正的话,那么实部的的值应该是1.2?br />   q种强制转化适合所有这U情况,例如QQ何带?LPCTSTR cd参数的函数都会强制执行这U{换? 于是Q你可能有这样一个函敎ͼ也许在某个你买来的DLL中)Q?/p>

BOOL DoSomethingCool(LPCTSTR s);

你象下面q样调用它:

CString file("c:\\myfiles\\coolstuff")
BOOL result = DoSomethingCool(file);

  它能正确q行。因?DoSomethingCool 函数已经说明了需要一?LPCTSTR cd的参敎ͼ因此 LPCTSTR 被应用于该参敎ͼ?MFC 中就是返回的串地址?br />
如果你要格式化字W串怎么办呢Q?/p>

CString graycat("GrayCat");
CString s;
s.Format("Mew! I love %s", graycat);

  注意׃在可变参数列表中的|在函数说明中是以?..”表C的Qƈ没有隐含一个强制类型{换操作符。你会得C么结果呢Q?br />   一个o人惊讶的l果Q我们得到的实际l果串是Q?/p>

"Mew! I love GrayCat"?/pre>

  因ؓ MFC 的设计者们在设?CString 数据cd旉常小心, CString cd表达式求值后指向了字W串Q所以这里看不到M? Format ?sprintf 中的强制cd转换Q你仍然可以得到正确的行为。描q?CString 的附加数据实际上?CString 名义地址之后?br />   有一件事情你是不能做的,那就是修改字W串。比如,你可能会试用?”代曎?”(不要做这LQ如果你在乎国际化问题,你应该用十q制转换? National Language Support Ҏ,Q,下面是个单的例子Q?/p>

CString v("1.00"); // 货币金额Q两位小?br />LPCTSTR p = v;
p[lstrlen(p) - 3] = '','';

  q时~译器会报错Q因Z赋g一个常量串。如果你做如下尝试,~译器也会错Q?/p>

strcat(p, "each");

  因ؓ strcat 的第一个参数应该是 LPTSTR cd的数据,而你却给了一?LPCTSTR?br />
  不要试图钻这个错误消息的牛角,q只会你自己陷入麻烦!

  原因是缓冲有一个计敎ͼ它是不可存取的(它位?CString 地址之下的一个隐藏区域)Q如果你改变q个Ԍ~冲中的字符计数不会反映所做的修改。此外,如果字符串长度恰好是该字W串物理限制的长度(梢后q会讲到q? 个问题)Q那么扩展该字符串将改写~冲以外的Q何数据,那是你无权进行写操作的内存(不对吗?Q,你会毁换坏不属于你的内存。这是应用程序真正的M? 斏V?/p>

CString转化成char* 之二Q?/b>使用 CString 对象?GetBuffer ҎQ?br />
  如果你需要修?CString 中的内容Q它有一个特D的Ҏ可以使用Q那是 GetBufferQ它的作用是q回一个可写的~冲指针? 如果你只是打修改字W或者截短字W串Q你完全可以q样做:

CString s(_T("File.ext"));
LPTSTR p = s.GetBuffer();
LPTSTR dot = strchr(p, ''.''); // OK, should have used s.Find...
if(p != NULL)
*p = _T(''\0'');
s.ReleaseBuffer();

  q是 GetBuffer 的第一U用法,也是最单的一U,不用l它传递参敎ͼ它用默认? 0Q意思是Q“给我这个字W串的指针,我保证不加长它”。当你调?ReleaseBuffer Ӟ字符串的实际长度会被重新计算Q然后存? CString 对象中?br />   必须一点,?GetBuffer ?ReleaseBuffer 之间q个范围Q一定不能用你要操作的q个~冲?CString 对象的Q何方法。因?ReleaseBuffer 被调用之前,?CString 对象的完整性得不到保障。研I以下代码:

CString s(...);

LPTSTR p = s.GetBuffer();

//... q个指针 p 发生了很多事?br />
int n = s.GetLength(); // 很糟D!!!!! 有可能给出错误的{案!!!

s.TrimRight(); // 很糟!!!!! 不能保证能正常工?!!!

s.ReleaseBuffer(); // 现在应该 OK

int m = s.GetLength(); // q个l果可以保证是正的?br />
s.TrimRight(); // 正常工作?/pre>

  假设你想增加字符串的长度Q你首先要知道这个字W串可能会有多长Q好比是声明字符串数l的时候用Q?/p>

char buffer[1024];

表示 1024 个字W空间以让你做M惛_得事情。在 CString 中与之意义相{的表示法:

LPTSTR p = s.GetBuffer(1024);

  调用q个函数后,你不仅获得了字符串缓冲区的指针,而且同时q获得了长度臛_?1024 个字W的I间Q注意,我说的是“字W”,而不是“字节”,因ؓ CString 是以隐含方式感知 Unicode 的)?br />   同时Q还应该注意的是Q如果你有一个常量串指针Q这个串本n的D存储在只d存中Q如果试囑֭储它Q即使你已经调用?GetBuffer Qƈ获得一个只d存的指针Q存入操作会p|Qƈ报告存取错误。我没有?CString 上证明这一点,但我看到q大把的 C E序员经常犯q个错误?br />   C E序员有一个通病是分配一个固定长度的~冲Q对它进?sprintf 操作Q然后将它赋值给一?CStringQ?/p>

char buffer[256];
sprintf(buffer, "%......", args, ...); // ... 部分省略许多l节
CString s = buffer;

虽然更好的Ş式可以这么做Q?/p>

CString s;
s.Format(_T("%...."), args, ...);

如果你的字符串长度万一过 256 个字W的时候,不会破坏堆栈?br />
  另外一个常见的错误是:既然固定大小的内存不工作Q那么就采用动态分配字节,q种做法弊端更大Q?/p>

int len = lstrlen(parm1) + 13  lstrlen(parm2) + 10 + 100;

char * buffer = new char[len];

sprintf(buffer, "%s is equal to %s, valid data", parm1, parm2);

CString s = buffer;

......

delete [] buffer;

它可以能被简单地写成Q?/p>

CString s;

s.Format(_T("%s is equal to %s, valid data"), parm1, parm2);

  需要注?sprintf 例子都不?Unicode qA的,管你可以?tsprintf 以及?_T() 来包围格式化字符Ԍ但是基本 思\仍然是在走弯路,q这样很Ҏ出错?br />
CString to char * 之三Q?/b>和控件的接口Q?br />
  我们l常需要把一?CString 的g递给一个控Ӟ比如QCTreeCtrl。MFC为我们提供了很多便利来重载这个操作,但是 在大多数情况下,你用“原始”Ş式的更新Q因此需要将墨某个串指针存储?TVINSERTITEMSTRUCT l构?TVITEM 成员中。如下:

TVINSERTITEMSTRUCT tvi;
CString s;
// ... 为s赋一些倹{?br />tvi.item.pszText = s; // Compiler yells at you here
// ... 填写tvi的其他域
HTREEITEM ti = c_MyTree.InsertItem(&tvi);

  Z么编译器会报错呢Q明明看h很完的用法啊!但是事实上如果你看看 TVITEM l构的定义你׃明白Q在 TVITEM l构?pszText 成员的声明如下:

LPTSTR pszText;
int cchTextMax;

  因此Q赋g是赋l一?LPCTSTR cd的变量,而且~译器无法知道如何将赋D句右边强制{换成 LPCTSTR。好吧,你说Q那我就Ҏq样Q?/p>

tvi.item.pszText = (LPCTSTR)s; //~译器依然会报错?/pre>

  ~译器之所以依然报错是因ؓ你试图把一?LPCTSTR cd的变量赋值给一?LPTSTR cd的变量,q种操作在C或C++中是被禁止的。你不能用这U方? 来滥用常量指针与非常量指针概念,否则Q会Cؕ~译器的优化机制Q之不知如何优化你的程序。比如,如果你这么做Q?/p>

const int i = ...;
//... do lots of stuff
... = a[i]; // usage 1
// ... lots more stuff
... = a[i]; // usage 2

  那么Q编译器会以为既?i ?const Q所?usage1和usage2的值是相同的,q且它甚臌事先计算?usage1 处的 a[i] 的地址Q然后保留着在后面的 usage2 处用,而不是重新计。如果你按如下方式写的话Q?/p>

const int i = ...;
int * p = &i;
//... do lots of stuff
... = a[i]; // usage 1
// ... lots more stuff
(*p)++; // mess over compiler''s assumption
// ... and other stuff
... = a[i]; // usage 2

  ~译器将认ؓ i 是常量,从?a[i] 的位|也是常量,q样间接地破坏了先前的假设。因此,你的E序会?debug ~译模式Q没有优化)?release ~译模式Q完全优化)中反映出不同的行为,q种情况可不好,所以当你试图把指向 i 的指针赋值给一? 可修改的引用Ӟ会被~译器诊断ؓq是一U伪造。这是Z么(LPCTSTRQ强制类型{化不起作用的原因?br />   Z么不把该成员声明?LPCTSTR cd呢?因ؓq个l构被用于读写控件。当你向控g写数据时Q文本指针实际上被当?LPCTSTRQ而当你从控gL? Ӟ你必L一个可写的字符丌Ӏ这个结构无法区分它是用来读q是用来写?br />
因此Q你会常常在我的代码中看到如下的用法Q?/p>

tvi.item.pszText = (LPTSTR)(LPCTSTR)s;

  它把 CString 强制cd转化?LPCTSTRQ也是说先获得改字W串的地址Q然后再强制cd转化?LPTSTRQ以便可以对之进行赋值操作? 注意q只有在使用 Set ?Insert 之类的方法才有效Q如果你试图获取数据Q则不能q么做?br />   如果你打获取存储在控g中的数据Q则ҎE有不同Q例如,Ҏ?CTreeCtrl 使用 GetItem ҎQ我惌取项目的文本。我知道q些 文本的长度不会超q?MY_LIMITQ因此我可以q样写:

TVITEM tvi;
// ... assorted initialization of other fields of tvi
tvi.pszText = s.GetBuffer(MY_LIMIT);
tvi.cchTextMax = MY_LIMIT;
c_MyTree.GetItem(&tvi);
s.ReleaseBuffer();

  可以看出来,其实上面的代码对所有类型的 Set Ҏ都适用Q但是ƈ不需要这么做Q因为所有的c?Set ҎQ包? InsertҎQ不会改变字W串的内宏V但是当你需要写 CString 对象Ӟ必须保证~冲是可写的Q这正是 GetBuffer 所做的事情。再ơ强调: 一旦做了一?GetBuffer 调用Q那么在调用 ReleaseBuffer 之前不要对这?CString 对象做Q何操作?br />
5?b> 6?b>

  对于单个?BSTR 串来_q种用法可以工作得很好,q是因ؓ CString 有一个特D的构造函CLPCWSTRQBSTR正是q种cdQ? 为参敎ͼq将它{化成 ANSI cd。专门检查是必须的,因ؓ BSTR 可能为空|?CString 的构造函数对?NULL 值情况考虑的不是很周到Q(感谢 Brian Ross 指出q一?Q。这U用法也只能处理包含 NUL l结字符的单字符Ԍ如果要{化含有多?NULL 字符 Ԍ你得额外做一些工作才行。在 CString 中内嵌的 NULL 字符通常表现不尽如h意,应该量避免?br />   Ҏ C/C++ 规则Q如果你有一?LPWSTRQ那么它别无选择Q只能和 LPCWSTR 参数匚w?br />
?Unicode 模式下,它的构造函数是Q?/p>

CString::CString(LPCTSTR);

正如上面所表示的,?ANSI 模式下,它有一个特D的构造函敎ͼ

CString::CString(LPCWSTR); 

  它会调用一个内部的函数?Unicode 字符串{换成 ANSI 字符丌Ӏ(在Unicode模式下,有一个专门的构造函敎ͼ该函数有一个参数是LPCSTRcd——一??ANSI 字符? 指针Q该函数它加宽?Unicode 的字W串Q)再次Q一定要?BSTR 的值是否ؓ NULL?br />   另外q有一个问题,正如上文提到的:BSTRs可以含有多个内嵌的NULL字符Q但?CString 的构造函数只能处理某个串中单?NULL 字符? 也就是说Q如果串中含有嵌入的 NUL字节QCString 会计算出错误的串长度。你必须自己处理它。如果你看看 strcore.cpp 中的构造函敎ͼ你会发现 它们都调用了lstrlenQ也是计算字符串的长度?br />   注意?Unicode ?ANSI 的{换用带专门参数?::WideCharToMultiByteQ如果你不想使用q种默认的{换方式,则必ȝ写自q转化代码?br />   如果你在 UNICODE 模式下编译代码,你可以简单地写成Q?br />

CString convert(BSTR b)
{
if(b == NULL)
return CString(_T(""));
CString s(b); // in UNICODE mode
return s;
}
  如果?ANSI 模式Q则需要更复杂的过E来转换。注意这个代码用与 ::WideCharToMultiByte 相同的参数倹{所以你 只能在想要改变这些参数进行{换时使用该技术。例如,指定不同的默认字W,不同的标志集{?
CString convert(BSTR b)
{
CString s;
if(b == NULL)
return s; // empty for NULL BSTR
#ifdef UNICODE
s = b;
#else
LPSTR p = s.GetBuffer(SysStringLen(b) + 1);
::WideCharToMultiByte(CP_ACP, // ANSI Code Page
0, // no flags
b, // source widechar string
-1, // assume NUL-terminated
p, // target buffer
SysStringLen(b)+1, // target buffer length
NULL, // use system default char
NULL); // don''t care if default used
s.ReleaseBuffer();
#endif
return s;
}
  我ƈ不担心如?BSTR 包含没有映射?8 位字W集?Unicode 字符时会发生什么,因ؓ我指定了::WideCharToMultiByte 的最后两个参Cؓ NULL。这是你可能需要改变的地方?

7?b>
return s;
case VT_I4 | VT_BYREF:
s.Format(_T("%d"), *va->plVal);
case VT_R8:
s.Format(_T("%f"), va->dblVal);
return s;
... 剩下的类型{换由读者自己完?br /> default:
ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)
return CString("");
} /* vt */
}
8?b>载入字符串表资源

  如果你想创徏一个容易进行语a版本UL的应用程序,你就不能在你的源代码中直接包含本土语a字符? Q下面这些例子我用的语言都是pQ因为我的本土语是英语)Q比如下面这U写法就很糟Q?pre>CString s = "There is an error";

  你应该把你所有特定语a的字W串单独摆放Q调试信息、在发布版本中不出现的信息除外)。这意味着向下面这样写比较好:

s.Format(_T("%d - %s"), code, text);

  在你的程序中Q文字字W串不是语言敏感的。不怎样Q你必须很小心,不要使用下面q样的串Q?/p>

// fmt is "Error in %s file %s"
// readorwrite is "reading" or "writing"
s.Format(fmt, readorwrite, filename);

  q是我的切n体会。在我的W一个国际化的应用程序中我犯了这个错误,管我懂徯Q知道在徯的语法中动词攑֜句子的最后面Q我们的德国斚w的发行h q是苦苦的抱怨他们不得不提取那些不可思议的d语错误提CZ息然后重新格式化以让它们能正常工作。比较好的办法(也是我现在用的办法Q是使用两个字符 Ԍ一个用 于读Q一个用于写Q在使用时加载合适的版本Q得它们对字符串参数是非敏感的。也是说加载整个格式,而不是加载串 “reading”,“writing”:

// fmt is "Error in reading file %s"
// "Error in writing file %s"
s.Format(fmt, filename);

  一定要注意Q如果你有好几个地方需要替换,你一定要保证替换后句子的l构不会出现问题Q比如在p中,可以是主?宾语Q主?谓语Q动?宾语的结构等{?br />   在这里,我们q不讨论 FormatMessageQ其实它?sprintf/Format q要有优势,但是不太Ҏ和CString l合使用。解册U问题的办法是我们按照参数出现在参数表中的位置l参数取名字Q这样在你输出的时候就不会把他们的位置排错了?br />   接下来我们讨论我们这些独立的字符串放在什么地斏V我们可以把字符串的值放入资源文件中的一个称?STRINGTABLE 的段中。过E如下:首先使用 Visual Studio 的资源编辑器创徏一个字W串Q然后给每一个字W串取一个IDQ一般我们给它取名字都以 IDS_开头。所以如果你有一个信息,你可以创Z个字W串资源然后取名?IDS_READING_FILEQ另外一个就取名? IDS_WRITING_FILE。它们以下面的Ş式出现在你的 .rc 文g中:

STRINGTABLE
IDS_READING_FILE "Reading file %s"
IDS_WRITING_FILE "Writing file %s"
END

注意Q?/b>q些资源都以 Unicode 的格式保存,不管你是在什么环境下~译。他们在Win9xpȝ上也是以Unicode 的Ş式存在,虽然 Win9x 不能真正处理 Unicode?br /> 然后你可以这样用这些资源:
// 在用资源串表之前,E序是这样写的:

   CString fmt;
if(...)
fmt = "Reading file %s";
else
fmt = "Writing file %s";
...
// much later
CString s;
s.Format(fmt, filename);
// 使用资源串表之后Q程序这样写Q?
    CString fmt;
if(...)
fmt.LoadString(IDS_READING_FILE);
else
fmt.LoadString(DS_WRITING_FILE);
...
// much later
CString s;
s.Format(fmt, filename);
  现在Q你的代码可以移植到M语言中去。LoadString Ҏ需要一个字W串资源?ID 作ؓ参数Q然后它?STRINGTABLE 中取出它对应的字W串Q赋值给 CString 对象? CString 对象的构造函数还有一个更加聪明的特征可以?STRINGTABLE 的用。这个用法在 CString::CString 的文档中没有指出Q但是在 构造函数的CZE序中用了。(Z么这个特性没有成为正式文档的一部分Q而是攑֜了一个例子中Q我C得了Q)——?b>译者注
Q从q句话看Q作者可能是CString的设计者。其实前面还有一句类似的话。说他没有对使用GetBuffer(0)获得的指针指向的地址是否可读做有效性检? 】。这个特征就是:如果你将一个字W串资源的ID强制cd转换?LPCTSTRQ将会隐含调?LoadString。因此,下面两个构造字W串的例子具有相同的效果Q而且?ASSERT 在debug模式下不会被触发Q?pre>CString s;
s.LoadString(IDS_WHATEVER);
CString t( (LPCTSTR)IDS_WHATEVER );
ASSERT(s == t);//不会被触发,说明s和t是相同的?/pre>

   现在Q你可能会想Q这怎么可能工作呢?我们怎么能把 STRINGTABLE ID 转化成一个指针呢Q很单:所有的字符?ID 都在1~65535q个范围内,也就是说Q它所有的高位都是0Q而我们在E序中所使用的指针是不可能小?5535的,因ؓE序的低 64K 内存永远也不可能存在的,如果你试图访?x00000000?x0000FFFF之间的内存,会引发一个内存越界错误。所以说1~65535的g 可能是一个内存地址Q所以我们可以用q些值来作ؓ字符串资源的ID?br />   我們֐于?MAKEINTRESOURCE 宏显式地做这U{换。我认ؓq样可以让代码更加易于阅诅R这是个只适合?MFC 中用的标准宏。你要记住,大多数的Ҏ卛_以接受一?UINT 型的参数Q也可以接受一?LPCTSTR 型的参数Q这是依?C++ 的重载功能做到的。C++重蝲函数带来?弊端是造成所有的强制cd转化都需要显C声明。同P你也可以l很多种l构只传递一个资源名?/p>

CString s;
s.LoadString(IDS_WHATEVER);
CString t( MAKEINTRESOURCE(IDS_WHATEVER));
ASSERT(s == t);

  告诉你吧Q我不仅只是在这里鼓吹,事实上我也是q么做的。在我的代码中,你几乎不可能扑ֈ一个字W串Q当Ӟ那些只是偶然在调试中出现的或者和语言无关的字W串除外?br />
9?b>

char* szName = GetName().GetBuffer(20);
RegSetValueEx(hKey, "Name", 0, REG_SZ,
(CONST BYTE *) szName,
strlen (szName + 1));

q个 Name 字符串的长度于 20Q所以我不认为是 GetBuffer 的参数的问题?br />
真让人困惑,请帮帮我?br />
亲爱?FrustratedQ?br />
你犯了一个相当微妙的错误Q聪明反被聪明误Q正的代码应该象下面这P

CString Name = GetName();
RegSetValueEx(hKey, _T("Name"), 0, REG_SZ,
(CONST BYTE *) (LPCTSTR)Name,
(Name.GetLength() + 1) * sizeof(TCHAR));
  Z么我写的代码能行而你写的有问题呢?主要是因为当你调?GetName 时返回的 CString 对象是一个时对象。参见:《C++ Reference manual》?2.2
  在一些环境中Q编译器有必要创Z个时对象,q样引入临时对象是依赖于实现的。如果编译器引入的这个时对象所属的cL构造函数的话,~译器要保q个cȝ构造函数被调用。同LQ如果这个类声明有析构函数的话,也要保证q个临时对象的析构函数被调用?br />   ~译器必M证这个时对象被销毁了。被销毁的切地点依赖于实?....q个析构函数必须在退出创临时对象的范围之前被调用?br />   大部分的~译器是q样设计的:在时对象被创徏的代码的下一个执行步骤处隐含调用q个临时对象的析构函敎ͼ实现hQ一般都是在下一个分号处。因此, q个 CString 对象?GetBuffer 调用之后p析构了(Z提一句,你没有理q GetBuffer 函数传递一个参敎ͼ而且没有使用ReleaseBuffer 也是不对的)。所?GetBuffer 本来q回的是指向q个临时对象中字W串的地址的指针,但是当这个时对象被析构后,q块内存p释放了。然?MFC 的调试内存分配器会重Cؓq块内存全部填上 0xDDQ显C出来刚好就是?amp;Yacute;”符受在q个时候你向注册表中写数据Q字W串的内容当然全被破坏了?br />   我们不应该立xq个临时对象转化?char* cdQ应该先把它保存C?CString 对象中,q意味着把时对象复制了一份,所以当临时?CString 对象被析构了之后Q这?CString 对象中的g然保存着。这个时候再向注册表中写数据没有问题了?br />   此外Q我的代码是h Unicode 意识的。那个操作注册表的函数需要一个字节大,使用lstrlen(Name+1) 得到的实际结果对? Unicode 字符来说?ANSI 字符要小一半,而且它也不能从这个字W串的第二个字符起开始计,也许你的本意?lstrlen(Name) + 1QOKQ我承认Q我也犯了同L错误Q)。不论如何,?Unicode 模式下,所有的字符都是2个字节大,我们需要处理这个问题。微软的文档令h惊讶地对此保持缄默:REG_SZ 的值究竟是以字节计还是以字符计算呢?我们假设它指的是以字节ؓ单位计算Q你需要对你的代码做一些修Ҏ计算q个字符串所含有的字节大?br />
10?b>
s += SomeCString4;

比v下面的代码来Q效率要低多了:

char s[1024];
lstrcpy(s, SomeString1);
lstrcat(s, SomeString2);
lstrcat(s, SomeString 3);
lstrcat(s, ",");
lstrcat(s, SomeString4);

  MQ你可能会想Q首先,它ؓ SomeCString1 分配一块内存,然后?SomeCString1 复制到里面,然后发现它要做一个连接,则重新分配一块新的够大的内存,大到能够放下当前的字W串加上SomeCString2Q把内容复制到这块内? Q然后把 SomeCString2 q接到后面,然后释放W一块内存,q把指针重新指向新内存。然后ؓ每个字符串重复这个过E。把q?4 个字W串q接h效率多低啊。事实上Q在很多情况下根本就不需要复制源字符Ԍ?+= 操作W左边的字符Ԍ?br />   ?VC++6.0 中,Release 模式下,所有的 CString 中的~存都是按预定义量子分配的。所谓量子,即确定ؓ 64?28?56 或?512 字节。这意味着除非字符串非帔RQ连接字W串的操作实际上是 strcat l过优化后的版本Q因为它知道本地的字W串应该在什么地方结束,所以不需要寻扑֭W串的结;只需要把内存中的数据拯到指定的地方卛_Q加上重新计字 W串的长度。所以它的执行效率和U?C 的代码是一LQ但是它更容易写、更Ҏl护和更Ҏ理解?br />   如果你还是不能确定究竟发生了怎样的过E,L?CString 的源代码Qstrcore.cppQ在?vc98的安装目录的 mfc\src 子目录中。看?ConcatInPlace ҎQ它被在所有的 += 操作W中调用?br />
啊哈Q难?CString 真的q么"高效"吗?比如Q如果我创徏

CString cat("Mew!");

  然后我ƈ不是得到了一个高效的、精?个字节大的~冲区(4个字W加一个结束字W)Q系l将l我分配64个字节,而其?9个字节都被浪费了?br />   如果你也是这么想的话Q那么就请准备好接受再教育吧。可能在某个地方某个人给你讲q尽量用少的空间是件好事情。不错,q种说法的确正确Q但是他忽略了事实中一个很重要的方面?br />   如果你编写的是运行在16K EPROMs下的嵌入式程序的话,你有理由量用空_在这U环境下Q它能你的E序更健壮。但是在 500MHz, 256MB的机器上?Windows E序Q如果你q是q么做,它只会比你认为的“低效”的代码q行得更p?br />   举例来说。字W串的大被认ؓ是媄响效率的首要因素Q字符串尽可能可以提高效率,反之则降低效率,q是大家一贯的x。但是这U想法是不对的,_? 的内存分配的后果要在程序运行了好几个小时后才能体现得出来,那时Q程序的堆中充满小片的内存Q它们太以至于不能用来做Q何事Q但是他们增加了你程 序的内存用量Q增加了内存面交换的次敎ͼ当页面交换的ơ数增加到系l能够忍受的上限Q系l则会ؓ你的E序分配更多的页面,直到你的E序占用了所有的可用 内存。由此可见,虽然内存片是决定效率的ơ要因素Q但正是q些因素实际控制了系l的行ؓQ最l,它损害了pȝ的可靠性,q是令h无法接受的?br />   CQ在 debug 模式下,内存往往是精分配的Q这是ؓ了更好的排错?br />   假设你的应用E序通常需要连l工作好几个月。比如,我常打开 VC++QWordQPowerPointQFrontpageQOutlook ExpressQForté AgentQInternet Explorer和其它的一些程序,而且通常不关闭它们。我曄夜以l日地连l用 PowerPoint 工作了好几天Q反之,如果你不q怸得不使用?Adobe FrameMaker q样的程序的话,你将会体会到可靠性的重要Q这个程序机会每天都要崩?~6ơ,每次都是因ؓ用完了所有的I间q填满我所有的交换面Q。所以精内存分配是不可取的Q它会危及到pȝ的可靠性,q引起应用程序崩溃?br />   按量子的倍数为字W串分配内存Q内存分配器可以回收用q的内存块,通常q些回收的内存块马上可以被其它?CString 对象重新用到Q这样就可以保证片最。分配器的功能加ZQ应用程序用到的内存p可能保持最,q样的程序就可以q行几个星期或几个月而不出现? 题?br />   题外话:很多q以前,我们?CMU 写一个交互式pȝ的时候,一些对内存分配器的研究昄出它往往产生很多内存片。Jim MitchellQ现在他?Sun Microsystems 工作Q那时侯他创造了一U内存分配器Q它保留了一个内存分配状늚q行时统计表Q这U技术和当时的主分配器所用的技术都不同Q且较ؓ领先。当一个内存块 需要被分割得比某一个值小的话Q他q不分割它,因此可以避免产生太多到什么事都干不了的内存碎片。事实上他在内存分配器中使用了一个Q动指针,他认为: 与其让指令做长时间的存取内存操作Q还不如单的忽略那些太小的内存块而只做一些Q动指针的操作。(His observation was that the long-term saving in instructions by not having to ignore unusable small storage chunks far and away exceeded the additional cost of doing a few floating point operations on an allocation operation.Q他是对的?br />   永远不要认ؓ所谓的“最优化”是建立在每一行代码都高速且节省内存的基上的Q事实上Q高速且节省内存应该是在一个应用程序的整体水^上考虑的。在软g的整体水q上Q只使用最内存的字符串分配策略可能是最p糕的一U方法?br />   如果你认Z化是你在每一行代码上做的那些努力的话Q你应该想一惻I在每一行代码中做的优化很少能真正v作用。你可以看我的另一关于优化问题的文章《Your Worst Enemy for some thought-provoking ideas》?br />   CQ?= q算W只是一U特例,如果你写成下面这P

CString s = SomeCString1 + SomeCString2 + SomeCString3 + "," + SomeCString4;
则每一?+ 的应用会造成一个新的字W串被创建和一ơ复制操作?br />
ȝ

  以上是?CString 的一些技巧。我每天写程序的时候都会用到这些。CString q不是一U很难用的c,但是 MFC 没有很明昄指出q些特征Q需要你自己L索、去发现?img src ="http://www.tkk7.com/tingfeng/aggbug/261265.html" width = "1" height = "1" />

听风 2009-03-21 22:49 发表评论
]]> վ֩ģ壺 һƷƵ߲ | ޳˾þ| ˺ݺۺϾþ޸| ëƬƵ| ˬָ߳ëƬ | ƷžƷƵ| þþþAVȥ| ŷպ޾Ʒ| ۺŷ㻨 | AVרAVԾ| ˾þô߽| һƷƵ| պŷƷ| avպƷþþþþa| ҳվѹۿ| vƬ߹ۿ| ӰӾ߹ۿȫ| ߹ۿվ| ҹƷ߹ۿ | ޾Ʒ| ҳƵ߹ۿ| ƷŮþþ | պAVһ| þ㽶߿| **ʵһëƬaa| ŷ޴Ƭ| Ļվѹۿ| ޹˾þһþ| þþƷҹɫA| ޳AVƬ| ޾ƷŮþþþ9999| 2017һ| ҹػaëƬѲ| һ| 3344ѲŹۿƵ| 18ڵվ| ޹Ӱavַ| A߹ۿ| ij| һëƬ߲| þþƷƵѲ|