(1)First,Next方法
void FirstNextTest()
{
char string[] = "A string\tof ,,tokens\nand some more tokens";
char seps[] = " ,\t\n";
char *token;
token = strtok( string, seps );
while( token != NULL )
{
cout << token << endl;
token = strtok( NULL, seps );
}
cout << endl;
}
這種遍歷方式實際上就是有一個GetFirst方法,如果GetFirst成功, 接下來就可以不斷地GetNext遍歷。{
char string[] = "A string\tof ,,tokens\nand some more tokens";
char seps[] = " ,\t\n";
char *token;
token = strtok( string, seps );
while( token != NULL )
{
cout << token << endl;
token = strtok( NULL, seps );
}
cout << endl;
}
上面的 strtok( string, seps )實際上就是GetFirst, strtok( NULL, seps )實際上就是GetNext。
類似的還有Windows API,如 FindFirstFile, FindNextFile等。
(2)Callback遍歷方法
該方式通過讓我們在開始遍歷時設置一個callback函數, 當找到符合條件的數據時, 通過調用我們設置的callback把數據發回來。
典型例子是Windows枚舉窗口的API:
typedef BOOL (CALLBACK* WNDENUMPROC)(HWND, LPARAM);
BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam );
(3)Index遍歷方法
該方法通過暴露2個API來實現,GetCount和GetItemByIndex,前者返回總的數量,后者根據索引返回某個Item。
我們通常實現的operator[](int nIndex)實際也是這種方法。
(4)COM里IEnum方法
IEnum接口包含4個方法:
HRESULT Reset(); //重置到起始狀態
HRESULT Next(ULONG celt, XXX* ppGet, ULONG* fetched); //嘗試去取celt個元素
HRESULT Skip(ULONG celt); //跳過下面的celt個元素
HRESULT Clone(IEnumXXX** ppEnum); //克隆一個當前狀態的Enum接口
應該說IEnum接口對于我們的遍歷需求來說,它很完整也很強大。
(5)C#里的IEnumerable和IEnumerator方法
如果一個類支持枚舉,它會實現IEnumerable接口, IEnumerable接口就一個簡單的方法: IEnumerator GetEnumerator()
IEnumerator接口包含3個方法:
void Reset(); //重置
Object Current(); //取得當前對象
bool MoveNext(); //指向下一個對象,如果沒有下一個對象,返回False
可以看到C#的接口和COM的IEnum接口其實很類似。
(6)Iterator方法
這是STL的推薦方法, 我們知道Iterator在STL是容器和算法的粘合劑, 也是讓算法獨立于容器的隔離層。
我們可以通過STL的begin(), end(), operator++實現上面枚舉方式的遍歷。
仔細觀察我們會發現iterator是比上面enum方式更高層次的抽象, Iterator支持InputIterator, OutputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, 而上面的IEnum實際上只是ForwardIterator的一種實現。
(7)C++11的foreach方法
C++11的foreach本質上也是iterator的一種封裝, 只要你的類符下面的規范,它就能支持foreach:
> 實現 begin()和end()方法
> 返回的Iterator支持operator*, operator!=, operator++
具體可以參考C++11 range-based for loops
最后簡單總結下,如果沒有特殊情況, 在C++編程中個人還是推薦盡量用Iterator的方式,因為這種方式可以更好的和STL算法融合在一起。不知道大家還有沒有其他的遍歷方式?
(3)Index遍歷方法
該方法通過暴露2個API來實現,GetCount和GetItemByIndex,前者返回總的數量,后者根據索引返回某個Item。
我們通常實現的operator[](int nIndex)實際也是這種方法。
(4)COM里IEnum方法
IEnum接口包含4個方法:
HRESULT Reset(); //重置到起始狀態
HRESULT Next(ULONG celt, XXX* ppGet, ULONG* fetched); //嘗試去取celt個元素
HRESULT Skip(ULONG celt); //跳過下面的celt個元素
HRESULT Clone(IEnumXXX** ppEnum); //克隆一個當前狀態的Enum接口
應該說IEnum接口對于我們的遍歷需求來說,它很完整也很強大。
(5)C#里的IEnumerable和IEnumerator方法
如果一個類支持枚舉,它會實現IEnumerable接口, IEnumerable接口就一個簡單的方法: IEnumerator GetEnumerator()
IEnumerator接口包含3個方法:
void Reset(); //重置
Object Current(); //取得當前對象
bool MoveNext(); //指向下一個對象,如果沒有下一個對象,返回False
可以看到C#的接口和COM的IEnum接口其實很類似。
(6)Iterator方法
這是STL的推薦方法, 我們知道Iterator在STL是容器和算法的粘合劑, 也是讓算法獨立于容器的隔離層。
我們可以通過STL的begin(), end(), operator++實現上面枚舉方式的遍歷。
仔細觀察我們會發現iterator是比上面enum方式更高層次的抽象, Iterator支持InputIterator, OutputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, 而上面的IEnum實際上只是ForwardIterator的一種實現。
(7)C++11的foreach方法
C++11的foreach本質上也是iterator的一種封裝, 只要你的類符下面的規范,它就能支持foreach:
> 實現 begin()和end()方法
> 返回的Iterator支持operator*, operator!=, operator++
具體可以參考C++11 range-based for loops
最后簡單總結下,如果沒有特殊情況, 在C++編程中個人還是推薦盡量用Iterator的方式,因為這種方式可以更好的和STL算法融合在一起。不知道大家還有沒有其他的遍歷方式?