Symbian开发简述(描述符)

来源:互联网 发布:中国瓷器品牌知乎 编辑:程序博客网 时间:2024/05/01 15:52

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 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 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 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.

原创粉丝点击