C++ find_first_of(STL find_first_of)查詢演算法詳解

2020-07-16 10:04:29
find_first_of() 演算法可以在第一個序列中搜尋第二個序列在第一個序列中第一次出現的任何元序列被搜尋的範圍由輸入疊代器指定,但用於確定搜尋序列的疊代器至少是正向疊代器。用 == 運算子來比較這兩個序列中的元素,所以如果序列中是類型別的物件,這個類必須實現 operator==()。下面是一個使用 find_first_of() 的範例:
string text {"The world of searching"};
string vowels {"aeiou"};
auto iter = std::find_first_of (std::begin (text), std:: end (text), std::begin (vowels),std::end(vowels));
if(iter != std::end(text))
    std::cout << "We found '" << *iter << "'." << std::endl; //We found 'e'.
這段程式碼會在 text 中查詢第一次出現的 vowels 中的任意字元。在這個範例中,返回的疊代器指向“The”的第三個字母。可以用迴圈來查詢 text 中所有匹配 vowels 中字元的字元:
string found {}; // Records characters that are found
for(auto iter = std::begin(text);(iter = std::find_first_of (iter,std::end (text),std::begin(vowels),std::end(vowels)))!= std::end(text);)
        found += *(iter++);
std::cout << "The characters "" << found << "" were found in text." << std::endl;
為了展示我們可以這樣做,這裡使用了 for 迴圈。第一個迴圈控制表示式以 text 的開始疊代器為初值定義了 iter。第二個迴圈控制表示式呼叫 find_first_of(),在 [iter,std::end(text))  這段範圍內搜尋第一次出現的 vowel 中的字元。

find_first_of() 返回的疊代器儲存在 iter 中,然後它被用來和 text 的結束疊代器進行比較。如果 iter 現在是 text 的結束疊代器,迴圈結束。如果 iter 不是 text 的結束疊代器,迴圈體會將這個字元附加到 iter 指向的 found 字串上,然後自增 iter,使它指向下一個字元。這個字元會作為下一次搜尋的開始位置。這段程式碼產生的輸出為:

The characters "eooeai" were found in text.

另一個版本的 find_first_of() 可以讓我們在第二個序列中搜尋指定範圍內的,可以使第 5 個引數指定的二元謂詞返回 true 的元素。這個序列中的元素不必是同種型別。當這個 == 運算子不支援所有這些元素的比較時,就可以用這個版本的演算法來定義相等比較,但也可以用其他的方式來定義。例如:
std::vector<long> numbers{64L, 46L, -65L, -128L, 121L, 17L, 35L, 9L, 91L, 5L};
int factors[] {7, 11, 13};
auto iter = std::find_first_of(std::begin(numbers),std::end(numbers),std::begin(factors), std::end(factors),[](long v, long d) { return v % d == 0; });// Predicate - true for a match
if (iter != std::end (numbers))
    std::cout << *iter << " was found." << std::endl;
這個謂詞是一個 lambda 表示式,當第一個引數可以被第二個引數整除時,它返回 true。

所以這段程式碼會找到 -65,因為這是 numbers 中第一個可以被 factors 陣列中的元素 13 整除的元素。斷言中的引數型別可以和序列元素的型別不同,只要每個序列中的元素可以隱式轉換為引數所對應的型別。在這裡,factors 中的元素可以隱式轉換為 long 型別。

當然,可以用迴圈來查詢所有使謂詞返回 true 的元素:
std::vector<long> numbers {64L, 46L, -65LA -128L, 121L, 17L, 35L, 9L, 91L, 5L};
int factors[] {7, 11, 13};
std::vector<long> results;  // Stores elements found
auto iter = std::begin (numbers);
while ((iter = std:: find_first_of (iter, std::end (numbers),std::begin(factors), std::end(factors),[](long vr long d) { return v % d == 0; }))!= std::end(numbers))
    results.push_back(*iter++);
std::cout << results.size() <<" values were found:n";
std::copy(std::begin(results), std::end(results),std::ostream_iterator < long > {std::cout," " });
std::cout << std::endl;
這段程式碼可以找出 numbers 中所有以 factors 中的一個元素為因子的元素。while 迴圈會持續進行,只要 find_first_of() 返回的疊代器不是 numbers 的結束疊代器。iter 變數開始時指向 numbers 的第一個元素,然後會用它來儲存被找到元素的疊代器,先前的值被覆蓋。在迴圈體中,iter 指向的元素會被儲存到 result 容器中,然後 iter 自增指向下一個元素。當迴圈結束時,results 包含的是找到的所有元素,然後用 copy() 演算法輸出它們。