Symbian编程总结-基础篇-描述符(1)-描述符简介
本文章由杨芹勍原创,如需转摘请注明出处。谢谢!
一、强化印象
在学习描述符之前,首先要理解Symbian中描述符的作用。在Symbian中,没有提供专门用来处理字符串的类,它把字符串和二进制缓冲区看成是同一类数据,有一套专门的类去管理,这一套类的类关系图层次结构如下图所示:
图一. 描述符类的层次关系
上图所示的类统称为“描述符”,Symbian用“描述符”来管理字符串,其中,TDesC、TDes、TBufCBase为抽象类。
我们首先来举一个简单的例子,来强化我们对描述符的理解。如果我们由一个字符串“NewLC”,我们想使用变量存放,在C语言中,我们可以使用如下代码编写:
1 |
char[] c = “NewLC”; |
而在Symbian C++中,我们应该使用以上那个描述符存放呢?
答案是:你可以使用任一描述符存放!我们不给代码,先向大家展示一下使用不同的描述符存放字符串在内存中的存放形式:
图二. 描述符对象与数据在内存中的位置
二、理解概念
1、根据描述符数据存放位置进行分类(如图二):
- 栈描述符TBuf和TBufC:数据做为描述符对象的组成部分而存在,描述符对象存放在程序的栈中,就像C语言中的字符数组(char[])。
- 堆描述符HBufC:数据做为描述符对象的组成部分而存在,描述符对象存放在堆中,就像C语言中的(char*)malloc( length+1 )一样通常用于预先不能确定长度的情况。因为是在堆上分配的,它总是通过HBufC*使用而不是直接定义HBufC对象。
- 指针描述符TPtr和TPtrC:描述符对象和它所表示的实际数据是分开存放的,描述符对象存放在栈中,正如“指针”的含义,指针描述符所指向的数据可以为栈中的数据,也可为堆中的数据。TPtrC和TPtr与C语言中的char*有点儿类似,但因为描述符自己包含了长度信息,所以不再需要扫描结尾的空字符(‘\0’)或为它分配空间。
2、可修改的描述符与不可修改的描述符:
大家可以看到,在描述符类中,有些类结尾带“C”,这些类表示“只读的描述符”,即:描述符在定义时拥有的数据或指向的数据,描述符不提供修改的方法。所以,推荐使用以下方法声明可修改的描述符和不可修改的描述符:
1 |
const TDesC& str; |
可以从图一看到,基类TDesC没有提供对内容修改的函数,而继承自TDesC的类TDes提供了对内容修改的函数。
3、描述符的宽度
所有这些描述符都可以指定数据尺度:TDes8、TDes16、TDesC8、TDesC16、TBuf8、TBuf16等
这里8表示描述符处理的数据是8bit的,而16表示是16bit数据。一般来说,你只要使用通用形式(TDes, TDesC,…)来表示文本数据而使用8bit版本(TDesC8等)来表示二进制的内容。
三、描述符的使用
1、使用宏_LIT(_LIT16,_LIT8)和_L定义字符串常量
_L()可以生成一个指向字符值的地址(TPtrC),它经常被用来传递字符串到函数中:
1 |
NEikonEnvironment::MessageBox(_L(“Error: init file not found!”)); |
_LIT()可以生成个常量名,以便以后重复使用:
1 |
_LIT(KMyFile, “c:\System\Apps\MyApp\MyFile.jpg”); |
_LIT()宏的结果(就是上面的KMyFile)实际上是个文字描述符(literal descriptor)TLitC,它可以在任何使用TDesC&的地方使用。
2、系统定义的描述符
KNullDesC(KNullDesC16, KNullDesC8)
1 |
_LIT16(KNullDesC, ""); |
表示空或者无文本的16位(8位)格式描述符。
3、构造描述符
- TBufC(不可修改的栈描述符)
1
2
3
4
5
6
7_LIT(KHelloWorld, "Hello World");
const TInt maxBuf = 32;
TBufC<maxbuf> buf;
TInt currentLen = buf.Length(); // == 0
buf = KHelloWorld;
currentLen = buf.Length(); // == 11
TText ch = buf[2]; // == ''l'' - TBuf(可修改的栈描述符)
1
2
3
4
5
6
7
8
9
10
11const TInt bufLen = 6;
TUInt8 objType = 1;
TUInt8 objId = 1;
TUInt8 xCoord = 128;
TUInt8 yCoord = 192;
....
TBuf8<bufLen> buf;
buf.Append(objType);
buf.Append(objId);
...
// 我们能够使用buf做一些事情,如:将buf写入文件或者通过Socket发送 - TPtrC(不可修改的指针描述符)
1
2
3const unsigned char KBuffer[] = {0x00, 0x33, 0x66, 0x99, 0xbb, 0xff};
TPtrC8 bufferPtr( KBuffer, sizeof(KBuffer));
iSocket.Write(bufferPtr, iStatus); - TPtr(可修改的指针描述符)
1
2
3
4
5
6
7_LIT(KHelloWorld, "Hello World");
const TInt maxBuf = 32;
TBufC<maxBuf> buf;
buf = KHelloWorld;
TPtr ptr = buf.Des();
ptr[7] = ''a''; ptr[8] = ''l''; ptr[9] = ''e''; ptr[10] = ''s'';
CEikonEnv::Static()->InfoMsg(ptr); // "Hello Wales" - HBufC(堆描述符)
1
2
3HBufC* heapBuf = HBufC::NewL(KHelloWorld().Length());
*heapBuf = KHelloWorld();
delete heapBuf;
4、使用描述符
- Ptr(),用来获得描述符数据中的指针。
- Length(),用来获得描述符数据中的字符数。
- Size(),用来获得描述符数据中的字节数目。
- Cpmpare()或操作符==、!=、<=和>=等专为比较描述符数据用的。
- 操作符[],可以被当作c/c++中一样,用来获得描述符字符串中的单个字符。
- Append()和Num()有很多重载形式,具体可以看SDK
- Compare()有2个变体:CompareC()和CompareF(),以及Copy(),Find(),Locate()和Match(),这些函数都有C/F的后缀形式,C代表Collated而F代表Folded。Folding是个比较格式化文本的简单方法,主要用在对比较不是太要求精确的场合。Collation是个更好的也更有效的比较字符串的方法,可以生成类似字典的顺序。
四、参考文献:
1.《Symbian中的String和Descriptors》,出处:http://blog.csdn.net/sworder_001/archive/2006/09/27/1297069.aspx
2.《描述符浅析》,出处:http://blog.csdn.net/btooth/archive/2006/07/05/879584.aspx
3.《Symbian基本规范:描述符》,出处:http://gardenlee.blogchina.com/gardenlee/3285302.html
4.《Nokia官方培训(Symbian4300)笔记(六)—Descriptors》,出处:http://embed.e800.com.cn/articles/2007/427/1177655438529691221_1.html