Title: Standard Template Library
1Standard Template Library
Unit - 11
2Unit Introduction
- This unit covers standard template library
3Unit Objectives
- After covering this unit you will understand
- Standard template library
- String library
- IOStream library
- General template library
- STL containers and iterators
- STL algorithms
4Introduction
- STL stands for Standard Template Library
- Complements the C libraries
- STL provides certain features, which include
- String library
- Input/Output stream library
- Localization library
- Containers library
5Introduction (contd.)
- Iterators library
- Algorithms library
- Numerics library
- Diagnostics library
- Language Support library
- General Utilities library
- The purpose of STL is to provide standardised set
of tools - These tools become the building blocks of most
programs
6Strings Library
- It provides a set of functions to implement the
low-level manipulation features - A string is a character array with a null
terminator (binary zero) - STL uses string object for string manipulation
7Characteristics of String Object
- A string object has
- Starting location in memory
- contents
- Length
- no NULL terminator
- A string automatically resizes according to
length of its contents - In case of reference counting, string may occupy
specific physical memory
8Advantages of String Object
- It has the following three advantages over the
character array, used in C - Checks overwriting array bounds
- Checks for uninitialized pointers before using
strings - Releases memory storage for dangling pointers
9Creating Strings
- Create an empty string and defer initializing it
with character data - Initialize a string by passing a literal, quoted
character array as an argument to the constructor - Initialize a string using
- Use one string to initialize another
- Use a portion of either a C char array or a C
string
10Creating Strings (contd.)
- Combine different sources of initialization data
using operator - Use the string objects substr( ) member function
to create a substring
11Example Creating Strings
- include ltstring.hgt
- include ltiostream.hgt
- void main()
-
- string s1 (This is String 1")
- string s2 This is String 2
- // Copy the first 8 chars
- string s3(s1, 0, 8)
- // Copy 3 chars from the 5th character of the
source - string s4(s2, 5, 3)
- // Copy all sorts of stuff
- string mixedStuff s4 hmmm s1.substr(10,
5) - // substr() copies 5 chars at element 10
- cout ltlt mixedStuff ltlt endl
-
12Operating on Strings
- You can perform four basic operations on a
string - Append
- Insert
- Concatenate
- Replace
13Example Operating on Strings
- include ltstring.hgt
- include ltiostream.hgt
- void main()
-
- string s1(This is String 1.")
- // How much data have we actually got?
- cout ltlt "Size " ltlt s1.size() ltlt endl
- // How much can we store without reallocating
- cout ltlt "Capacity ltlt s1.capacity() ltlt endl
- s1.insert(1, "This is Inserted at index 1.")
- // Make sure that there will be this much space
- s1.reserve(50)
- // Add this to the end of the string
- s1.append("I've been working too hard.")
- string tag(String) // tag to find
- int start s1.find (tag) // get the start
index - s1.replace (start, tag.size(), hey there)
14Searching in String
- Following are useful functions used for string
searching - find()
- find_first_of()
- find_last_of()
- find_first_not_of()
- find_last_not_of()
- rfind()
15Example Searching in Strings
- include ltstringgt
- include ltiostreamgt
- void main()
-
- string s1(This is String 1.")
- // find the tag
- string tag(String)
- // get the start index
- int start s1.find (tag)
- // replace the tag totally with the new string
- s1.replace (start, tag.size(), hey there)
- // finds the i in String in s1
- int current s1.rfind(i)
- // finds the first space after This in s1
- int space s1.find_first_not_of( )
16String Comparison
- Compares the ASCII values of the string
characters - Returns 0 if both strings match
- Returns 1 if string1 has greater ASCII value
- Returns -1 if string2 has greater ASCII value
- Two types of syntax
- string1.compare(string2)
- strcmp(string1, string2)
17Example String Comparison
- include ltiostream.hgt
- include ltstring.hgt
- void main()
-
- string s1(This is One String)
- string s2(This is the Other String)
- int result strcmp(s1, s2)
- int caseInsensitive strcmpi(s1, s2)
- int result2 s1.compare(s2)
- switch (result)
-
- case 0
- coutltltBoth the Strings are equal
- break
-
18Example String Comparison (contd.)
- case -1
- coutltltString1 is lexically less than
String2 break - case 1
- coutltltString1 is lexically greater than
String2 break - // end switch statement
- // end main
19IOStream Library
- Deals with the following I/O functions in a safe,
efficient and easier manner - Standard Input
- Standard Output
- Files
- Memory Blocks
20General Template Library
- Templates provide an interface to assign variable
type or class type, to be used at runtime - There are two types of Template arguments
- Non-type template arguments
- Default template arguments
21Example Non-type Template Arguments
- include ltstring.hgt
- include ltsstream.hgt
- templatelttypename Tgt
- stdstring toString(const T templateVar)
-
- stdostringstream output
- output ltlt templateVar
- return output.str()
-
- void main()
-
- int i 1234
- cout ltlt "i \"" ltlt toString(i) ltlt "\"\n"
- float x 567.89
- cout ltlt "x \"" ltlt toString(x) ltlt "\"\n"
22Example Default Template Arguments
- // Using 'typename' to say it's a type,
- // and not something other than a type
- templateltclass Tgt
- class TemplateClass
-
- // without typename, it is an error
- typename T AnyVarType
- public
- void TemplateFunc()
-
- AnyVarType.Function()
-
-
- class NormalClass
-
- public
- void Function()
23Example Default Template Arguments (contd.)
- void main()
-
- NormalClass normalObj
- TemplateClassltNormalClassgt templateObj
- templateObj.TemplateFunc()
24Typedef a typename
- It is recommended to use typedef when using
typename - / The following causes a variable to be
declared of type Seqiterator / - // instead of using typename only
- typename Seqiterator ItType
- // use typedef
- typedef typename Seqiterator SeqIteratorType
- // now SeqIteratorType is a type and can be used
as - SeqIteratorType it
25Example Using typename Instead of Class
- // Using 'typename' in the template argument list
- templatelttypename Tgt
- class TemplateClass
- int main()
-
- TemplateClassltintgt templateObj
26Function Templates
- You can create Function Templates in places,
where - you have a number of functions,
- that look identical,
- but have different data types
27STL Containers and Iterators
- Container classes are the solution to a specific
kind of code reuse problem - They are building blocks used to create
object-oriented programs - They make the internals of a program much easier
to construct - They are sometimes referred to as Collection
Classes - A container class describes an object that holds
other objects
28Why Use Containers?
- Containers solve the problem of creating objects
at runtime - You create another type of object, the new type
of object holds other objects, or pointers to
objects - It will expand itself whenever necessary to
accommodate everything you place inside it
29Why Use Containers? (contd.)
- You dont need to know how many objects youre
going to hold in a collection - You just create a collection object and let it
take care of the details - You can add/delete elements in a container
- For fetching/comparing/manipulating objects
within a container, you need an iterator
30Iterators
- Iterators job is to iterate the elements within
a container - Present them to the user of the iterator
- The container, via the iterator, is abstracted to
be simply a sequence - The iterator allows you to traverse that sequence
without worrying about the underlying structure
that is, whether its a vector, a linked list, a
stack or something else
31Iterators (contd.)
- Gives the flexibility to easily change the
underlying data structure without disturbing the
code
32Example String Containers
- include ltstring.hgt
- include ltvector.hgt
- include ltfstream.hgt
- include ltiostream.hgt
- include ltiterator.hgt
- include ltsstream.hgt
- void main(int argc, char argv)
-
- ifstream in(argv1)
- vectorltstringgt stringVector
- string inputLine
- // Add to strings container
- while(getline(in, inputLine))
- stringVector.push_back(inputLine)
- int i 1
- vectorltstringgtiterator vectorIterator //
iterator
33Example String Containers (contd.)
- for(vectorIterator stringVector.begin()
- vectorIterator ! stringVector.end()
vectorIterator) -
- ostringstream out // define output string
stream // object - out ltlt i // outputs the element number
- vectorIterator out.str() " "
vectorIterator -
- // write strings to console
- // create ostream iterator to write to console
- ostream_iteratorltstringgt os_it(cout, "\n")
- //copy contents of strings to console using
the iterator - copy(stringVector.begin(), stringVector.end(),
os_it) -
- // string objects clean themselves up when they
go out of - // scope
34Types of Containers
- There are two types of containers
- Sequence Containers These containers keep the
sequence of objects in whichever order you want
to establish - Associative Containers These containers keep
key, value pairs, and store/retrieve data using
associations
35Sequence Containers
- These containers keep the sequence of objects in
whichever order you want to establish - The different sequence containers are
- Vector
- Deque
- List
- Set
- Stack
- Queue
36Vectors
- It has array-style indexing but also can expand
dynamically - It maintains its storage as a single contiguous
array of objects - It keeps everything in a single sequential block
of memory
37Example Vectors
- include ltiostream.hgt
- include ltvector.hgt
- include ltalgorithm.hgt
- int Noisy()
- // return some random integer
-
- void main()
-
- vectorltintgt v
- v.reserve(11) // make room for 11 integers
- ostream_iteratorltintgt out(cout, " ")
- copy(v.begin(), v.end(), out) // write to
console - vectorltintgtiterator it v.begin() v.size()
/ 2 - v.insert(it, Noisy()) // insert an element in
middle - copy(v.begin(), v.end(), out) // write to
console - v.erase(it) // erasing an element from
vector - copy(v.begin(), v.end(), out) // write to
console
38Deque
- The deque (double-ended-queue, pronounced deck)
is optimized for adding and removing elements
from either end - Deque uses multiple blocks of sequential storage
(keeping track of all the blocks and their order
in a mapping structure)
39Example Deque
- include ltdeque.hgt
- include ltiostream.hgt
- include ltiterator.hgt
- void main()
-
- dequeltintgt dequeObj(100, 0)
- ostream_iteratorltintgt out(cout, " ")
- // No problem iterating from beginning to end,
- // even though it spans multiple blocks
- copy(dequeObj.begin(), dequeObj.end(), out)
- dequeltintgtiterator dequeIterator
dequeObj.begin() dequeObj.size() / 2 - // Walk the iterator forward as you perform
- // a lot of insertions in the middle
- for(int j 0 j lt 1000 j)
-
- cout ltlt j ltlt endl
40Example Deque (contd.)
- dequeObj.insert(dequeIterator, j) //
Eventually // breaks - //end for loop
- // end main()
41List
- It is implemented as a doubly-linked list
- It is designed for rapid insertion and removal of
elements in the middle of the sequence - A list is so slow when randomly accessing
elements that it does not have an operator - It has a memory overhead of each link, which
requires a forward and backward pointer
42Example List
- include ltlist.hgt
- include ltiostream.hgt
- void main()
-
- // create list 100 elements initialized with
0 - listltintgt li(100, 0)
- // create iterator to traverse the list
- listltintgtiterator iter li.begin()
- // insert new elements with value 1
- for(int k 0 k lt 50 k)
- li.insert(iter, 1) // No problem
- cout ltlt iter // prints first 0
- li.erase(iter) // erases first 0
- --iter
- cout ltlt iter // prints the 1
- iter 2 // replaces 1 with 2 at the
current position
43Set
- It produces a container that will accept only one
of each thing you place in it - It also sorts the elements in a balanced binary
tree to provide rapid lookups - It produces sorted results when you traverse it
44Example Set
- include ltstring.hgt
- include ltset.hgt
- include ltiostream.hgt
- include ltfstream.hgt
- const char delimiters "\t()\"ltgt-.,/\
\" - void main(int argc, char argv)
-
- ifstream in(argv1)
- setltstringgt wordListSet
- string line
- while(getline(in, line))
-
- // Capture individual words
- char token strtok((char)line.c_str(),
delimiters) -
45Example Set (contd.)
- while(token)
-
- // Automatic type conversion
- wordListSet.insert(token)
- token strtok(0, delimiters)
-
- // end outer while loop
- ostream_iteratorltstringgt out(cout, "\n")
- // Output results
- copy(wordListSet.begin(), wordListSet.end(),
out) - // end main()
46Stack
- The stack is classified as adapters, which means
they are implemented using one of the basic
sequence containers vector, list or deque - The stack has one pointer, which points to the
top of the stack - You can add (push) or delete (pop) elements from
the top of the stack only
47Example Stack
- include ltiostream.hgt
- include ltfstream.hgt
- include ltstack.hgt
- include ltlist.hgt
- include ltvector.hgt
- include ltstring.hgt
- typedef stackltstringgt Stack1Type // Default
dequeltstringgt - typedef stackltstring, vectorltstringgt gt
Stack2Type // Vector - typedef stackltstring, listltstringgt gt Stack3Type
// List - void main(int argc, char argv)
-
- ifstream in(argv1)
- Stack1Type textLines // Try the different
versions - // Read file and store lines in the stack
- string line
48Example Stack (contd.)
- while(getline(in, line))
- textLines.push(line "\n")
- // Print lines from the stack and pop them
- while(!textLines.empty())
-
- cout ltlt textLines.top()
- textLines.pop()
-
- // end main()
49Queue
- The queue is a restricted form of a deque
- You can only enter elements at one end, and pull
them off the other end - The queue is an adapter class like stack, in that
it is built on top of another sequence container
50Priority Queues
- Its a special type of queue
- When you push( ) an object onto a priority_queue,
that object is sorted into the queue according to
a function or function object - The priority_queue ensures that when you look at
the top( ) element it will be the one with the
highest priority
51Priority Queues (contd.)
- When youre done with it, you call pop() to
remove it and bring the next - one into place
- Thus, the priority_queue has nearly the same
interface as a stack, but it behaves differently
52Example Priority Queue
- include ltiostream.hgt
- include ltqueue.hgt
- void main()
-
- priority_queueltintgt pqi
- for(int i 0 i lt 100 i)
- pqi.push(i 25) // Insertion will be
sorted - while(!pqi.empty())
-
- cout ltlt pqi.top() ltlt ' '
- pqi.pop()
-
-
53Associative Containers
- These containers keep key, value pairs, and
store/retrieve data using associations - Basic operations with associative containers are
putting things in - In the case of a set, seeing if something is in
the set - In the case of a map, you want to first see if a
key is in the map, and if it exists you want the
associated value for that key to be returned
54Map
- In a map you associate one object with another in
an array-like fashion - Instead of selecting an array element with a
number, you look it up with an object - In a map, youve got two things the key and the
value that results from the lookup with the key - If you simply want to move through the entire map
and list each key-value pair
55Map (contd.)
- You use an iterator, which when dereferenced
produces a pair object containing both the key
and the value - You access the members of a pair by selecting
first or second - A Map may have duplicate keys, and that is called
a Multi-Map
56Example Map
- include ltstringgt
- include ltfstreamgt
- include ltmapgt
- typedef mapltstring, stringgt DataMapType
- void main()
-
- ifstream in("myFile.db")
- DataMapType dMap
- string line
- while(getline(in, line))
-
- int pos line.find("")
- string meta line.substr(0, pos)
- string data line.substr(pos1,
line.size()) - dMapmetadata
-
57Multi-Set
- The Multi-Set allows more than one object of each
value to be inserted - It has more than one object of the same value in
a set - The objects look the same, but they actually
contain some differing internal state
58Container Concepts
- Can inherit container classes to achieve the
extra functionality, the container provides - Can combine container classes to achieve
multi-functional goals - Can create templates of clean-up container
pointers (since thats not automatic)
59Creating Custom Containers
- You can create your own custom containers
- Follow the same model of containers, by
providing - Iterators
- Using primitive data types
- Using library object types
- Providing your own object data types
60STL Algorithms
- They are templatized functions designed to work
with the containers - The STL was originally designed around the
algorithms - The goal was that you use algorithms for almost
every piece of code that you write
61Function Objects
- A function object has an overloaded operator()
- The result is that a template function cant tell
whether youve handed it a pointer to a function
or an object that has an operator() - All the template function knows is that it can
attach an argument list to the object as if it
were a pointer to a function
62Example Function Objects
- include ltiostream.hgt
- templateltclass UnaryFunc, class Tgt
- void CallFunc(T templateElement, UnaryFunc
uFunc) -
- uFunc(templateElement)
-
- void Function(int element)
-
- element 47
-
- struct UnaryFunc
-
- void operator()(int element)
-
- element 48
-
63Example Function Objects (contd.)
- void main()
-
- int y 0
- // This calls the template function Function
and sets - // y 47
- CallFunc(y, Function)
- cout ltlt y ltlt endl
- y 0
- // This calls the template function operator
and - // sets y 48
- CallFunc(y, UnaryFunc())
- cout ltlt y ltlt endl
64Classification of Function Objects
- Function objects are classified based on
- The number of arguments that their operator()
takes zero, one or two arguments - The kind of value returned by that operator a
bool or non-bool value - The different classifications are
- Generator
- UnaryFunction
65Classification of Function Objects (contd.)
- BinaryFunction
- Predicate
- BinaryPredicate
- StrictWeakOrdering
66STL Algorithms Summary
- STL Algorithms have a wide range of header files,
which cover - Filling Generating (values)
- Counting (number of elements)
- Manipulating sequences
- Search Replace
- Comparing ranges
- Removing (elements, values)
- Sorting (elements, values)
67STL Algorithms Summary (contd.)
- Heap operations
- Numeric algorithms (calculations)
68Fill Generate
- These algorithms allow you to automatically fill
a range with a particular value - Or to generate a set of values for a particular
range - The fill functions insert a single value
multiple times into the container - The generate functions use an object called a
generator to create the values to insert into
the container
69Example Fill Generate
- include ltvector.hgt
- include ltalgorithm.hgt
- include ltstring.hgt
- include ltstdlib.hgt
- void main()
-
- randomize()
- vectorltstringgt v1(5)
- fill(v1.begin(), v1.end(), "howdy")
- vectorltstringgt v2
- fill_n(back_inserter(v2), 7, "bye")
- vectorltintgt v3(10)
- generate(v3.begin(), v3.end(), random(10))
- vectorltintgt v4
- generate_n(back_inserter(v4),15, random(15))
70Counting
- All containers have a method size() that will
tell you how many elements they hold - In the example, the set is used to count all the
instances of all the different characters, and
display them
71Example Counting
- include ltvector.hgt
- include ltalgorithm.hgt
- include ltstdlib.hgt
- void main()
-
- vectorltchargt v
- // generates random characters and inserts it
into vector - generate_n(back_inserter(v), 50,
(char)(random(26) 49)) - // Create a set of the characters in v
- setltchargt cs(v.begin(), v.end()) // copies
vector in set - setltchargtiterator it cs.begin() // set
iterator - while(it ! cs.end()) // loop till end of set
reached -
- int n count(v.begin(), v.end(), it)
- cout ltlt it ltlt " " ltlt n ltlt ", "
- it
-
72Example Counting (contd.)
- int lc count_if(v.begin(), v.end(),
bind2nd(greaterltchargt(), 'a')) - cout ltlt "\nLowercase letters " ltlt lc ltlt endl
- // end main()
73Manipulating Sequences
- Following algorithms allows to work with
sequences - copy
- copy_backward
- reverse
- reverse_copy
- swap_ranges
74Search Replace
- Following algorithms are used to search and
replace elements in containers - find
- find_if
- adjacent_find
- find_first_of
- search
- find_end
- search_n
75Search Replace (contd.)
- min_element
- max_element
- replace
76Example Search Replace
- include ltvector.hgt
- include ltalgorithm.hgt
- include ltfunctional.hgt
- void main()
-
- int a 1, 2, 3, 4, 5, 6, 6, 7, 7, 7,
- 8, 8, 8, 8, 11, 11, 11, 11, 11
- const int asz (sizeof a) (sizeof a)
- vectorltintgt v(a, a asz)
- // This finds the value 4 in v
- vectorltintgtiterator it find(v.begin(),
v.end(), 4) - // use find_if to return iterator to second
occurrence of - // 11 in the vector (greater than 8)
- it find_if(v.begin(), v.end(),
- bind2nd(greaterltintgt(), 8))
- // it finds the first identical values, which
are adjacent
77Example Search Replace (contd.)
- // e.g. first 6 in vector given above
- it adjacent_find(v.begin(), v.end())
- int b 8, 11
- const int bsz (sizeof b) (sizeof b)
- // It finds first matching value in v having
value bbsz - it find_first_of(v.begin(), v.end(), b, b
bsz) - // Finds exactly the second range inside the
first one, - // with the elements in the same order.
- it search(v.begin(), v.end(), b, b bsz)
- int d 11, 11, 11
- const int dsz (sizeof d) (sizeof d)
- // Finds the last occurrence of the entire
sequence - it find_end(v.begin(), v.end(), d, d dsz)
- // Looks for 3 copies of the value 7
- it search_n(v.begin(), v.end(), 3, 7)
- vectorltintgt v2
-
78Example Search Replace (contd.)
- // Replaces the specified values in a new
vector - replace_copy(v.begin(), v.end(),
back_inserter(v2), 8, 47) - // Replaces 7 or values greater than 7 with
-1 - replace_if(v.begin(), v.end(),
bind2nd(greater_equalltintgt(), 7), -1) - // end main()
79Comparing Ranges
- These algorithms provide ways to compare two
ranges - The different comparison operations are
- equal
- lexicographical_compare
- mismatch
80Example Comparing Ranges
- include ltvector.hgt
- include ltalgorithm.hgt
- include ltfunctional.hgt
- include ltstring.hgt
- void main()
-
- string s1("This is a test")
- string s2("This is a Test")
- equal(s1.begin(), s1.end(), s2.begin())//
compare s1 s2 - lexicographical_compare(s1.begin(), s1.end(),
s2.begin(), s2.end()) // ASCII value
comparison - // This prints the string characters that dont
match in - // both the strings
- pairltstringiterator, stringiteratorgt p
- mismatch(s1.begin(), s1.end(),
s2.begin()) - print(p.first, s1.end(), "p.first", "")
- print(p.second, s2.end(), "p.second","")
81Removing elements from a container
- Because of the genericity of the STL, the concept
of removal is a bit constrained - Elements can only be removed via iterators
- It is not safe or reasonable to actually try to
destroy the elements that are being removed, and
to change the size of the input range
82Removing Elements (contd.)
- The STL remove functions
- Rearrange the sequence so that the removed
elements are at the end of the sequence - The un-removed elements are at the beginning of
the sequence - function will return an iterator to the new
last element of the sequence, which is the end
of the sequence without the removed elements - function will return the beginning of the
sequence of the removed elements
83Example Removing Elements
- include ltvector.hgt
- include ltalgorithm.hgt
- void main()
-
- vectorltchargt v(50)
- generate(v.begin(), v.end(), (char)
(random(26)49)) - vectorltchargtiterator cit
- // Step through and remove everything
- while(cit ! v.end())
-
- cit remove(v.begin(), v.end(), cit)
- cout ltlt cit
- cit
-
84Example Removing Elements (contd.)
- cit remove_if(v.begin(), v.end(),
isUpper()) - vectorltchargt v2
- unique_copy(v.begin(), cit, back_inserter(v2))
- // end main()
85Sorting
- There is actually only one sort algorithm used
in the STL - This algorithm is presumably the fastest one
- The different types of sorting are
- sort
- stable_sort
- partial_sort
- partial_sort_copy
- nth_element
86Example Sorting
- include ltdeque.hgt
- include ltiostream.hgt
- include ltsort.hgt
- include ltvector.hgt
- void main(int argc, char argv)
-
- ifstream in(argv1)
- StreamTokenizer words(in) // used to delimit
elements - dequeltstringgt nstr
- string word
- while((word words.next()).size() ! 0)
- nstr.push_back(string(word)) // add to
deque - // Create a vector from the contents of nstr
- vectorltstringgt v(nstr.begin(), nstr.end())
- sort(v.begin(), v.end()) // sort the elements
- print(v, "sort") // print the sorted
elements
87Heap Operations
- The heap operations in the STL are primarily
concerned with the creation of the STL
priority_queue - It provides efficient access to the largest
element (can be set in code) - The different heap operations are
- make_heap
- push_heap
- pop_heap
- sort_heap
88Creating Your Own STL-Style Algorithms
- The easiest way to create STL-style algorithms
is - Goto the ltalgorithmgt header file of STL
- Search the closest implementation of what you
need - Copy the file, and rename it to your own name
(e.g. myalgo.h) - Make the necessary changes to the file
89Example Custom STL Algorithm
- // copy_if.h
- // Your own STL-style algorithm
- ifndef COPY_IF_H
- define COPY_IF_H
- templatelttypename ForwardIter, typename
OutputIter, typename UnaryPredgt - OutputIter copy_if(ForwardIter begin, ForwardIter
end, - OutputIter dest, UnaryPred f)
-
- while(begin ! end)
-
- if(f(begin))
- dest begin
- begin
-
- return dest
-
- endif // COPY_IF_H
90Unit Summary
- In this unit you have covered
- Standard template library
- Different features of STL
- In-depth knowledge of some of the library
features like string, containers etc