Presentation is loading. Please wait.

Presentation is loading. Please wait.

John Lambert jlambert@jlambert.com STL John Lambert jlambert@jlambert.com.

Similar presentations


Presentation on theme: "John Lambert jlambert@jlambert.com STL John Lambert jlambert@jlambert.com."— Presentation transcript:

1 John Lambert jlambert@jlambert.com
STL John Lambert

2 Copyright © 1998 J. D. Birdwell
Overview Motivation What is the STL? Where did it come from? Template review (?) Containers Iterators Algorithms Glossed-over stuff Copyright © 1998 J. D. Birdwell

3 Every line of code you don’t write is bug-free.
Why learn the STL? Every line of code you don’t write is bug-free. Copyright © 1998 J. D. Birdwell

4 Copyright © 1998 J. D. Birdwell
Perspective I’m going to blast through most of the STL The syntax can always be looked up Common sticking points will be mentioned Figuring out the right applications is trickier “Advanced” features glossed over Sneak in some “generic programming” though Eye towards you actually using it Start off by diving in… Copyright © 1998 J. D. Birdwell

5 Copyright © 1998 J. D. Birdwell
Example 1 Read in an arbitrary number of integers (n >= 1) from “numbers.txt” and display: Minimum, maximum Median Average Geometric mean ((y1 * y2 * … yn)^(1/n)) How many lines would it take you? arbitrary storage (for median), sorting, loops… Copyright © 1998 J. D. Birdwell

6 Copyright © 1998 J. D. Birdwell
Example 1: STL solution vector<int> v; copy(istream_iterator<int>(ifstream("numbers.txt")), istream_iterator<int>(), back_inserter(v)); sort(v.begin(), v.end()); cout << "min/max: " << v.front() << " " << v.back() << endl; cout << "median : " << *(v.begin() + (v.size()/2)) << endl; cout << "average: " << accumulate(v.begin(), v.end(), 0.0) / v.size() << endl; cout << "geomean: " << pow(accumulate(v.begin(),v.end(),1.0,multiplies<double>()), 1.0/v.size()) << endl; Seven (7) lines with the STL (excluding #includes) 1 line to declare data structure 1 line to read the file in 1 line to sort it 1 expression for each item to display, 4 lines Copyright © 1998 J. D. Birdwell

7 Copyright © 1998 J. D. Birdwell
Example 2 Write a program that outputs the words and the number of times it occurs in a file (sorted by word) File input, hashtable, hash function… Copyright © 1998 J. D. Birdwell

8 Copyright © 1998 J. D. Birdwell
Example 2: STL solution vector<string> v; map<string, int> m; copy(istream_iterator<string>(ifstream("words.txt")), istream_iterator<string>(), back_inserter(v)); for (vector<string>::iterator vi = v.begin(); vi != v.end(); ++vi) ++m[*vi]; for (map<string, int>::iterator mi = m.begin(); mi != m.end(); ++mi) cout << mi->first << ": " << mi->second << endl; Seven lines: 2 lines for data structures 1 lines to read in 2 lines to count 2 lines to display Copyright © 1998 J. D. Birdwell

9 Copyright © 1998 J. D. Birdwell
What is the STL? “Standard Template Library” Basic motivation: N data types, M containers, and K algorithms Possibly N *M *K implementations CountIntegerInList(IntList il, int toFind), CountIntegerInSet, CountDoubleInList, etc. STL (with C++ templates): N +M +K implementations algorithms operate over containers of types set<int> mySet; count(mySet.begin(), mySet.end(), 4); list<double> myList; count(myList.begin(), myList.end(), 3.14); Copyright © 1998 J. D. Birdwell

10 Copyright © 1998 J. D. Birdwell
Platforms STL is part of Standard C++ In Visual C++/Studio 6.0 Missing some stuff: hash_map In Visual Studio.NET / VC++ 7.0 Still some issues G++ 3.0: dunno Stlport.org Free std C++ implementation (including iostreams), some nice features/performance Copyright © 1998 J. D. Birdwell

11 Copyright © 1998 J. D. Birdwell
Where did it come from? Alex Stepanov “In 1976, still back in the USSR, I got a very serious case of food poisoning from eating raw fish.” “While in the hospital, in the state of delirium, I suddenly realized that the ability to add numbers in parallel depends on the fact that addition is associative.” (Huh?) “Putting it simply, STL is the result of a bacterial infection.” (That I can understand.) Copyright © 1998 J. D. Birdwell

12 Copyright © 1998 J. D. Birdwell
STL overview Fundamentally, the STL defines algorithms that operate over a range in a container Our order: Containers Iterators (ranges) Algorithms Copyright © 1998 J. D. Birdwell

13 Copyright © 1998 J. D. Birdwell
Containers Lists vector, list, deque Adaptors queue, priority_queue, stack Associative map, multimap, set, multiset hash_{above} Copyright © 1998 J. D. Birdwell

14 Copyright © 1998 J. D. Birdwell
vector<T> #include <vector> A dynamic array: random-access, grows Array-indexing syntax: vector<int> v(10); v[0] = 4; Copyright © 1998 J. D. Birdwell

15 Copyright © 1998 J. D. Birdwell
vector<T> Constructors vector<T>() vector<T>(size_t num_elements) vector<T>(size_t num, T init) Properties v.empty() // true if v has 0 elements v.size() // number of elements v.capacity() // number of elements v can hold before allocating more memory (cap ! nec. = size) Copyright © 1998 J. D. Birdwell

16 Copyright © 1998 J. D. Birdwell
vector<T> Adding elements v.push_back(42); // increases size v[0] = 31; // only ok if v.size() >= 1 v.insert(iter before, T val) // skipped v.insert(iter before, iter start, iter end) // skipped Accessing elements v.at(i) // reference, range checked! v[i] // reference, not range checked v.front() // reference to first element v.back() // reference to last element v.back() = 4; // legal if size > 0 Copyright © 1998 J. D. Birdwell

17 Copyright © 1998 J. D. Birdwell
vector<T> Removing elements v.pop_back(): removes last element, returns nothing v.clear(): removes everything v.erase(iterator i) // skipped v.erase(iter start, iter end) // skipped Copyright © 1998 J. D. Birdwell

18 Copyright © 1998 J. D. Birdwell
vector<T> Time: constant time insertion and removal of elements at the end linear time insertion and removal of elements at the beginning or in the middle. The “standard” container Copyright © 1998 J. D. Birdwell

19 vector<T> example
vector<char> v; for (int i = 0; i < 10; ++i) v.push_back('A' + i); cout << v[0] << v.back() << endl; // AJ v.pop_back(); // doesn't return anything cout << v.size() << v.back() << endl; // 9I for (size_t i = 0; i < v.size(); ++i) cout << v[i]; // ABCDEFGHI (no J) cout << endl; Copyright © 1998 J. D. Birdwell

20 Forward reference: Iterators
v.begin() and v.end() return iterators Like pointers: arithmetic (++, --) and dereferencing (*) for (vector<char>::iterator i = v.begin(); i != v.end(); ++i) cout << *i; // ABCDEFGHI (no J) Copyright © 1998 J. D. Birdwell

21 Copyright © 1998 J. D. Birdwell
list<T> Bidirectional, linear list Sequential access only (not L[52]) Constructors list<T>() list<T>(size_t num_elements) list<T>(size_t num, T init) Properties l.empty() // true if l has 0 elements l.size() // number of elements Copyright © 1998 J. D. Birdwell

22 Copyright © 1998 J. D. Birdwell
list<T> Adding elements l.push_back(43); l.push_front(31); l.insert(iter b, iter s, iter s) // and others, skipped Accessing elements l.front() // T & l.back() // T & l.begin() // list<T>::iterator l.end() // list<T>::iterator Copyright © 1998 J. D. Birdwell

23 Copyright © 1998 J. D. Birdwell
list<T> Removing elements l.pop_back() // returns nothing l.pop_front() // returns nothing l.erase(iterator i) l.erase(iter start, iter end) Time Amortized constant time insertion and removal of elements at the beginning or the end, or in the middle [because you pass an iterator] Copyright © 1998 J. D. Birdwell

24 Copyright © 1998 J. D. Birdwell
list<T> Other operations l.sort(), l.sort(CompFn) // sorts in place, can’t use normal sort function (why?) l.splice(iter b, list<T>& grab_from) Copyright © 1998 J. D. Birdwell

25 Copyright © 1998 J. D. Birdwell
list<T> Example: list<char> l; for (int i = 0; i < 4; ++i) { l.push_front(i + 'A'); l.push_back(i + 'A'); } for (list<char>::iterator i = l.begin(); i != l.end(); ++i) cout << *i; // DCBAABCD Copyright © 1998 J. D. Birdwell

26 Copyright © 1998 J. D. Birdwell
Step back! Notice anything? A lot of the functions (c.begin(), c.end()) are the same! So, write a “generic” display function… Now displaying a “supported” container is 1 line! template<typename Container> void display(Container & c) { for(Container::iterator i = c.begin(); i != c.end(); ++i) cout << *i << " "; cout << endl; } Wait for it, btw… Copyright © 1998 J. D. Birdwell

27 Copyright © 1998 J. D. Birdwell
deque<T> Double-ended queue Random access List: no d[i] Vector: no push_front Good for adding/removing at beginning Copyright © 1998 J. D. Birdwell

28 deque<T>: readers/writers
deque<char> d; srand(1337); for (int i = 0; i < N; ++i) { if (rand() % 2) // add a random letter to the back d.push_back((rand() % 26) + 'A'); else if (d.size()) // take the one in the front d.pop_front(); if (d.size()) display(d); } cout << d.size() << " elements left!" << endl; cout << "final: "; display(d); Readers/Writers, sorta Copyright © 1998 J. D. Birdwell

29 deque<T> example output
N N B B B I B I F B I F F B I F F K I F F K I F F K H F F K H F K H K H K H X K H X K K H X K F H X K F X K F Copyright © 1998 J. D. Birdwell

30 Copyright © 1998 J. D. Birdwell
deque<T>: time Constant time insertion and removal of elements at the beginning/end of the sequence Linear time insertion and removal of elements in the middle Copyright © 1998 J. D. Birdwell

31 Copyright © 1998 J. D. Birdwell
queue<T> First-in, first-out (FIFO) only front(), back(), push(), pop() No q[i] No iterators (need to write display_queue) An “adaptor”: uses a deque internally Could use a list (ads/disads): queue<T,list<T> > Same example as deque Copyright © 1998 J. D. Birdwell

32 queue<T> example
queue<char> q; srand(1337); for (int i = 0; i < N; ++i) { if (rand() % 2) // add a random letter to the back q.push((rand() % 26) + 'A'); // was d.push_back( else if (q.size()) // take the one in the front q.pop(); // was d.pop_front() if (q.size()) display_queue(q); } cout << q.size() << " elements left!" << endl; cout << "final: "; display_queue(q); Same output as before! Copyright © 1998 J. D. Birdwell

33 Copyright © 1998 J. D. Birdwell
display_queue Why couldn’t we use display<Container>? No iterators in queue! VC++ doesn’t have “partial template specialization”, so we can’t do: template<typename T, typename C> void display(const queue<T, C>& c) We need a new function... Q will expand to queue<T> or queue<T, list<T> > or whatever’s needed template<typename Q> void display_queue(const Q & q) { Q qc(q); // make copy while (!qc.empty()) { cout << qc.front() << " "; qc.pop(); } cout << endl; Copyright © 1998 J. D. Birdwell

34 priority_queue<T>
“Sorted” queue pop(), push(T t), size(), top() (instead of front()) Can take a comparison object in ctor Handwaving, we’ll come back to this Generally use bool operator<(T a, T b) Example: job scheduling A job has a name, priority, and user High (valued) priority jobs go first If tie, then lowest user goes first Copyright © 1998 J. D. Birdwell

35 Copyright © 1998 J. D. Birdwell
Job struct definition struct Job { string name; int user; int pri; Job(string n, int u, int p): name(n), user(u), pri(p){} }; Copyright © 1998 J. D. Birdwell

36 Copyright © 1998 J. D. Birdwell
Job helper operators ostream& operator<<(ostream& o, Job j) { o << j.name << "\tuser=" << j.user << ", pri=" << j.pri; return o; } bool operator<(Job j1, Job j2) { return (j1.pri < j2.pri) || (j1.pri == j2.pri && j1.user>j2.user); Copyright © 1998 J. D. Birdwell

37 Actual priority_queue<T> code
priority_queue<Job> pq; pq.push(Job("printer", 1, 5)); pq.push(Job("gcc", 200, 4)); pq.push(Job("kernel", 1, 10)); pq.push(Job("nfs", 1, 7)); pq.push(Job("irc", 800, 4)); pq.push(Job("ftpd", 1, 2)); pq.push(Job("pine", 100, 4)); while (!pq.empty()) // display { cout << pq.top() << endl; // uses operator<< pq.pop(); } Copyright © 1998 J. D. Birdwell

38 Copyright © 1998 J. D. Birdwell
Priority queue output kernel user=1, pri=10 nfs user=1, pri=7 printer user=1, pri=5 pine user=100, pri=4 gcc user=200, pri=4 irc user=800, pri=4 ftpd user=1, pri=2 Copyright © 1998 J. D. Birdwell

39 Copyright © 1998 J. D. Birdwell
stack<T> Last in, first out (LIFO) push(), pop(), top(), size() Example: palindrome push letters on to stack pop them off and store in a different string if the strings are equal, it’s a palindrome terrible approach, but I needed an example Copyright © 1998 J. D. Birdwell

40 Copyright © 1998 J. D. Birdwell
stack<T> // returns true if input is a palindrome bool is_palindrome_naive(string input) { stack<char> st; for(int i = 0; i < input.size(); ++i) st.push(input[i]); // add to stack string back = ""; while (!st.empty()) { back += st.top(); st.pop(); } return (back == input); // this is where I cry Copyright © 1998 J. D. Birdwell

41 Copyright © 1998 J. D. Birdwell
Review (so far) vector: dynamic array, random access list: linked list, one-directional access deque: double-ended queue, random access queue: like deque, but just push, pop, front, back priority_queue: “sorted” queue, only push, pop, top stack: LIFO, push, pop, top Deep breath: only going to get cooler  Copyright © 1998 J. D. Birdwell

42 [hash_]map, [hash_]multimap
A map is an “associative container” Given one value, will find another map<string, int> is a map from strings to int’s maps are 1:1, multimap are 1:n map, multimap are logarithmic when inserting/deleting Needs to maintain sortedness hash_map, hash_multimap are amortized constant time Not sorted (“hashed”) Copyright © 1998 J. D. Birdwell

43 Copyright © 1998 J. D. Birdwell
Mmm… pairs… pair<KeyType, ValueType> is used with maps Can use pairs outside of (inside) maps, too Can create pair<K,V> objects with make_pair(k, v): pair<string, int> si("foo", 42); si = make_pair("bar", 24); Copyright © 1998 J. D. Birdwell

44 Generically output pairs?
template <typename T1, typename T2> ostream& operator<<(ostream& o, const pair<typename T1, typename T2> p) { o << "(" << p.first << ", " << p.second << ")"; return o;} cout << make_pair( make_pair("str", 31), make_pair(Job("kernel", 1, 3), 9) ) << endl; Output: ((str, 31), (kernel user=1, pri=3, 9)) Bonus: typeid(T1).name() is the data type’s name (double, int, etc.) Copyright © 1998 J. D. Birdwell

45 Copyright © 1998 J. D. Birdwell
Map functions m.insert(make_pair(key, value)); // inserts m.count(key); // times occurs (0, 1) m.erase(key); // removes it m[key] = value; // inserts it into the table m[key] //retrieves or creates a “default” for it m.begin(), m.end() // iterators Copyright © 1998 J. D. Birdwell

46 Copyright © 1998 J. D. Birdwell
Map example typedef pair<string, int> dorm_location; map<string, dorm_location> people; people.insert(make_pair("jrl7", dorm_location("staley", 810))); cout << people["jrl7"] << endl; // (staley, 810) cout << people["JRL7"] << endl; // (, 0) people["jrl7"] = dorm_location("pierce", 411); for (map<string, dorm_location>::iterator p = people.begin(); p != people.end(); ++p) cout << "Name: " << p->first << ": " << p->second << endl; // Name: JRL7: (, 0) // Name: jrl7: (pierce, 411) Note that just cout’ing people["JRL7"] inserted it into the map! We also overwrote my staley address with pierce p->first == (*p).first (C++ arrow notation) Copyright © 1998 J. D. Birdwell

47 Copyright © 1998 J. D. Birdwell
Multimap Like map, but 1:n instead Introduces new function: mm.upper_bound(key) is an iterator that comes after all the elements specified No more [ ] indexing, either mm.count(key) will return count (0, 1, .. N) Copyright © 1998 J. D. Birdwell

48 Copyright © 1998 J. D. Birdwell
Multimap example Output: 314 430 345 multimap<string, int> mm; mm.insert(make_pair("PSCL", 102)); mm.insert(make_pair("EECS", 314)); mm.insert(make_pair("EECS", 430)); mm.insert(make_pair("EECS", 345)); mm.insert(make_pair("PSCL", 101)); multimap<string, int>::iterator i = mm.find("EECS"); if (i != mm.end()) // we found some EECS do { cout << i->second << endl; ++i; } while (i != mm.upper_bound("EECS")); Copyright © 1998 J. D. Birdwell

49 Multimap example (continued)
// display all; could use display(mm)! for (i = mm.begin(); i != mm.end(); ) { const multimap<string, int>::iterator j = mm.upper_bound(i->first); cout << i->first<<' ' << mm.count( i->first) << ":"; do { cout << i->second << " "; ++i; } while(i != j && i != mm.end()); cout << endl; } Output: EECS 3: PSCL 2: Copyright © 1998 J. D. Birdwell

50 Copyright © 1998 J. D. Birdwell
Step back Now we’ve seen like 6 containers They’re all pretty similar We go through them with iterators similarly Code “patterns” Learn once, apply to others Copyright © 1998 J. D. Birdwell

51 Copyright © 1998 J. D. Birdwell
Set Unique values, sorted Somewhat like a map, except that the key = value Copyright © 1998 J. D. Birdwell

52 Copyright © 1998 J. D. Birdwell
Set example (using mm) set<string> depts; for (multimap<string, int>::iterator i = mm.begin(); i != mm.end(); ++i) depts.insert(i->first); display(depts); display(mm); EECS PSCL (EECS, 314) (EECS, 430) (EECS, 345) (PSCL, 102) (PSCL, 101) Copyright © 1998 J. D. Birdwell

53 Copyright © 1998 J. D. Birdwell
Multiset More than one key for a lot of items “An auto-sorted list” Counts quickly Copyright © 1998 J. D. Birdwell

54 Copyright © 1998 J. D. Birdwell
Multiset multiset<char> grades; grades.insert('A'); grades.insert('C'); grades.insert('D'); grades.insert('C'); grades.insert('F'); grades.insert('D'); grades.insert('B'); grades.insert('I'); display(grades); cout << grades.count('D') << endl; Output A B C C D D F I 2 Copyright © 1998 J. D. Birdwell

55 Copyright © 1998 J. D. Birdwell
Hash_{…} There are hash_map, hash_multimap, hash_set, hash_multiset Basically, these are constant time insert/delete instead of log time They don’t maintain sortedness Me: reduced running time from 10 min to 5 min Copyright © 1998 J. D. Birdwell

56 Copyright © 1998 J. D. Birdwell
Hash performance Fill with 100,000 random elements Lookup 200,000 random elements Same random seed map: fill s map: lookups s hash_map: fill s hash_map: lookups s So, if you don’t need order, go with hash_map Copyright © 1998 J. D. Birdwell

57 Classes in associative cont.
Can always put your classes in associative containers Must have a default (no-arg) constructor Must have global bool operator<(T a, T b) Might need == as well Don’t put pointers in! set<string*> ss; ss.insert(new string("foo")); cout << ss.size() << endl; // outputs 2! Copyright © 1998 J. D. Birdwell

58 Copyright © 1998 J. D. Birdwell
Summary map: 1:1, sorted, m[k] = v multimap: 1:n, sorted, mm.insert(make_pair(k,v)) set: unique elements, sorted multiset: multiple keys allowed, sorted hash_: faster but not sorted Copyright © 1998 J. D. Birdwell

59 Copyright © 1998 J. D. Birdwell
Iterators Touched on earlier An iterator is like a pointer You can increment to it to go to the “next” element You can [sometimes] subtract or add N You can dereference it Different kinds of iterators Most useful when combined with algorithms Copyright © 1998 J. D. Birdwell

60 Copyright © 1998 J. D. Birdwell
Iterators Copyright © 1998 J. D. Birdwell

61 Copyright © 1998 J. D. Birdwell
Iterators c.begin() = start c.end() = 1 past the last element Never dereference end! (*c.end() is bad!) Why? Makes loops simpler. Prefer ++i because i++ makes a temporary object and returns it, incrementing later. Copyright © 1998 J. D. Birdwell

62 Copyright © 1998 J. D. Birdwell
Different kinds Technically: random access (i += 3; --i; ++i) bidirectional (++i, --i), store/retreive forward (++i), store/retrieve input (++i) retrieve output (++o) store But, writing code directly using iterators hurts a lot Copyright © 1998 J. D. Birdwell

63 Copyright © 1998 J. D. Birdwell
Practical iterators iterator “Standard”, goes from beginning to end c.begin(), c.end() const_iterator Like iterator, but changes can’t be made (prefer!) c.begin() and c.end() are overloaded so you can use them to assign their result to a const_iterator reverse_iterator Goes from the end to the beginning with same semantics as iterator Generally, c.rbegin() and c.rend() list, vector, deque, map, multimap, set, multiset, hash_, string Copyright © 1998 J. D. Birdwell

64 Copyright © 1998 J. D. Birdwell
Iterator example vector<int> v; for (int k = 0; k < 7; ++k) v.push_back(k); display(v); // for(vector<int>::iterator i = v.begin(); i != v.end(); ++i) *i = *i + 3; // add three to content display(v); // for(vector<int>::const_iterator ci = v.begin(); ci != v.end(); ++ci) cout << *ci << ' ';// *ci = *ci - 3; won't compile cout << endl;// for (vector<int>::reverse_iterator ri = v.rbegin(); ri != v.rend(); ++ri) { *ri = *ri - 3; cout << *ri << ' ';} cout << endl; // Copyright © 1998 J. D. Birdwell

65 Copyright © 1998 J. D. Birdwell
“Insert” iterators back_inserter(Container) returns an iterator that calls push_back when assigned to front_inserter(Container) returns an iterator that calls push_front inserter(Container, where) is “generalized” inserter, works for sets, maps, etc. Example in a second or two Copyright © 1998 J. D. Birdwell

66 Array/iterator parallelism:
int A[] = {1, 4, 2, 8, 5, 7}; const int N = sizeof(A) / sizeof(int); for(int* i = A; i != A + N; ++i) cout << *i << ' '; Copyright © 1998 J. D. Birdwell

67 Copyright © 1998 J. D. Birdwell
Algorithms AKA: finally, the cool part  Basically, the STL provides 70 algorithms of general interest Pretty much all of them take in iterators and return iterators Hardest to wrap your mind around Not going to talk about function objects Copyright © 1998 J. D. Birdwell

68 General algorithm categories
Copying Searching unsorted sequences Searching sorted sequences Replacing/removing elements Reordering Sorting Merging sorted sequences Set operations Heap operations Minimum/maximum Permutations Transforming and generating Miscellanous Numeric Copyright © 1998 J. D. Birdwell

69 Copyright © 1998 J. D. Birdwell
All algorithms adjacent_find, binary_search, copy, copy_backward, count, count_if, equal, equal_range, fill, fill_n, find, find_end, find_first_of, find_if, for_each, generate, generate_n, includes, inplace_merge, iter_swap, lexicographical_compare, lower_bound, make_heap, max, max_element, merge, min, min_element, mismatch, next_permutation, nth_element, partial_sort, partial_sort_copy, partition, pop_heap, prev_permutation, push_heap, random_shuffle, remove, remove_copy, remove_copy_if, remove_if, replace, replace_copy, replace_copy_if, replace_if, reverse, reverse_copy, rotate, rotate_copy, search, search_n, set_difference, set_intersection, set_symmetric_difference, set_union, sort, sort_heap, stable_partition, stable_sort, swap, swap_ranges, transform, unique, unique_copy, upper_bound accumulate, adjacent_difference, inner_product, partial_sum Copyright © 1998 J. D. Birdwell

70 Copyright © 1998 J. D. Birdwell
Our algorithms copy, find, remove, unique, reverse, sort, min/max_element, count, accumulate, for_each, transform, equal Writing your own Copyright © 1998 J. D. Birdwell

71 Copyright © 1998 J. D. Birdwell
copy(b, e, Dest) vector<int> w, v; w.push_back(42); w.push_back(31); w.push_back(1); v.resize(w.size()); // needed copy(w.begin(), w.end(), v.begin()); vector<int> c; copy(w.begin(), w.end(), back_inserter(c)); // calls c.push_back deque<int> d; copy(w.begin(), w.end(), front_inserter(d)); // calls d.push_front display(v); // display(c); // display(d); // (b/c added to front) Copyright © 1998 J. D. Birdwell

72 copy + istream iterators
An istream iterator reads from an istream (file, console, etc.) until an eof is received Hopefully this makes sense now: vector<int> v; copy(istream_iterator<int>(ifstream("numbers.txt")), istream_iterator<int>(), back_inserter(v)); Note that the “end” iterator is istream_iterator<int>(); a special instance which indicates the EOF Copyright © 1998 J. D. Birdwell

73 copy + ostream iterators
Same goes for ostream_iterators: copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); Now, we can rewrite display in two lines, with no loops: template<typename Container> void display(const Container & c, string sep = " ") { copy(c.begin(), c.end(), ostream_iterator<Container::value_type>(cout, sep.c_str())); cout << endl; } Copyright © 1998 J. D. Birdwell

74 Copyright © 1998 J. D. Birdwell
i = find(b, e, val) Returns an iterator (or e if not found) if (find(v.begin(), v.end(), 31) != v.end()) cout << "Found 31." << endl; Copyright © 1998 J. D. Birdwell

75 Copyright © 1998 J. D. Birdwell
ne = remove(b, e, val) Doesn’t actually modify the end point: returns the new end point remove_copy(b, e, Dest, val) will remove val while copying to Dest v.clear(); for(int i = 0; i < 10; ++i) v.push_back(i); vector<int> vc; remove_copy(v.begin(), v.end(), back_inserter(vc), 4); display(vc); // vector<int>::const_iterator e = remove(v.begin(), v.end(), 4); display(v); // “extra 9” for (vector<int>::const_iterator vi = v.begin(); vi != e; ++vi) // not v.end() cout << *vi << ' '; cout << endl; // Copyright © 1998 J. D. Birdwell

76 Copyright © 1998 J. D. Birdwell
sort(b, e) Sorts a range; needs random access iterators N log N, average and worst case sort(v.begin(), v.end()); Will raise a compile time error if not supported Can sort normal arrays this way, too int A[] = {1, 4, 2, 8, 5, 7}; const int N = sizeof(A) / sizeof(int); sort(A, A + N); Copyright © 1998 J. D. Birdwell

77 Copyright © 1998 J. D. Birdwell
ne = unique(b, e) Doesn’t actually modify the end point unique_copy Removes “consecutive duplicate elements” Sort first if you want a “real unique” list Just like remove Linear Copyright © 1998 J. D. Birdwell

78 Copyright © 1998 J. D. Birdwell
reverse(b, e) Bidirectional iterators Reverses the range in-place Linear for(int i = 0; i < 10; ++i) v.push_back(i); display(v); // reverse(v.begin(), v.end()); display(v); // Copyright © 1998 J. D. Birdwell

79 Copyright © 1998 J. D. Birdwell
min/max_element(b,e) An iterator to the minimum/maximum element in a range (e if range is empty) (*min_element(..) is value) Doesn’t need to be sorted list<int> l; l.push_back(4); l.push_front(12); l.push_back(1); l.push_front(2); l.push_back(7); display(l); // cout << *min_element(l.begin(), l.end()) << endl; // 1 cout << *max_element(l.begin(), l.end()) << endl; // 12 Copyright © 1998 J. D. Birdwell

80 Copyright © 1998 J. D. Birdwell
count(b, e, V) Counts occurances of V in range b, e count_if(b, e, Func): bool iscomma(char c) { return c == ','; } string s = "(X,Y) or [X,Y]?"; cout << count_if(s.begin(), s.end(), iscomma) << endl; Outputs 2 Copyright © 1998 J. D. Birdwell

81 accumulate(b, e, initial)
in <numeric> Adds (+) up the values in the range b, e Iinitial is used if it’s an empty range As long as operator+ is defined, we’re good You can pass in a binary function to use instead of + (beyond scope) vector<string> vs; vs.push_back("This"); vs.push_back("Talk"); vs.push_back("Is"); vs.push_back("Way"); vs.push_back("Too"); vs.push_back("Long"); cout << accumulate(vs.begin(), vs.end(), string("")) << endl; // ThisTalkIsWayTooLong Copyright © 1998 J. D. Birdwell

82 Copyright © 1998 J. D. Birdwell
for_each(b, e, op) Call op(*i) for each i in range b, e; magical void display_backwards(string s) { // strings have reverse iterators copy(s.rbegin(), s.rend(), ostream_iterator<char>(cout)); } for_each(vs.begin(), vs.end(), display_backwards); // sihTklaTsIyaWooTgnoL Copyright © 1998 J. D. Birdwell

83 Copyright © 1998 J. D. Birdwell
for_each(b, e, op) Using “function objects”, you can do some neat stuff void truncate_word(string s, int len) { cout << s.substr(0, len); } for_each(vs.begin(), vs.end(), bind2nd(ptr_fun(truncate_word), 2)); // ThTaIsWaToLo Copyright © 1998 J. D. Birdwell

84 Copyright © 1998 J. D. Birdwell
transform My favorite; probably the most powerful algorithm Two forms: transform(b, e, out, UnaryFunc): Applies UnaryFunc to b, e and stores result in out string s = "hello"; string upcase, upcasebackwards; transform(s.begin(), s.end(), back_inserter(upcase), toupper); // reverse and upper case in one line transform(s.rbegin(), s.rend(), back_inserter(upcasebackwards), toupper); cout << upcase << " " << upcasebackwards << endl; // HELLO OLLEH // straight to screen transform(s.rbegin(), s.rend(), ostream_iterator<char>(cout), toupper); // OLLEH cout << endl; Copyright © 1998 J. D. Birdwell

85 Copyright © 1998 J. D. Birdwell
transform transform(Argument 1 beginning, Arg 1 end, Argument 2 beginning, output, BinaryFunction); typedef pair<double, double> point; point midpoint(point p1, point p2) { return point((p1.first + p2.first)/2.0, (p1.second + p2.second)/2.0); } vector<point> v1, v2; v1.push_back(point(0.0, 3.1)); v1.push_back(point(7.3, 8.1)); v1.push_back(point(9.1, -2.89)); v2.push_back(point(4.3, 9.3)); v2.push_back(point(1.3, 9.1)); v2.push_back(point(8.3, -3.1)); display(v1); // (0, 3.1) (7.3, 8.1) (9.1, -2.89) display(v2); // (4.3, 9.3) (1.3, 9.1) (8.3, -3.1) transform(v1.begin(), v1.end(), v2.begin(), ostream_iterator<point>(cout, " "), midpoint); // (2.15, 6.2) (4.3, 8.6) (8.7, ) Copyright © 1998 J. D. Birdwell

86 Copyright © 1998 J. D. Birdwell
bool equal(b, e, b2); Returns true if the ranges are identical Can rewrite is_palindrome: return equal(input.begin(), input.end(), input.rbegin()); “the string going forwards is the same as going backwards” Better: no space overhead Copyright © 1998 J. D. Birdwell

87 Writing own algorithms
Poor example… template<typename Iter, typename Val> void add_to_each(Iter b, Iter e, Val v) { while (b != e) { *b = *b + v; ++b; } vector<int> v; v.push_back(0); v.push_back(1); v.push_back(2); add_to_each(v.begin(), v.end(), 4); display(v); // 4 5 6 Copyright © 1998 J. D. Birdwell

88 Copyright © 1998 J. D. Birdwell
Review Let’s go back over the Examples at the beginning of the presentation Problem 1: Read in a list of numbers, min/max, avg, geo mean, median Problem 2: Read in a list of words and output the number of times each word occurs Copyright © 1998 J. D. Birdwell

89 Copyright © 1998 J. D. Birdwell
Example 1: STL solution vector<int> v; copy(istream_iterator<int>(ifstream("numbers.txt")), istream_iterator<int>(), back_inserter(v)); sort(v.begin(), v.end()); cout << "min/max: " << v.front() << " " << v.back() << endl; // could have used min/max_element but list already sorted cout << "median : " << *(v.begin() + (v.size()/2)) << endl; cout << "average: " << accumulate(v.begin(), v.end(), 0.0) / v.size() << endl; cout << "geomean: " << pow(accumulate(v.begin(),v.end(),1.0,multiplies<double>()), 1.0/v.size()) << endl; Seven (7) lines with the STL (excluding #includes) 1 line to declare data structure 1 line to read the file in 1 line to sort it 1 expression for each item to display, 4 lines Copyright © 1998 J. D. Birdwell

90 Copyright © 1998 J. D. Birdwell
Example 2: STL solution vector<string> v; map<string, int> m; copy(istream_iterator<string>(ifstream("words.txt")), istream_iterator<string>(), back_inserter(v)); for (vector<string>::iterator vi = v.begin(); vi != v.end(); ++vi) ++m[*vi]; for (map<string, int>::iterator mi = m.begin(); mi != m.end(); ++mi) cout << mi->first << ": " << mi->second << endl; Seven lines: 2 lines for data structures 1 lines to read in 2 lines to count 2 lines to display Copyright © 1998 J. D. Birdwell

91 Copyright © 1998 J. D. Birdwell
Conclusion The STL has everything Let the compiler do the work for you Saves time and lines of code Next steps: Buy a good book on STL Schildt’s STL Programming from the Ground Up Use it on your homeworks/personal projects Learn about function objects Didn’t have time to cover them; another talk?? Copyright © 1998 J. D. Birdwell

92 Copyright © 1998 J. D. Birdwell
Resources Books Schildt – “STL Programming from the Ground Up” *** Schildt – “C/C++ Programmers Reference” URLs MSDN Google: sgi stl <container or algorithm> Copyright © 1998 J. D. Birdwell

93 Copyright © 1998 J. D. Birdwell
Miscellaneous STLPort has a runtime “debug mode” #define _STLP_DEBUG 1 list<int> l1(array1, array1 + 3); list<int> l2(array2, array2 + 2); l1.erase(l2.begin()); _debug.h:70 STL error : Container doesn't own the iterator Also: copy(v1.begin(), v2.end(), v2.begin()); l1.erase(l1.end()); Copyright © 1998 J. D. Birdwell

94 Containers with pointers
Need to write a custom comparison object Can’t use operator< on non-class objects struct stringpointerless: public binary_function<string*, string*, bool> { bool operator()(string* s, string* t) { return *s < *t; }}; // could have been more generic! set<string*, stringpointerless > ss; (works now) Copyright © 1998 J. D. Birdwell


Download ppt "John Lambert jlambert@jlambert.com STL John Lambert jlambert@jlambert.com."

Similar presentations


Ads by Google