調查顯示企業IT技術員工面臨短缺

phphot發表於2008-02-20

RArray和RPointerArray是沒有Delete方法的,換句話說是,只能新增,不能刪除,CArray提供了刪除的功能,比起CRarray和CPointerArray來顯得更加靈活。

CArray的儲存方式分為連續儲存(Flat)和分段儲存(Segmented buffer)兩種。

對於Flat方式,多用於查詢比較頻繁的地方。對於Segmented方式,多用於儲存空間大小經常發生變化的時候。

由於存在連續儲存和分段儲存兩種不同形式的儲存,CArray可根據儲存形式和儲存內容的不同分為4種。

(1)Fix型別,每個元素都擁有相同的長度。

(2)Var型別,各元素擁有不同的長度,每給物件都儲存在各自的堆單元中,陣列空間中儲存著各個元素的指標。

(3)Pak型別,陣列中每個元素都有可變的長度,類似於描述符物件,每個元素前面都有其自身的長度資訊。

(4)Ptr型別,指標陣列。

在選擇儲存形式時,要考慮如下問題:

(1)是否需要經常的重新分配

(2)資料元素插入和刪除的頻率

(3)訪問資料成員的速度

 下表中列出了可以使用的CArray型別:

名稱 元素大小 緩衝器型別 用法
CArrayFixFlat 固定大小 平面 很少進行分配時,用於儲存固定大小的T類和R類物件
CArrayVarFlat 可變大小 平面 很少進行分配時,用於儲存可變大小的T類和R類物件
CArrayPtrFlat 指標 平面 很少進行分配時,用於物件指標
CArrayPakFlat 大小可變(壓縮) 平面 很少進行分配時,用於在一個堆單元中儲存可變大小的T類或R類物件
CArrayFixSeg 固定大小 片斷 頻繁進行分配時,用於儲存固定大小的T類和R類物件
CArrayVarSeg 可變大小 片斷 頻繁進行分配時,用於儲存可變大小的T類和R類物件
CArrayPtrSeg 指標 片斷 頻繁進行分配時,用於儲存物件指標

 從上表中,我們知道了CArray提供了多個版本的類用來提供給使用者更多的選擇。通常我們常用的有4種:

CArrayVarFlat:儲存可變長度元素,儲存方式為Flat。

CArrayVarSeg:儲存可變長度元素,儲存方式為Segment。

CArrayPakFlat:儲存固定的或者可變長度的元素,而且每個元素都保留自己的長度資訊。

CArrayPtrFlag:儲存陣列指標,儲存方式為Segment。

 下面,我們將使用CArrayFixFlat和CArrayFixSeg來寫一個例子,實際上,在下面的那個例子裡,兩個陣列是完全可以互換的,因此,我只需要寫一個就足夠了。

在給出例子之前,我們還要再講一下CArray的排序與查詢,由於CArray不同於RArray類,因此,在查詢與排序方面也是有很大區別的。

對於排序,我們首先要構造一個適當的鍵,這個鍵將是你排序的根本,在宣告鍵時要指明排序的型別、欄位偏移量和文字長度。其次,將鍵傳入Sort()方法中進行排序。

下表為CArray類不同型別時,所要用到的鍵型別:

名稱 鍵型別 說明
CArrayFixFlat TKeyArrayFix  
CArrayVarFlat TKeyArrayVar  
CArrayPtrFlat TKeyArrayFix派生類 需要特殊實現
CArrayPkgFlat TKeyArrayVar  
CArrayFixSeg TKeyArrayFix  
CArrayVarSeg TKeyArrayVar  
CArrayPtrSeg TKeyArrayFix派生類 需要特殊實現

由於下面的例子中,我們使用了CArrayFixFlat,因此我們的鍵就是TKeyArrayFix(依照上表),TKeyArrayFix(TInt anOffset,TKeyCmpText aType)。這兩個引數是:

TInt anOffset —類中欄位的偏移量

TKeyCmpText aType — 對應欄位的型別

對於第一個引數,Symbian中提供了一個_FOFF(c,f)巨集來取得類中欄位的偏移量,其中,c為類命,f為欄位命。如:_FOFF(TStudent,iSName);

對於第二個引數,我們通常是可以有據可循的,請見下表:

欄位型別 鍵型別
資料 ECmpTInt8、ECmpTInt16、ECmpTInt32、ECmpTInt、ECmpTUint8、ECmpTUint16、ECmpTUint32、ECmpTUint、ECmpTInt64
文字 ECmpNormal、ECmpNormal8、ECmpNormal16、ECmpFolded、ECmpFolded8、ECmpFolded16、ECmpCollated、ECmpCollated8、ECmpCollated16、

class TStudent
{
public:
TStudent(const TDesC& aSName,TUint aSNo,TReal aScore);
public:
TUint iSNo;
TReal iScore;
TBuf<10> iSName;
};

TStudent::TStudent(const TDesC& aSName,TUint aSNo,TReal aScore)
{
iSNo = aSNo;
iScore = aScore;
iSName = aSName;
}

void ManageStu()
{
//使用CArrayFixFlat,很少進行分配時,用於儲存固定大小的T類和R類物件

//這裡也可以改成CArrayFixSeg<TStudent>* StuArraySeg;
CArrayFixFlat<TStudent>* StuArrayFlat;
StuArrayFlat = new(ELeave)CArrayFixFlat<TStudent>(5);
//壓入清理棧
CleanupStack::PushL(StuArrayFlat);
//分配空間儲存兩個學生的資訊
_LIT(KSTUDENT1,"GuanYabei");
_LIT(KSTUDENT2,"WuMingshi");
_LIT(KRETURN,"/n");
TBuf<10> StuName1 = KSTUDENT1;
TBuf<10> StuName2 = KSTUDENT2;
//初始化兩個學生的資訊(姓名,學號,分數)
TStudent stu1(StuName1,1,100.0);
TStudent stu2(StuName2,2,99.5);
//新增到陣列中,請注意,用到的是AppendL()方法,它是可能引起異常的
StuArrayFlat->AppendL(stu1);
StuArrayFlat->AppendL(stu2);
_LIT(KFORMAT2,"id is %d");
_LIT(KFORMAT3,"score is %f");

//顯示所有的學生資訊
for(TInt i=0;i<StuArrayFlat->Count();i++)
{
console->Printf(_L("name is "));

console->Printf((*StuArrayFlat)[i].iSName);
//如果你覺得指標括號太多而不夠美觀,我們也可以使用另一種方法
//即,使用At()函式,如:console->Printf(StuArrayFlat->At(i).iSName);
console->Printf(KRETURN);
console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
console->Printf(KRETURN);
console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
console->Printf(KRETURN);
}
console->Printf(_L("Press any key to continue/n"));
console->Getch();

//刪除陣列中的元素
console->Printf(_L("Delete first Student/n"));
StuArrayFlat->Delete(0);
for(i=0;i<StuArrayFlat->Count();i++)
{
console->Printf(_L("name is "));
console->Printf((*StuArrayFlat)[i].iSName);
console->Printf(KRETURN);
console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
console->Printf(KRETURN);
console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
console->Printf(KRETURN);
}
console->Printf(_L("Press any key to continuce/n"));
console->Getch();

//修改第一個學生的姓名
console->Printf(_L("Modify first student's name/n"));
console->Printf(_L("first student old name is "));
console->Printf((*StuArrayFlat)[0].iSName);
console->Printf(KRETURN);
(*StuArrayFlat)[0].iSName = _L("GuanYabei");
console->Printf(_L("first student new name is "));
console->Printf((*StuArrayFlat)[0].iSName);
console->Printf(KRETURN);
console->Printf(_L("Press any key to continue/n"));
console->Getch();

//以姓名方式查詢
console->Printf(_L("Find student by name/n"));
//建立主鍵,對於不同型別的CArray有不同的主鍵型別
TKeyArrayFix nameKey(_FOFF(TStudent,iSName),ECmpNormal);

//_FOFF(c,f)巨集來取得類中欄位的偏移量
TInt findPos;
TStudent S(StuName1,0,0);
console->Getch();
if(StuArrayFlat->Find(S,nameKey,findPos)!=KErrNotFound){

//查詢物件是S,按ECmpNormal格式
console->Printf(_L("findPos is %d "),findPos);
console->Printf((*StuArrayFlat)[findPos].iSName);//直接引用findPos的值,有的書上寫findPos-1,這是錯誤的!
}
console->Printf(KRETURN);
console->Printf(_L("Press any key to continue/n"));
console->Getch();

TKeyArrayFix scoreKey(_FOFF(TStudent,iScore),ECmpTInt32);
User::LeaveIfError(StuArrayFlat->Sort(scoreKey));
for(i=0;i<StuArrayFlat->Count();i++)
{
console->Printf(_L("name is "));
console->Printf((*StuArrayFlat)[i].iSName);
console->Printf(KRETURN);
console->Printf(KFORMAT2,(*StuArrayFlat)[i].iSNo);
console->Printf(KRETURN);
console->Printf(KFORMAT3,(*StuArrayFlat)[i].iScore);
console->Printf(KRETURN);
}
CleanupStack::PopAndDestroy();
//delete StuArrayFlat;

}

 

相關文章