一、_LIT宏
在讨论描述符之前,有必要来看下_LIT宏
可以用它引入一个字符串常量, 如_LIT(KText, "OK");
KText并不是描述符,而是TLiC类型,TLiC类的定义在<e32std.h>,3rd fp1 将其定义在<e32cmn.h>,其中有一个public变量,TUint iTypeLength; 表示字符串的长度
可以通过3种方式转换为描述符:隐式转换,使用operator()转换和使用operator&转换,《Series 60应用程序开发》P74讲到了,
在<e32std.inl>中可以看到的转换函数的定义
// Template class TLitC
// 使用operator&转换
template <TInt S>
inline const TDesC* TLitC<S>::operator&() const
{return REINTERPRET_CAST(const TDesC*,this);}
// 使用operator()转换
template <TInt S>
inline const TDesC& TLitC<S>::operator()() const
{return *operator&();}
// 以下两种是隐式转换
template <TInt S>
inline TLitC<S>::operator const TDesC&() const
{return *operator&();}
template <TInt S>
inline TLitC<S>::operator const __TRefDesC() const
{return *operator&();}
在<e32std.h>,3rd fp1 <e32cmn.h>中有下面几个常量,有时你会用到的
_LIT(KNullDesC,"");
_LIT8(KNullDesC8,"");
_LIT16(KNullDesC16,"");
另外很多人也许会用到 _L宏,因为比较方便,但很多书上说相比_LIT宏,它具有效率低和作用域相关问题,建议使用_LIT宏。
二、TDesC
在<e32des16.h>中,TDesC16类定义有:
private:
#if defined(__DESC_NO_BIT_FIELDS__)
TUint iLength;
#else
unsigned int iLength:28;
unsigned int iType:4;
#endif
__DECLARE_TEST;
这里不是太懂,
我们只看其中两个成员变量,iLength和iType。
1、iLength表示对象的长度, 可以通过成员函数Length()来获得, Length()就是返回字符的个数?不一定,请看下面的代码,本人分三种情况进行分析。
_LIT(KFormat, "%d");
_LIT(KNEWLINE,"/n");
TInt ITemp;
// 先看下无汉字时的情况
_LIT8(KOkText8, "OK");
_LIT16(KOkText16, "OK");
//使用operator()转换,然后使用TDesC8::Length(); 得ITemp == 2
ITemp = KOkText8().Length();
console->Printf(KFormat, ITemp);
console->Printf(KNEWLINE);
// ITemp == 2
ITemp = KOkText16().Length();
console->Printf(KFormat, ITemp);
console->Printf(KNEWLINE);
// 再来看下汉字的情况
_LIT8(KCnText8, "中国");
_LIT16(KCnText16, "中国");
// 请注意这时ITemp == 4 而不是2
ITemp = KCnText8().Length();
console->Printf(KFormat, ITemp);
console->Printf(KNEWLINE);
// ITemp == 2 (但在3rd中 == 4)
ITemp = KCnText16().Length();
console->Printf(KFormat, ITemp);
console->Printf(KNEWLINE);
//最后看下有汉字时的另一种情况(这种情况有点复杂,因为牵涉到编码知识)
我们在编译器里写的代码(如上面)的编码默认是ANSI, 如果你在ANSI的编码输入汉字,那么他实际就是GBK的编码方式,还有一种我们可能要用到的编码UTF-8,如下代码
_LIT8(KText8, "中国");
来源:(http://blog.sina.com.cn/s/blog_4a774f1e010099f4.html) - symbian 描述符问题_Love_新浪博客
_LIT16Text16, "中国");
将其保存到Common.h头文件中,同时将其保存为UTF-8编码。
在cpp文件中有
// 请注意这时ITemp == 6 而不是4,更不是2, 原因有点复杂,但可以确定的是一个汉字返回的Length()是3
ITemp = KText8().Length();
console->Printf(KFormat, ITemp);
console->Printf(KNEWLINE);
// ITemp == 2 (但在3rd中 == 6)
Temp = KText16().Length();
console->Printf(KFormat, ITemp);
console->Printf(KNEWLINE);
2、iType感觉是用于区别具体派生类的类型, 本人试了下,iType的值为
0: HBufC 和 TBufC
1: TPtrC
3: TBuf
4: TPtr
所有描述符的基类是TDesC,该类实际上为一个抽象类,在symbian的头文件中,该对象的所有构造函数都为protected。因此你无法创建TDesC,也永远不会(应该说你不应该)出现如下的语句: TDesc des。但是symbian可能疏忽了,也比较程序容易出错的是,它没有屏蔽C++自动产生的拷贝构造函数。因此下面的语句没有任何编译警告:
extern TPtrC ptr; //TPtrC是TDesC的派生类
TDesC des = ptr; //调用默认的拷贝构造函数,造成slice切割
foo(des); //调用一个函数,需要const TDesC&参数,由于数据已被切割,结果无法预料。
它主要用于函数参数传递,作为函数参数时,不是const TDesC& des,就是const TDesC× des,
三、TBuf、TBufC
_LIT(KText, "123");
// or TBuf<10> BufTemp = KText; (但在3rd中会报错,很奇怪)
TBuf<10> BufTemp(KText);
// 再看下面代码
TText cstr[3] = {'1', '2', '3'};
TBuf<10> BufTemp1(&cstr[0]);
TBuf<10> BufTemp2(cstr);
TBuf<10> BufTemp3= cstr;
TBuf<10> Buftemp4(BufTemp1);
上面的代码在编译的时候不会出问题,但在运行的时候在会报USER 11的越界错误,将TText cstr[3] = {'1', '2', '3'};改为TText cstr[3] = {'1', '2'};就可以了,这种错误有时很难发现,建议初始化TText变量时最好在最后加上'/0',即改为TText cstr[3] = {'1', '2','/0'};
四、TPtr、TPtrC
1、利用TBufC对其初始化
_LIT(KText, "123");
// or TBufC<50> BufCTemp = KText; (但在3rd中会报错,很奇怪)
TBufC<50> BufCTemp(KText);
TPtr ptr1 = BufCTemp.Des();
TPtr ptr2(BufCTemp.Des());
//TPtr ptr3(BufCTemp); // 报错
TPtrC ptrC1 = BufCTemp;
TPtrC ptrC2(BufCTemp);
2、利用TBuf对其初始化
//TBuf<50> BufTemp = KText; //(但在3rd中会报错,很奇怪)
TBuf<50> BufTemp(KText);
//TPtr ptr1 = BufCTemp.Des();// 报错
//TPtr ptr2(BufCTemp.Des()); // 报错
//TPtr ptr3(BufCTemp); // 报错
TPtrC ptrC1 = BufTemp;
TPtrC ptrC2(BufTemp);
上面的报错原因你可以参考SDK文档
最后:字符串之间的转换
1、char 到 TBuf
char* aShortName="123";
TText16 a[20]; // or TUint16 a[20];
TInt i;
for (i =0; i<strlen(aShortName); i++)
{
a[i] = aShortName[i];
}
a[i]='/0';
TBuf<20> bufShortName ;
bufShortName = a;
2、
to be continued。。。。。。。。。