Standard Template Library
910 likes | 1.3k Views
Unit - 11. Standard Template Library. C++ Library of templates. Unit Introduction. This unit covers standard template library. Unit Objectives. After covering this unit you will understand… Standard template library String library IOStream library General template library
Standard Template Library
E N D
Presentation Transcript
Unit - 11 Standard Template Library C++ Library of templates
Unit Introduction This unit covers standard template library
Unit Objectives After covering this unit you will understand… • Standard template library • String library • IOStream library • General template library • STL containers and iterators • STL algorithms
Introduction • 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
Introduction (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
Strings 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
Characteristics 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
Advantages 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
Creating 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
Creating Strings (contd.) • Combine different sources of initialization data using operator+ • Use the string object’s substr( ) member function to create a substring
Example: Creating Strings #include <string.h> #include <iostream.h> 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 << mixedStuff << endl; }
Operating on Strings • You can perform four basic operations on a string: • Append • Insert • Concatenate • Replace
Example: Operating on Strings #include <string.h> #include <iostream.h> void main() { string s1(”This is String 1."); // How much data have we actually got? cout << "Size = " << s1.size() << endl; // How much can we store without reallocating cout << "Capacity = ” << s1.capacity() << 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”); }
Searching 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();
Example: Searching in Strings #include <string> #include <iostream> 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(“ “); }
String 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);
Example: String Comparison #include <iostream.h> #include <string.h> 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: cout<<“Both the Strings are equal”; break;
Example: String Comparison (contd.) case -1: cout<<“String1 is lexically less than String2”; break; case 1: cout<<“String1 is lexically greater than String2”; break; } // end switch statement } // end main
IOStream Library • Deals with the following I/O functions in a safe, efficient and easier manner: • Standard Input • Standard Output • Files • Memory Blocks
General 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
Example: Non-type Template Arguments #include <string.h> #include <sstream.h> template<typename T> std::string toString(const T& templateVar) { std::ostringstream output; output << templateVar; return output.str(); } void main() { int i = 1234; cout << "i == \"" << toString(i) << "\"\n"; float x = 567.89; cout << "x == \"" << toString(x) << "\"\n"; }
Example: Default Template Arguments // Using 'typename' to say it's a type, // and not something other than a type template<class T> class TemplateClass { // without typename, it is an error typename T AnyVarType; public: void TemplateFunc() { AnyVarType.Function(); } }; class NormalClass { public: void Function() {} };
Example: Default Template Arguments (contd.) void main() { NormalClass normalObj; TemplateClass<NormalClass> templateObj; templateObj.TemplateFunc(); }
Typedef a typename • It is recommended to use typedef when using typename /* The following causes a variable to be declared of type Seq::iterator */ // instead of using typename only typename Seq::iterator ItType; // use typedef typedef typename Seq::iterator SeqIteratorType; // now SeqIteratorType is a type and can be used as SeqIteratorType it;
Example: Using typename Instead of Class // Using 'typename' in the template argument list template<typename T> class TemplateClass { }; int main() { TemplateClass<int> templateObj; }
Function Templates • You can create Function Templates in places, where • you have a number of functions, • that look identical, • but have different data types
STL Containers and Iterators • Container classesare 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
Why 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
Why Use Containers? (contd.) • You don’t need to know how many objects you’re 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
Iterators • Iterator’s 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 it’s a vector, a linked list, a stack or something else
Iterators (contd.) • Gives the flexibility to easily change the underlying data structure without disturbing the code
Example: String Containers #include <string.h> #include <vector.h> #include <fstream.h> #include <iostream.h> #include <iterator.h> #include <sstream.h> void main(int argc, char* argv[]) { ifstream in(argv[1]); vector<string> stringVector; string inputLine; // Add to strings container while(getline(in, inputLine)) stringVector.push_back(inputLine); int i = 1; vector<string>::iterator vectorIterator; // iterator
Example: String Containers (contd.) for(vectorIterator = stringVector.begin(); vectorIterator != stringVector.end(); vectorIterator++) { ostringstream out; // define output string stream // object out << i++; // outputs the element number *vectorIterator = out.str() + ": " + *vectorIterator; } // write strings to console // create ostream iterator to write to console ostream_iterator<string> 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 }
Types 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
Sequence 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
Vectors • 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
Example: Vectors #include <iostream.h> #include <vector.h> #include <algorithm.h> int Noisy() { // return some random integer } void main() { vector<int> v; v.reserve(11); // make room for 11 integers ostream_iterator<int> out(cout, " "); copy(v.begin(), v.end(), out); // write to console vector<int>::iterator 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 }
Deque • 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)
Example: Deque #include <deque.h> #include <iostream.h> #include <iterator.h> void main() { deque<int> dequeObj(100, 0); ostream_iterator<int> out(cout, " ") // No problem iterating from beginning to end, // even though it spans multiple blocks copy(dequeObj.begin(), dequeObj.end(), out); deque<int>::iterator 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 < 1000; j++) { cout << j << endl;
Example: Deque (contd.) dequeObj.insert(dequeIterator++, j); // Eventually // breaks } //end for loop } // end main()
List • 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
Example: List #include <list.h> #include <iostream.h> void main() { // create list 100 elements initialized with 0 list<int> li(100, 0); // create iterator to traverse the list list<int>::iterator iter = li.begin(); // insert new elements with value 1 for(int k = 0; k < 50; k++) li.insert(iter++, 1); // No problem cout << *iter; // prints first 0 li.erase(iter); // erases first 0 --iter; cout << *iter; // prints the 1 *iter = 2; // replaces 1 with 2 at the current position }
Set • 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
Example: Set #include <string.h> #include <set.h> #include <iostream.h> #include <fstream.h> const char* delimiters = "\t;()\"<>:{}[]+-=&*#.,/\\~"; void main(int argc, char* argv[]) { ifstream in(argv[1]); set<string> wordListSet; string line; while(getline(in, line)) { // Capture individual words: char* token = strtok((char*)line.c_str(), delimiters);
Example: Set (contd.) while(token) { // Automatic type conversion: wordListSet.insert(token); token = strtok(0, delimiters); } } // end outer while loop ostream_iterator<string> out(cout, "\n") // Output results: copy(wordListSet.begin(), wordListSet.end(), out); } // end main()
Stack • 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
Example: Stack #include <iostream.h> #include <fstream.h> #include <stack.h> #include <list.h> #include <vector.h> #include <string.h> typedef stack<string> Stack1Type; // Default: deque<string> typedef stack<string, vector<string> > Stack2Type; // Vector typedef stack<string, list<string> > Stack3Type; // List void main(int argc, char* argv[]) { ifstream in(argv[1]); Stack1Type textLines; // Try the different versions // Read file and store lines in the stack: string line;
Example: Stack (contd.) while(getline(in, line)) textLines.push(line + "\n"); // Print lines from the stack and pop them: while(!textLines.empty()) { cout << textLines.top(); textLines.pop(); } } // end main()
Queue • 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
Priority Queues • It’s 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