symbian学习笔记二(字符串)
本文内容非原创,属于网上资源的整理。
========================================
- 8位:(TDesC8),用于二进制数据或者ASCII字符串
- 16位:(TDesC16),默认,Unicode
描述符可以分为五类:
- 抽象类(Abstract):(TDes、TDesC、Tdes8、TdesC8),其他描述符的基类,仅提供接口和基本功能,不能被实例化,一般只用作函数的参数。
- 文字常量(Literal):(TlitC、_LIT()),用于存储文字字符串(literal string),即C中字符串常量,通常使用_LIT()这种方式(当然还有_L()和_L8()的描述方式,但都不提倡用)。
- 栈类(Buffer):(Tbuf、TbufC、 Tbuf8、TbufC8),数据存储于栈上,最基本的描述符变量类型,大小在编译时确定,包含描述符本身数据,使用最为普遍
- 堆类(Heap):(HbufC、HbufC8),数据存储于堆上,大小在运行时确定,也就是是用来处理动态申请的描述符类。
- 指针类(Pointer):(TPtr、TPtrC、TPtr8、TPtrC8),本身不包含描述符数据,但是包含长度数据,而且还包含一个指向位于描述符之外数据的指针。
1、 文字描述符常量
- LIT(KMyFile, “c:\System\Apps\MyApp\MyFile.jpg”);
_L()可以生成一个指向字符值的地址(TPtrC),它经常被用来传递字符串到函数中(包括描述符的构造函数和格式化函数);同理_L8()则可以生成一个指向二进制数据的地址(TPtrC8)举例如下:
- NEikonEnvironment::MessageBox(_L(“Error: init file not found!”));
- //数字转字符串
- TBuf16<20> buf;
- TInt iNum = 20;
- buf.Format( _L( “%d” ) , iNum );
2、 栈描述符
- LIT(Ktext , “Test Text”);
- _LIT(Ktext1 , “Test1 Text”);
- _LIT(KXtraText , “New:”);
- _LIT(NewText , “New1″);
- _LIT(NewText1 , “New2″);
- TBufC<10> Buf1 ( Ktext );//Buf1长度为9 内容 “Test Text”
- TBufC<10> Buf2 ( Ktext1 );//Buf2长度为10 内容 “Test1 Text”
- // 通过赋值的方式改变数据
- Buf2 = Buf1; //Buf2长度变为9 内容 “Test Text”
- //通过使用Des()生成指针改变TBufC的数据
- TPtr Pointer = Buf1.Des();
- // 删除后四个字符
- Pointer.Delete(Pointer.Length()-4, 4 ); //Buf1长度变为5 内容“Test ”//但是内存应该没变
- // 增加新的数据
- Pointer.Append(KXtraText);//Buf1长度为9 内容为“Test New:”
- // 也可以使用下列方式改变数据
- TBufC<10> Buf3(NewText);
- Pointer.Copy(Buf3);//Buf1长度为4,内容为New1
- // 或直接从字符串里获得数据
- Pointer.Copy(NewText1);//Buf1长度为4,内容为New2
以上介绍的是不可修改的栈描述符,而可修改的描述符就不用通过那么复杂的方法来实现修改,它直接可以用Copy、Delete等方法,但是无论可修改的还是不可修改的,一旦指定最大的数据长度后,最大长度就不能进行修改了。
在内存中如下所示:
- TBuf<16> helloWorld = KHelloWorld; TInt len = KHelloWorld().Length(); helloWorld[len-1]=’?';
TBufC的用法如下:
- _LIT(KHelloWorld, “Hello World”); const TInt maxBuf = 32; TBufCbuf; 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.
3、 堆描述符
堆描述符虽然都是不可修改类型的,但是它仍然具有构造和修改,与栈描述符不同的是:首先对内存需要显示释放,其次是堆描述符没有最大长度的限制,任何时候都可以用ReAlloc()函数重新申请分配。具体见示例:
- //例1、构造
- //有两种方式来生成一个Heap Descriptor
- //第一种方式用New(),NewL(),或NewLC()
- //如下操作便可以构建一个存放数据的空间,空间为15,不过目前大小为0
- HBufC * Buf = HBufC::NewL(15);
- //第二种方式是采用Alloc(),AllocL()或AllcLC()来处理,
- //不过这是已经存在的数据的管理方式。新的Heap Descriptor
- //可以自动的根据这个内容来构造。
- _LIT (KText , “Test Text”);
- TBufC<10> CBuf = KText;
- HBufC * Buf1 = CBuf.AllocL();
- CleanupStack::PushL(Buf1);
- //例2、修改
- //下面是通过赋值方式改变其数据的方法
- _LIT ( KText1 , “Text1″);
- *Buf1 = KText1;
- // 通过可修改指针来改变数据的方式
- TPtr Pointer = Buf1->Des();
- //添加数据
- Pointer.Delete(Pointer.Length() - 2, 2);
- //删除数据
- _LIT ( KNew, “New:”);
- Pointer.Append(KNew);
- //例3、重新申请内存
- Buf1 = Buf1->ReAllocL(KText().Length() + KNew().Length());
- CleanupStack::PushL(Buf1);
- //例4、释放内存
- //直接用delete
- delete Buf;
- Buf = NULL;
- //如果在使用NewL、ReAllocL等异常函数后我们使用清除栈压入的话
- //那么我们也可以用清除栈来释放内存
- CleanupStack::PopAndDestroy();
- Buf1 = NULL;
注:关于以上用清除栈的方式,个人只是猜测,因为对Symbian的异常处理三部曲,至今仍没有很好的掌握,所以如果有什么误用还望指点。
- HBufC* heapBuf = HBufC::NewL(KHelloWorld().Length()); *heapBuf = KHelloWorld(); delete heapBuf;
在内存中的情况如下图所示:
HBufC通常在以下几种情况下使用:
- 在运行时从资源文件中加载字符串
- 从用户界面中接收用户输入的字符串
- 从应用程序引擎中接收字符串,如contacts database中的名字
对HBufC中的内容进行修改:
- HBufC* heapBuf = HBufC::NewL(KHelloWorld().Length()); *heapBuf = KHelloWorld(); delete heapBuf;
4、 指针描述符
- //例1、用TBuf和TBufC构造出TPtrC对象
- _LIT(KText , “Test Code”);
- TBufC<10> Buf ( KText );
- //或者为 TBuf<10> Buf ( KText );
- // Creation of TPtrC using Constructor
- TPtrC Ptr (Buf);
- // Creation of TPtrC using Member Function
- TPtrC Ptr1;
- Ptr1.Set(Buf);
- //例2、用TText*构造TPtrC
- const TText* text = _S(“Hello World\n”);
- TPtrC ptr(text);
- // 或者
- TPtrC Ptr2;
- Ptr2.Set(text);
- //如果要存储TText的一部分数据,我们使用下列方法
- TPtrC ptr4(text, 5);
- //例3、从另一个TPtrC中构造TPtrC
- const TText * text1 = _S(“Hello World\n”);
- TPtrC Ptr3(text1);
- // 从一个TPtrC中获得另一个TPtrC
- TPtrC p1(Ptr3);
- // 或
- TPtrC p2;
- p2.Set(Ptr3);
以上是不可修改的TPtrC的构造,相对应的也有可修改的TPtr的构造,不过我们下面省略了用Set()函数的构造方法
- //例1、通过TBufC,HBufC的Des()方法获取
- _LIT(KText, “Test Data”);
- TBufC<10> NBuf ( KText );
- TPtr Pointer = NBuf.Des();
- //例2、通过指定内存区域和大小来生成
- const TText * Text = _S(“Test Second”);
- TPtr Pointer1((TText*)Text, 11, 12);
- //例3、 通过另一个TPtr对象来生成
- TPtr Pointer2 ( Pointer );
对于可修改的TPtr虽然前面用过,但是我们在这里在简单的添加两个例子加深下印象,并且说明指针修改的始终是它指向的描述符:
- //例1、改变已有TPtr数据的方式:赋值和Copy()方法
- _LIT(KText, “Test Data”);
- _LIT(K1, “Text1″);
- _LIT(K2, “Text2″);
- TBufC<10> NBuf ( KText );//NBuf内容为“Test Data”
- TPtr Pointer = NBuf.Des(); //Pointer指向NBuf的内容
- Pointer = K1; // NBuf内容为“Text1”
- Pointer.Copy(K2); // NBuf内容为“Text2”
- //例2、直接通过修改长度改变数据内容
- Pointer.SetLength(2); // NBuf内容为”Te” 注:实际内存的内容应该没变
- const unsigned char KBuffer[ ] = {0×00, 0×33, 0×66, 0×99, 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”
5、 抽象描述符
抽象描述符,没有什么好说的,正如前面所说,只用在函数的形参中,通常要强调参数是不可修改的,就用const TDesC&表示,可修改的参数用TDesC&表示。
- 在函数参数中尽量使用基类
- 使用中性的描述符,一般情况下使用TDesC而不是TDesC8或者TDesC16
- 当描述符内容不应该改变时,使用const修饰符
- 经典用法:void SetText(const TDesC& aText); TPtrC Text() const;
描述符之间的转换
不可修改向可修改描述符的转换
原则1:通过不可修改描述符类内的Des()函数,将不可修改的描述符转换成可修改的指针描述符
示例1:TBufC转换成TPtr
- _LIT(KText, “Test Data”);
- TBufC<10> NBuf ( KText );
- TPtr Pointer = NBuf.Des();
示例2:HBufC转换成TPtr
- HBufC * Buf = HBufC::NewL(15);
- _LIT (KText , “Test Text”);
- *Buf = KText;
- TPtr Pointer = Buf->Des();
原则2:通过TPtr的构造函数或Set()函数可以将TPtrC描述转换为可修改的指针描述符
示例3:TPtrC到TPtr
- const TText * text1 = _S(“Hello World\n”);
- TPtrC Ptr1(text1);
- TPtrC Ptr2(Ptr1);
- //可以通过构造函数
- TPtr Ptr3((TUint16 *)(Ptr1.Ptr()), Ptr1.Length());
- //也可以通过Set()函数
- Ptr3.Set((TUint16 *)(Ptr1.Ptr()),Ptr1.Length(), Ptr1.Length());



