首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 网页制作
VB中String的用法及原理-.NET教程,VB.Net语言
作者:网友供稿 点击:276
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 
 

    在各种不同开发语言中,字符串类型显然是最常见,也是最常用的。
    常用代表它最易用,是这样吗?未必,越简单,越普通,你会忽视,内里隐藏着的陷井更容易使你中招。它往往是绊脚石,或者程序中性能的瓶颈。
    本身,我对vb语言及相关应用并不太熟,只不过近期编码用到,有些体会。

一: 先来总结一下,常用编程语言的字串表达方式:
c:      char(wchat_t) * 或 []:  字符数组来表示字符串,以0结尾,无长度标识。
          配一堆操作函数,不好记,不好用。
c++:  std::string  basic_string<>的特化版本. 注意:其内在的数据区由默认的内存管理器分配。
         对象哈,提供还算好用的方法。
mfc: cstring 标准的c++类. 数据项:lptstr 一堆可用的方法。
windows普通api dll:       lptstr 采用c标准的0结束字串
windows扩展com中:         bstr  ole标准, 头上带长度标识的字符串.
java中:                            java.lang.string 
vb中:                              string   实际上就是ole标准的bstr
好了,我们关心的是bstr。
看看bstr到底是什么东东。
1.0:看看在windows sdk中的定义:
typedef olechar* bstr;
typedef wchar olechar;
typedef wchar_t wchar;
所以,它实际上是宽字符指针。

1.1:它的内存结构呢?很容易查到资料。
前置四字节,内置字串的长度,后面是字串内容,原则上并不以\0结尾,长度由前置值决定。
所以,它又不简简单单就是宽字符指针。但从基本类型定义上来看,它与宽字符指针是可以划等号的。

1.2:那vb中的string也就明白了。实际上是地址,是字串的首地址(注意:不是长度的首地址)
另外,string是可以装载中间带\0字符的字串的,只不过,一些显示函数可能将其省略。
如:dim str as string
     str = "ab" & chr(0) & "cd"
     msgbox str   输出:ab
     debug.print str 输出 ab cd

1.3:可以看出,它很特珠,windows提供几个函数,用来分配和释放它。
分配:sysallocstringlen      sysallocstring
释放:sysfreestring
取长度:sysstringlen
注意:分配得到的bstr,实际上仍然是以\0结尾。sysstringlen似乎有点儿英雄无用武之地,呵。
比如:sysallocstringlen 的说明文档:
allocates a new string, copies cch characters from the passed string into it, and then appends a null character.
比如:sysallocstring,我们可以通过例子:
 bstr bstrval = ::sysallocstring(l"abcd");
 for(int n=0;n<::sysstringlen(bstrval)+1;n++)
 {
  trace(_t("\n%d"),*(bstrval+n));
 }
 ::sysfreestring(bstrval);
输出:
97
98
99
100
0
仍然有0。

1.4:vc中的用法:
无论用mfc,还是atl,实际上,由于bstr并不是基本类型,而它的相关操作函数也是沿用的以\0结尾的函数,所以,虽然它在字串中可以带\0,但实际上,经过相关操作后,\0后的内容会丢掉,这要小心。比如,我们看看cstring的构造:
cstring::cstring(lpcwstr lpsz)
{
 init();
 int nsrclen = lpsz != null ? wcslen(lpsz) : 0;
 if (nsrclen != 0)
 {
  allocbuffer(nsrclen*2);
  _wcstombsz(m_pchdata, lpsz, (nsrclen*2)+1);
  releasebuffer();
 }
}

小结:bstr有长度标识,但是ms在实现时,为了兼容以前的字串操作,再加上bstr并不是基本类型,所以,它的分配函数和一些操作函数都是把它当作\0结尾来处理。千万要注意。最好也不要用它来装载中间带\0的字串,因为,说不定什么时候,它就丢掉了。

二:  vbr的应用中将麻烦的地方,应该集中在以下几个方面:
2.1: vb调用windows api dll
2.1.1: 字串作为输入参数
   这还用说吗?
   在api中如果是lptstr,在vb中直接转为byval s as string
   原因?  为什么 bstr可以直接转为 lptstr ?
   前面其实已经讲了,再说一次吧。
   bstr实际上是指针,指向字串头.所以,采用byval指向的刚好是字串的首地址,也就是lpstr,嘿嘿,刚刚好,符合需要,真是巧啊。

2.1.2: 字串作为输出参数
这个麻烦一点,举个例子吧.
如: 
    uint getwindowsdirectory( 
      lptstr lpbuffer, 
      uint usize 
   );
使用api viewer得到声明 
   public declare function getwindowsdirectory lib "kernel32" alias "getwindowsdirectorya" _ 
      (byval lpbuffer as string, byval nsize as long) as long
代码: 
    dim stemp as string * max_path 
    dim lsize as long 
    dim str as string 
    lsize = getwindowsdirectory(stemp, max_path) 
    str = left(stemp, lsize) 
    msgbox "windows路径:" & str & "长度:" & len(str)
注意一下:
a: 引用的windows api是a版,而不是w版,如果是w版会有错误.
原因,我的猜测是:   vb的api调用机制中,字串强制做了unicode到ansi的转换.api的dll没法告知调
用端,它是unicode版还是ansi版.如果是ocx或com就没问题了,因为它们有标识。没办法,只能用一种了, ms选了a版。
b: 参数是byval
道理同作为输入时,实际上传的指针,所以,指向的内容是可以修改地,也就可以返回了。 
c: 根据api的使用说明,可得到
[out] pointer to the buffer to receive the null-terminated string containing the path.
需要调用方分配空间,因此, stemp需要给足够长度的空间. 
d: 返回的0结尾的字串,可以用left达到目的.
因为:vb的string对应的是bstr类型,长度由前置字节决定,而不是0字符决定. 

2.1.3: 字串作为return值
这种api是不是存在呢?系统级的没看见,一般不会这样用,因为这存在内存分配的问题.
但我自已好像写过,处理方式是:
vb声明中可以使用long返回,然后用lstrcpy进行转换,
说起lstrcpy就不得不说说它的作用了,它实在是很关键,它很神奇,它可以把
地址指向的字符串拿出来。
我们来看看原理:
lstrcpy本身只是简单的复制字符串的函数:
public declare function lstrcpy lib "kernel32" alias "lstrcpya" (byval lpstring1 as string, byval lpstring2 as string) as long 如果按照api view中的声明,是不行的.它确实就是字串拷字串,没办法把字址指向的字串拷到另一串.
   好了,需要小小改动一下:
   首先:目的地没错,确实应该是指向字串的首地址.用byval string就可以.第一个参数ok。
   源串呢? 因为你传入的实际上不是string,而是long啊(上例返回的是long噢),那当然应该将声明改成long,否则,传入的string会变成啥,啥都不是呢?就这么简单。 

2.1.4: lptstr 都可以用vb的byval string替代吗?
如果在结构体里,可就不是这样了.
如:enumforms  枚举某个打印机的所有打印纸型。
public declare function enumforms lib "winspool.drv" alias "enumformsa" (byval hprinter as long, _ byval level as long, byref pform as form_info_1, byval cbbuf as long, byref pcbneeded as long, _ 
 byref pcreturned as long) as long 
对于 form_info_1的定义:
public type form_info_1 
        flags as long 
        pname as string 
        size as sizel 
        imageablearea as rectl
end type 
    如果按上述的方法调用,会出现异常.估计是在拷贝数据时,string实际上是不同于lptstr的,因为它的前面还有四字节是标识长度的,如果定义为string,那在构造pname之前的长度,必将动到它不应该动到的地方,这样,就错了.想来不会异常退出的,但却退出了,不知原因(我没弄明白)

  所以,此种情况,应该将pname变为long,然后再用2.1.3提到的方法,将字串拷贝出来使用. 
         这样,就ok了。 

引申一下:
    对于一些api中大的结构体中的指针类型,我们完全可以用long来取代它,然后传递0&,因为,大多数情况,我们是不需要传入任何参数的,避免定义很多我们并不需要的类型.这样就降低了api使用的复杂性。

2.2 : vb调用com组件(或ocx控件)
这似乎没啥可说的,com组件的接口一般都是标准的bstr,与vb的string完全兼容.
vb调用端没啥问题,倒是书写com的程序需要注意:
2.2.1: 应用端可能会传入空指针.比如传入vbnullstring,这需要留意.
2.2.2: bstr的释放与普通lptstr可不同,使用前需要初始化,使用后要释放,当然,vb无此烦恼.

3: vb字串的连接操作.
    当我们要序列化生成文本文件时,大都喜欢先将内容写入字串,然后再一次写了文件.否则多次写入文件,似乎有效率低之嫌,但如果字串为多次累加而成,那么使用vb字串的连接操作,将是效率极差的做法,这也变成性能低下的重要原因.
    分析一下原因: 
    对于string的连接,系统的做法一定是重分配空间,搬移到新空间,拷贝进新内容.如果连接次数较多,且较细,那将是灾难性的。(类似mfc的cstring的做法,假设我们要写一个100k长度的字串,但每次添加一个字符,那你可以试试它的速度)
   如何解决? 
   很简单,采用预分配内存块, 当内存块不够用时,自动增加指定块的增量(当然每次增长的内存块这个阀值需要慎重考虑) 
   这样,减少搬移操作,效率自然提升。 
   具体实现:可以使用内存操作api实现.vb会麻烦一点(需要用api生成全局内存,自行完成搬移,拷贝),
vc可以直接使用cmemfile简单搞定.

4: vb字串多语言化
4.1: 一般的做法是: 将原生串与多语言串做成key.value pair结构。多语言信息为value,然后做一个简单的hashc ode来索引,或者干脆用hash map来实现 (为了更高效,更容易使用已有容器,最好借助于c++编写相关支持)。
4.2: 为了使ui上的字串也能多语言化,需要保证字串信息为动态加载。
4.3: 对于控件的字体编码字符集也需要处理,以保证正确显示。



文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·中文字符从jsp传送到servlet的处理-JSP教程,Jsp/Servlet
·带右键菜单的树形控件(1)-ASP教程,ASP应用
·RSA加密解密及RSA签名和验证-.NET教程,安全和优化
·VB中String的用法及原理-.NET教程,VB.Net语言
·ASP Forum2.0学习笔记之二---了解Master Pages库-ASP教程,数据库相关
·使用ImageList时候发生运行错误提示资源问题的解决方法-.NET教程,评论及其它
·web.config点滴:更改login控件对密码安全性的要求-.NET教程,组件控件开发
·基于h.323协议的ip视频会议质量技术
·框架(javascript)-JSP教程,Java技巧及代码
·讲一讲ASP处理数据用的组件ADO (ActiveX Data Object)-ASP教程,数据库相关
最新文章
·从两方面看ajax与b/s_ajax教程
·google adsense for content新的广告样式_google推广
·flash as代码简单实现动态文本包边效果_flash教程
·我做gg广告从0到每月1000美元详细全过程_网赚技巧
·google adsense 中文高价关键词一览_网赚技巧
·谁说小网站赚不到钱!_网赚技巧
·什么样的网站才算是高质量网站呢?_站长心得
·经验:搜索引擎的页面各个元素的权重比例参考_站长心得
·搜索引擎google排名优化全攻略_google推广
·月入千美金不是梦--adsense高收入实战及分_google推广
相关主题
西部数码虚拟主机

友情链接
CNNIC 西部数码
万网 自助建站
虚拟主机 asp空间
域名注册 域名
域名申请 主页空间
论坛空间 网站空间
国际域名 虚拟空间
空间租用 DDOS防火墙
成都主机托管 四川主机托管
主机租用 服务器租用
网站目录 自助建站
虚拟主机 网址大全
软件下载
自助链接
虚拟主机资讯 特价虚拟主机
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
发表评论 打印  刷新     关闭