بخش ۱۷ - کتابخانهی STL
در این بخش مثالهایی از استفاده از کتابخانهی استاندارد STL مورد بررسی قرار میگیرند.
فهرست مثالها
در این مثال، عناصر یک بردار با استفاده از تکرارکننده پیمایش میشوند.
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v; v.push_back(10); v.push_back(123); v.push_back(87); vector<int>::iterator it = v.begin(); while (it != v.end()) { cout << *it << ' '; ++it; } cout << endl; for (vector<int>::iterator it2 = v.begin(); it2 != v.end(); ++it2) cout << *it2 << ' '; cout << endl; }
در این مثال، جستجو به دنبال یک عنصر در یک بردار توسط تابع find که در کتابخانهی STL تعریف شده صورت میگیرد. همین تابع را برای یافتن یک کلمه در یک لیست پیوندی از رشتهها و یک عدد اعشاری در آرایهای از اعداد نیز بهکار خواهیم برد.
#include <iostream> #include <vector> #include <string> #include <list> #include <algorithm> using namespace std; /* template<typename I, typename T> I find(I first, I last, const T& val) { while (first!=last && *first != val) ++first; return first; } */ int main() { vector<int> v; v.push_back(10); v.push_back(123); v.push_back(87); vector<int>::iterator p = find(v.begin(), v.end(), 123); if (p != v.end()) cout << "Found " << *p << endl; else cout << "Not found" << endl; list<string> words; words.push_back("Money"); words.push_back("For"); words.push_back("Nothing"); list<string>::iterator q = find(words.begin(), words.end(), "Chicks"); if (q != words.end()) cout << "Found " << *q << endl; else cout << "Not found" << endl; double nums[] = {1.4, 50.1, 3.5}; double *r = find(nums, nums + sizeof(nums)/sizeof(double), 50.1); if (r != nums + sizeof(nums)/sizeof(double)) cout << "Found " << *r << endl; else cout << "Not found" << endl; }
در این مثال لیست پیوندی که در بخش ۱۵ نوشته شد را به تکرارکنندهای به سبک STL مجهز میکنیم. به این ترتیب از این لیست در بسیاری از الگوریتمهای STL میشود استفاده کرد.
#include <iostream> #include <algorithm> #include <numeric> #include <vector> #include <string> using namespace std; template<typename T> class List { private: public: class Iterator : public iterator<input_iterator_tag, T> { private: Iterator(Node* n) { current = n; } friend class List; public: Iterator& operator++() { if (current != NULL) current = current->next; return *this; } T& operator*() { return current->data; } bool operator==(const Iterator& it) { return current == it.current; } bool operator!=(const Iterator& it) { return current != it.current; } private: Node *current; }; }; int main() { List<int> l; l.push_back(86); l.push_front(43); l.push_front(12); cout << accumulate(l.begin(), l.end(), 0) << endl; List<int>::Iterator it = find(l.begin(), l.end(), 43); if (it != l.end()) { cout << "found\n"; *it = 56; } else cout << "not found\n"; vector<string> v; v.push_back("gholi"); v.push_back("aroosi"); v.push_back("naraft!"); cout << accumulate(v.begin(), v.end(), string("")) << endl; double dd[3] = {1.2, 3.4, 67485.2}; cout << accumulate(dd, dd + 3, 0.0) << endl; }
این مثال نحوهی استفاده از تابع find_if در کتابخانهی STL را نشان میدهد. این تابع در یک مجموعه از عناصر به دنبال اولین عنصری میگردد که «شرط خاصی» را ارضاء کند. این شرط (که مسند یا predicate نام دارد) نامیده میشود، میتواند اشارهگر به تابع یا اصطلاحاً شیءتابع (function object) باشد که به معنی کلاسی است که عملگر پرانتز را سربارگذاری کرده است.
#include <iostream> #include <vector> #include <algorithm> using namespace std; /* template<class In, class Pred> In find_if(In first, In last, Pred pred) { while (first!=last && !pred(*first)) ++first; return first; } */ bool odd(int x) { return x % 2; } class OddSelector { public: bool operator()(int x) { return x % 2; } }; int main() { vector<int> v; v.push_back(10); v.push_back(39); v.push_back(42); vector<int>::iterator it = find_if(v.begin(), v.end(), odd); cout << *it << endl; vector<int>::iterator it2 = find_if(v.begin(), v.end(), OddSelector()); cout << *it2 << endl; }
این مثال، نشان میدهد استفاده از شیءتابعها میتواند پیشرفتهتر از مثال قبل باشد و شیء تابع مربوطه علاوه بر عملگر پرانتز اعضای دیگری هم داشته باشد. شیءتابع تعریف شده در این مثال، دانشجویان را بر اساس نمره cutoff فیلتر میکند. دقت کنید که اگر میخواستیم از اشارهگر به تابع استفاده کنیم لازم بود برای هر مقدار cutoff باید یک تابع مجزا مینوشتیم.
#include <iostream> #include <vector> using namespace std; /* template<class In, class Pred> In find_if(In first, In last, Pred pred) { while (first!=last && !pred(*first)) ++first; return first; } */ class student { public: student(string n, double d) : name(n), grade(d) {} string get_name() const { return name; } double get_grade() const { return grade; } private: string name; double grade; }; class GradeBelow { public: GradeBelow(double c) : cutoff(c) {} bool operator()(const student& s) { return s.get_grade() < cutoff; } private: double cutoff; }; int main() { vector<student> v; v.push_back(student("Moez", 8.0)); v.push_back(student("Gholam", 17.3)); v.push_back(student("Ghamar", 4.5)); vector<student>::iterator it; it = find_if(v.begin(), v.end(), GradeBelow(10)); cout << it->get_name() << endl; it = find_if(v.begin(), v.end(), GradeBelow(5)); cout << it->get_name() << endl; }