Symbian描述符概述

 

Introduction

    描述符(Descriptors)封装了字符串和二进制数据,用于替代C中的以NULL结尾的字符串。它的长度和数据都封装在了描述符中,Symbian API中用的都是描述符。如:

    TPtrC ptr (KHelloWorld);    CEikonEnv::Static()->InfoMsg(ptr);

 Main Types of Descriptors

    主要可以分为以下几类,其中带C的是不可修改的。 

  • Abstract:(TDes、TDesC),其他描述符的基类,不能实例化,一般用作函数的参数。
  • Literal:(TLitC,_LIT()),用于存储literal string,一般使用后者。
  • Buffer:(TBuf,TBufC),数据存储于栈上,大小在编译时确定。
  • Heap:(HBufC),数据存储于堆上,大小在运行时确定。
  • Pointer:(TPtr,TPtrC),引用存储于类之外的数据

Descriptor Modification

    描述符可以是可修改的和不可修改的,通常带C的都是不可修改的,不可修改的是可修改的基类。   

  • Moidfiable:提供了访问和修改数据的API,如TBuf
  • Non-Modifiable:数据只可以被访问,不可修改。但是通过Des()函数可返回一个可修改的指针

Descriptor Width

    在描述符类后加上8或者16影响了存储在描述符中的数据的宽度,默认是16位的,处理二进制或ASCII时采用8位。

  • 8位:(TDesC8),用于二进制数据或者ASCII字符串
  • 16位:(TDesC16),默认,Unicode

下面开始对上述5类描述符进行详细介绍,首先看一下类继承关系

 

                                            这里显示的是8位的,16位默认的类继承关系与此一致

Abstract Descriptors

    除Literal外的所有描述符的基类,提供了基本的接口和基础功能。他们本身不能实例化,一般用作函数参数。

TDesC:提供了比较、复制、搜索、提取部分字符串的函数。

TInt TDesCUtil::SumLengths(const TDesc& aDesC1, const TDesc& aDesC2)
{
   return aDesC1.Length() + aDesC2.Length();

TDes:继承自TDesC,添加了许多用于修改数据的函数。其最大长度是描述符被创建时确定的。

TInt TDesCUtil::AppendL(TDesc& aTarget, const TDesc& aDesC)
{
   TInt sumLen = aTarget.Length() + aDesC.Length();
   if (aTarget.MaxLength() < sumLen)
   {
      User::Leave(KErrOverflow);
   }
   aTarget.AppendL(aDesC);

 Literal Descriptors

    提供了一种将字符串放在只读存储空间中的机制(实际存放在程序的数据区,而不是真的在ROM中)。一般不采用TLitC而直接采用_LIT()宏。    _LIT(KHelloWorld, "Hello World!");

    通过()操作符可以得到 const TDesC&。 TInt length = KHelloWorld().Length();

    在函数参数为const TDesC&可以直接使用KHelloWorld。iLabel->SetTextL(KHelloWorld);

 Buffer Descriptors

    将数据作为本身的一部分存储在stack上,他们的最大长度是在编译时确定的。  

TBuf<16> helloWorld = KHelloWorld;
TInt len = KHelloWorld().Length();
helloWorld[len-1]='?'; 

在内存中如下所示: 

TBufC的用法如下:

_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的用法如下:

const TInt bufLen = 6;
TUInt8 objType = 1;
TUInt8 objId = 1;
TUInt8 xCoord = 128;
TUInt8 yCoord = 192;
....
TBuf8<bufLen> buf;
buf.Append(objType);
buf.Append(objId);
...
//we can now do something with the buffer such as writting it to a binary file or send via socket.

Pointer Descriptor

    用于引用存储在其他地方的数据,如:

const unsigned char KBuffer[ ] = {0x00, 0x33, 0x66, 0x99, 0xbb, 0xff};
TPtrC8 bufferPtr( KBuffer, sizeof(KBuffer));
iSocket.Write(bufferPtr, iStatus);

在内存中如下所示:

TPtr的用法:

 _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"

 Heap Descriptors

     动态在堆(heap)上分配,通过HBufC的API,数据可以被set和reset,但是不能被修改。如:

HBufC* heapBuf = HBufC::NewL(KHelloWorld().Length());
*heapBuf = KHelloWorld();
delete heapBuf; 

     在内存中的情况如下图所示:

    HBufC通常在以下几种情况下使用: 

  •  在运行时从资源文件中加载字符串
  •  从用户界面中接收用户输入的字符串
  • 从应用程序引擎中接收字符串,如contacts database中的名字 

     对HBufC中的内容进行修改:

_LIT(KHello, "Hello!");
_LIT(KWorld, "World!"); 
HBufC* heapBuf = HBufC::NewL(KHello().Length());
*heapBuf = KHello;    //buf holds "Hello!"

heapBuf = heapBuf->ReAllocL(KHello().Length() + KWorld().Length());
CleanupStack::PushL(heapBuf);

TPtr ptr (heapBuf->Des());  //DON'T use TPtr ptr = heapBuf->Des(); this will set maxlen to 6 but not 12...
ptr[KHello().Length() - 1] = ' ';
ptr += KWorld;
iTopLabel -> SetTextL(ptr);
CleanupStack::PopAndDestroy();
DrawNow();

下面介绍Descriptors的具体用法: 

 Non-Modifying Methods

     Length(),Size(),Left(),Right(),Mid(),Compare(),Locate(),LocateReverse (),Find(),Match()等。以下代码示例描述了如何在一个descriptor中找到<>中的内容,如果不存在,返回整个字符 串:

static const TUint KAddressStartChar = '<'; 
static const TUint KAddressEndChar = '>';

TPtrC ExtractAddressNumber( const TDesC& aAddressString)
{
    TInt addrStart = aAddressString.Locate(KAddressStartChar ) + 1;
    TInt addrEnd  = aAddressString.LocateReverse(KAddressEndChar ) ;
    if ((addrStart == KErrNotFound) || (addrEnd == KErrNotFound) || (addrStart >= addrEnd) )
    {
        addrStart = 0;
        addEnd    = aAddressString.Length();
    }
    return (aAddressString.Mid(addrStart, (addrEnd - addrStart) ) );

 Modifying Methods

     Zero(),Copy(),Num(),Format(),Insert(),Replace(),Delete(),Append(),Trim()等。代码示例:

_LIT(KText, "Hello World!");
_LIT(KNewText, "New Text");
_LIT(KReplaced, "Replaced");

TBuf<16> buf1(KText); 
buf1.Delete(6, 6); // length is now 6, leaving "Hello" in the buffer

TBuf<16> buf2(KNewText);
buf2.Copy(KReplaced); // buf2 now contains "Replaced"
buf2.Append(KNewText);  //buf2 now contains "Replaced New Text"

buf2.Delete(99, 1); //Will Cause a PANIC!!! 

 Descriptors in Method Declarations

  • 在函数参数中尽量使用基类
  • 使用中性的描述符,一般情况下使用TDesC而不是TDesC8或者TDesC16
  • 当描述符内容不应该改变时,使用const修饰符 
  • 经典用法:void SetText(const TDesC& aText);    TPtrC Text() const; 

  Character Conversions   

     CCnvCharacterSetConverter类提供了在Unicode和其他字符集编码之间转换的方法。

ASCII本来就是Unicode的一个子集,无须使用该类。和Unicode之间的转换方法如下所示:

TBuf16<64>  UnicodeBuf;
_LIT8(KAsciiStr, "Hello");
UnicodeBuf.Copy(KAsciiStr);

Unicode和拉丁语系之间的转化可使用如下的代码:

 TBuf8<64> Latin1Buf;
_LIT16(KUnicodeStr1, "hello");
_LIT16(KUnicodeStr2, "I have got 10/x20AC.");  ///x20AC is a euro
Latin1Buf.Copy(KUnicodeStr1); //OK
Latin1Buf.Copy(KUnicdoeStr2); //Not as you wanted.

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值