0% found this document useful (0 votes)
15 views

LectureSlide For CPP

The document discusses templates in C++, which allow functions and classes to operate on different data types through type parameters. It provides examples of generic functions that can swap or output values of various types using a single function definition. Template functions must perform the same general logic for all data types rather than having different implementations as overloaded functions can.
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

LectureSlide For CPP

The document discusses templates in C++, which allow functions and classes to operate on different data types through type parameters. It provides examples of generic functions that can swap or output values of various types using a single function definition. Template functions must perform the same general logic for all data types rather than having different implementations as overloaded functions can.
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 121

CSE107

Object Oriented Programming Language

Weeks 5 to 8

Khaled Mahmud Shahriar


Assistant Professor, CSE, BUET
khaledshahriar@cse.buet.ac.bd
Let’s Introduce

2
Course Content Source: CSE_BUET_UG_Course_Calendar_2022.pdf

• Philosophy of object oriented programming (OOP); Basic principles of OOP: abstraction,


encapsulation, polymorphism, inheritance; Advantages of OOP over structured
programming;

• C++: Classes and objects: specifying a class, access specifiers; Functions: inline functions,
friend functions; Constructors and destructors; Operator overloading and type conversions;
Inheritance: single inheritance, multilevel inheritance, multiple inheritance; Polymorphism:
function overloading, virtual functions, pure virtual functions; Templates: class templates,
function templates, introduction to the standard template library (STL);

• Java: Nested and Inner classes; Local variable type inference; Strings: String, StringBuffer,
StringBuilder; Inheritance: abstract class and anonymous subclasses, object class; Access
protection with package; Interface; Exception; Thread: multithreading, Introduction to Java
concurrency utilities; Generics and collections; Stream API and lambda expressions;
Networking: ServerSocket, Socket
3
It’s time to Proceed to Contents

4
Templates

5
Templates
• Template is one of C++'s most sophisticated and high-powered features.
• Using templates, it is possible to create generic functions and classes.
• In a generic function or class, the type of data upon which the function or
class operates is specified as a parameter.
• It is possible to use one function or class with several different types of data without
having to explicitly recode specific versions for each data type.

6
Generic Functions
int main() // This is a function template
{ template <class X> void swapargs(X &a, X &b)
int i = 10, j = 20; {
double x = 10.1, y = 23.3; X temp;
char a = 'x', b = 'z'; temp = a;
cout << "Original i, j: " << i << ' ' << j << '\n'; a = b;
cout << "Original x, y: " << x << ' ' << y << '\n'; b = temp;
cout << "Original a, b: " << a << ' ' << b << '\n'; }
swapargs(i, j); // swap integers
swapargs(x, y); // swap floats
swapargs(a, b); // swap chars
cout << "Swapped i, j: " << i << ' ' << j << '\n';
cout << "Swapped x, y: " << x << ' ' << y << '\n';
cout << "Swapped a, b: " << a << ' ' << b << '\n';
return 0;
}

7
Generic Functions (2)
• A generic function defines a general set of operations that will be applied to
various types of data.
• The type of data that the function will operate upon is passed to it as a
parameter.
• Through a generic function, a single general procedure can be applied to a
wide range of data.
• Applicable for many algorithms are logically the same no matter what type
of data is being operated upon.
• For example, sorting algorithm
• In essence, a generic function is a function that can automatically overload
itself.

8
Generic Functions (3)
• A generic function is created using the keyword template.
• The normal meaning of the word "template" accurately reflects its use in C++.
• It is used to create a template (or framework) that describes what a function
will do, leaving it to the compiler to fill in the details as needed.
• The general form of a template function definition is shown here:

template <class Ttype> ret-type func-name (parameter list)


{
// body of function
} template <class Ttype>
ret-type func-name (parameter list)
{
// body of function
}
9
Functions with Multiple Generic Types
#include <iostream>
using namespace std;
template <class type1, class type2>
void myfunc(type1 x, type2 y)
{
cout << x << ' ' << y << '\n';
}

int main()
{
myfunc(10, "I like C++");
myfunc(98.6, 19L);
return 0;
}
10
Explicit Overloading of Generic Functions
template <class X> int main()
void swapargs(X &a, X &b) {
{ int i = 10, j = 20;
X temp; double x = 10.1, y = 23.3;
temp = a; char a = 'x', b = 'z';
a = b; cout << "Original i, j: " << i << ' ' << j << '\n';
b = temp; cout << "Original x, y: " << x << ' ' << y << '\n';
cout << "Inside template swapargs.\n"; cout << "Original a, b: " << a << ' ' << b << '\n';
} swapargs(i, j); // calls explicitly overloaded swapargs()
swapargs(x, y); // calls generic swapargs()
void swapargs(int &a, int &b) swapargs(a, b); // calls generic swapargs()
{ cout << "Swapped i, j: " << i << ' ' << j << '\n';
int temp; cout << "Swapped x, y: " << x << ' ' << y << '\n';
temp = a; cout << "Swapped a, b: " << a << ' ' << b << '\n';
a = b; return 0;
b = temp; }
cout << "Inside swapargs int specialization.\n";
}

11
Specialization Syntax for Overloading Generic Functions
template <class X> int main()
void swapargs(X &a, X &b) {
{ int i = 10, j = 20;
X temp; double x = 10.1, y = 23.3;
temp = a; char a = 'x', b = 'z';
a = b; cout << "Original i, j: " << i << ' ' << j << '\n';
b = temp; cout << "Original x, y: " << x << ' ' << y << '\n';
cout << "Inside template swapargs.\n"; cout << "Original a, b: " << a << ' ' << b << '\n';
} swapargs(i, j); // calls explicitly overloaded swapargs()
swapargs(x, y); // calls generic swapargs()
// Use new-style specialization syntax. swapargs(a, b); // calls generic swapargs()
template <> cout << "Swapped i, j: " << i << ' ' << j << '\n';
void swapargs<int>(int &a, int &b) cout << "Swapped x, y: " << x << ' ' << y << '\n';
{ cout << "Swapped a, b: " << a << ' ' << b << '\n';
int temp; return 0;
temp = a; }
a = b;
b = temp;
cout << "Inside swapargs int specialization.\n";
} 12
Overloading Function Templates
// First version of f() template. int main()
template <class X> {
void f(X a) f(10); // calls f(X)
{ f(10, 20); // calls f(X, Y)
cout << "Inside f(X a)\n"; return 0;
} }

// Second version of f() template.


template <class X, class Y>
void f(X a, Y b)
{
cout << "Inside f(X a, Y b)\n";
}

13
Standard Parameters with Template Functions
const int TABWIDTH = 8; int main()
// Display data at specified tab position. {
template<class X> tabOut("This is a test", 0);
void tabOut(X data, int tab) tabOut(100, 1);
{ tabOut('X', 2);
for (; tab; tab--) tabOut(10 / 3, 3);
for (int i = 0; i < TABWIDTH; i++) return 0;
cout << ' '; }
cout << data << "\n";
}

14
Generic Function Restrictions
• Generic functions are similar to overloaded functions
except that they are more restrictive.
• When functions are overloaded, different actions can be
performed within the body of each function.
• But a generic function must perform the same general
action for all versions—only the type of data can differ.

15
Application of Generic Function – Generic Sort
template <class X> int main()
void bubble( {
X *items, // pointer to array to be sorted int iarray[7] = {7, 5, 4, 3, 9, 8, 6};
int count) // number of items in array double darray[5] = {4.3, 2.5, -0.9, 100.2, 3.0};
{ int i;
register int a, b; cout << "Here is unsorted integer array: ";
X t; for (i = 0; i < 7; i++) cout << iarray[i] << ' ';
for (a = 1; a < count; a++) cout << endl;
for (b = count - 1; b >= a; b--) cout << "Here is unsorted double array: ";
if (items[b - 1] > items[b]) for (i = 0; i < 5; i++) cout << darray[i] << ' ';
{ cout << endl;
// exchange elements bubble(iarray, 7);
t = items[b-1]; bubble(darray, 5);
items[b-1] = items[b]; cout << "Here is sorted integer array: ";
items[b] = t; for (i = 0; i < 7; i++) cout << iarray[i] << ' ';
} cout << endl;
} cout << "Here is sorted double array: ";
for (i = 0; i < 5; i++) cout << darray[i] << ' ';
cout << endl;
return 0;
} 16
Generic Classes
const int SIZE = 10; template <class StackType>
// Create a generic stack class void stack<StackType>::push(StackType ob)
template <class StackType> class stack {
{ if (tos == SIZE) {
StackType stck[SIZE]; // holds the stack cout << "Stack is full.\n";
int tos; // index of top-of-stack return;
public: }
stack() { tos = 0; } // initialize stack stck[tos] = ob;
void push(StackType ob); // push object on stack tos++;
StackType pop(); // pop object from stack }
};
template <class StackType>
StackType stack<StackType>::pop()
{
if (tos == 0) {
cout << "Stack is empty.\n";
return 0; // return null on empty stack
}
tos--;
return stck[tos];
} 17
Generic Classes (2)
• A generic class defines all the algorithms used by that class
• The actual type of the data being manipulated are specified as a parameter when
objects of that class are created.
• Generic classes are useful when a class uses logic that can be generalized.
• For example, stack, queue
• The compiler will automatically generate the correct type of object, based upon
the type specified when the object is created.
• The general form of a generic class declaration is shown here:
template <class Ttype>
class class-name {
.
.
.
};
• Once you have created a generic class, you create a specific instance of that class
using the following general form: class-name <type> ob; 18
Generic Classes with Multiple Types
template <class Type1, class Type2> int main()
class myclass {
{ myclass<int, double> ob1(10, 0.23);
Type1 i; myclass<char, char *> ob2('X', "Templates add power.");
Type2 j; ob1.show(); // show int, double
ob2.show(); // show char, char *
public: return 0;
myclass(Type1 a, Type2 b) }
{
i = a;
j = b;
}
void show() { cout << i << ' ' << j << '\n'; }
};

19
Applications of Generic Classes
const int SIZE = 10; // Provide range checking for atype. int main()
template <class AType> template <class AType> {
class atype AType &atype<AType>::operator[](int i) atype<int> intob; // integer array
{ { atype<double> doubleob; // double array
AType a[SIZE]; if (i < 0 || i > SIZE - 1) int i;
{ cout << "Integer array: ";
public: cout << "\nIndex value of "; for (i = 0; i < SIZE; i++) intob[i] = i;
atype() cout << i << " is out-of-bounds.\n"; for (i = 0; i < SIZE; i++)
{ exit(1); cout << intob[i] << " ";
register int i; } cout << '\n';
for (i = 0; i < SIZE; i++) a[i] = i; return a[i]; cout << "Double array: ";
} } for (i = 0; i < SIZE; i++)
AType &operator[](int i); doubleob[i] = (double)i / 3;
}; for (i = 0; i < SIZE; i++)
cout << doubleob[i] << " ";
cout << '\n';
intob[12] = 100; // generates runtime
error
return 0;
} 20
Non-Type Arguments with Generic int main()
{
Classes atype<int, 10> intob; // integer
array of size 10
template <class AType, int size> // Provide range checking for atype. atype<double, 15> doubleob; //
class atype template <class AType, int size> double array of size 15
{ AType &atype<AType, size>::operator[](int i) int i;
AType a[size]; // length of array { cout << "Integer array: ";
is passed in size if (i < 0 || i > size - 1) for (i = 0; i < 10; i++)
public: { intob[i] = i;
atype() cout << "\nIndex value of "; for (i = 0; i < 10; i++)
{ cout << i << " is out-of-bounds.\n"; cout << intob[i] << " ";
register int i; exit(1); cout << '\n';
for (i = 0; i < size; i++) } cout << "Double array: ";
a[i] = i; return a[i]; for (i = 0; i < 15; i++)
} } doubleob[i] = (double)i / 3;
AType &operator[](int i); for (i = 0; i < 15; i++)
}; cout << doubleob[i] << " ";
cout << '\n';
intob[12] = 100; // generates
runtime error
return 0;
}
21
Default Arguments in Generic Classes
template <class AType = int, int size = 10> int main() {
class atype atype<int, 100> intarray; // integer array, size 100
{ atype<double> doublearray; // double array, default size
AType a[size]; // size of array is passed in size atype<> defarray; // default to int array of size 10
public: int i;
atype() { cout << "int array: ";
register int i; for (i = 0; i < 100; i++) intarray[i] = i;
for (i = 0; i < size; i++) a[i] = i; for (i = 0; i < 100; i++) cout << intarray[i] << " ";
} cout << '\n';
AType &operator[](int i); cout << "double array: ";
}; for (i = 0; i < 10; i++) doublearray[i] = (double)i / 3;
for (i = 0; i < 10; i++) cout << doublearray[i] << " ";
template <class AType, int size> cout << '\n';
AType &atype<AType, size>::operator[](int i){ cout << "defarray array: ";
if (i < 0 || i > size - 1) { for (i = 0; i < 10; i++)
cout << "\nIndex value of "; defarray[i] = i;
cout << i << " is out-of-bounds.\n"; for (i = 0; i < 10; i++)
exit(1); cout << defarray[i] << " ";
} cout << '\n';
return a[i]; return 0;
} } 22
Template Class Specialization
template <class T> // Explicit specialization for int. int main()
class myclass template <> {
{ class myclass<int> myclass<double> d(10.1);
T x; { cout << "double: " << d.getx() << "\n\n";
int x; myclass<int> i(5);
public: cout << "int: " << i.getx() << "\n";
myclass(T a) public: return 0;
{ myclass(int a) }
cout << "Inside generic myclass\n"; {
x = a; cout << "Inside myclass<int>
} specialization\n";
T getx() { return x; } x = a * a;
}; }
int getx() { return x; }
};

23
Typename Keyword
template <class X> template <typename X>
void swapargs(X &a, X &b) void swapargs(X &a, X &b)
{ {
X temp; X temp;
temp = a; temp = a;
a = b; a = b;
b = temp; b = temp;
} }

24
Standard Template Library
(STL)

26
Introduction to STL
• Developed by Alexander Stepanov and Meng Lee at Hewlett-
Packard Lab
- as proof-of-concept for so-called generic programming.
• Released in 1994 and subsequently adopted into the C++98.
• STL provides general-purpose, templatized classes and functions
that implement
- many popular and commonly used algorithms and
- data structures, including, for example, support for
vectors, lists, queues, and stacks.
• It also defines various routines that access them.
• Because the STL is constructed from template classes, the
algorithms and data structures can be applied to nearly any type
of data. 27
STL Templates

Container  Iterator  
Templatized data structure. Can be used to A generalization of pointer. An object that
hold fundamental-type values or almost any allows traversing through elements of a
type of objects, e.g., vector<int>, list<string>, container, e.g., vector<int>::iterator,
deque<Person>. list<string>:: iterator.

Algorithms   Function
 Used for tasks such as searching, sorting and
comparison, e.g., for_each, find, sort.
Objects
 Objects that act like functions.

28
Types of Containers
Sequence Containers Container Adapter Classes
linear data structures of elements constrained sequence containers

array (C++ 11): NOT a STL container because it Stack: Last-in-first-out (LIFO) queue, adapted
has a fixed size and does not support operations like from deque (default), or vector, or list. Support
insert. But STL algorithms can be applied. operations back, push_back, pop_back.
vector: dynamically resizable array. Support fast queue: First-in-first-out (FIFO) queue, adapted
insertion and deletion at back; and direct access to its from deque (default), or list. Support
elements. operations front, back, push_back, pop_front.
deque: double-ended queue. Support fast insertion priority_queue: highest priority element at
and deletion at front and back; and direct access to its front of the queue. adapted from vector (default)
elements. or deque. Support
forward_list (C++ 11): single-linked list that operations front, push_back, pop_front.
support forward transversal only. It is simpler than list.
list: double-linked list. Support fast insertion and
deletion anywhere in the list; and direct access to its
elements. 29
Types of Containers (2)
Associative Containers Unordered Associative Containers
nonlinear data structures storing key-value pairs, sorted based on hash table, efficient in insertion, removal and
by keys search but requires more storage

set: No duplicate element. Support fast lookup. unordered_set: No duplicate element. Support fast
lookup.
multiset: Duplicate element allowed. Support fast
lookup. unordered_multiset: Duplicate element allowed.
Support fast lookup.
map: One-to-one mapping (associative array) with no
duplicate. Support fast key lookup. unordered_map: One-to-one mapping (associative
array) with no duplicate. Support fast key lookup.
multimap: One-to-many mapping, with duplicates
allowed. Support fast key lookup. Unordered_multimap: One-to-many mapping,
with duplicates allowed. Support fast key lookup.

C++ 11
30
Flowchart of Sequence and Ordered Containers
start

31
Ref: https://www.geeksforgeeks.org/containers-cpp-stl/
Flowchart of Adaptive and Unordered Containers

start

32
Ref: https://www.geeksforgeeks.org/containers-cpp-stl/
Types of Containers
Simple Containers Other Container Classes
pair: bitset: stores series of bits similar to a fixed-sized
• The pair container is a simple associative container vector of bools. Implements bitwise operations and
consisting of a 2-tuple of data elements or objects, lacks iterators. Not a sequence. Provides random
called 'first' and 'second', in that fixed order. access.
• The STL 'pair' can be assigned, copied and
compared.
valarray: Another array data type, intended for
• The array of objects allocated in a map or hash_map numerical use (especially to represent vectors and
matrices); the C++ standard allows specific
are of type 'pair' by default, where all the 'first'
optimizations for this intended purpose.
elements act as the unique keys, each associated
with their 'second' value objects.

33
Container Functions
All containers provides these functions: In addition, the first-class containers support
• Default Constructor: to construct an these functions:
empty container. Other constructors are • begin, end, cbegin, cend: Returns the
provided for specific purposes. begin and end iterator, or the const
• Copy Constructor version.
• Destructor • rbegin, rend, crbegin, crend: Returns the
• empty(): returns true if the container is reverse_iterator.
empty. • clear(): Removes all elements.
• size(): returns the size (number of • erase(): Removes one element given an
elements). iterator, or a range of elements given
• Assignment Operator (=) [begin, end) iterators.
• Comparison Operators (==, !=, <, <=, >, • max_size(): Returns the maximum number
>=). of elements that the container can hold.
• swap(): exchanges the contents of two
containers.
34
Container Headers
<vector> <valarray>
<list> <bitset>
<deque> <array> (C++11)
<queue>: queue and priority_queue <forward_list> (C++11)
<stack> <unordered_map> (C++11)
<map>: map and multimap <unordered_set> (C++11)
<set>: set and multiset

In addition to the headers required by the various STL classes, the C++ standard
library includes the <utility> and <functional> headers, which provide support for
the STL. For example, the template class pair, which can hold a pair of values, is
defined in <utility>.
35
Iterators
• An iterator behaves like a generic pointer, that can be used to
- reference (point-to) individual element of a generic container; and
- transverse through elements of a container.
• The purpose of iterator is to make traversing (iterating) of containers
independent on the type of the containers (e.g., vector<int>,
queue<double>, stack<string>).
• With iterator, it is possible apply generic algorithm (such as searching,
sorting and comparison) to the container, independent of types.

36
Requirements of Iterators
• The dereferencing operator * shall be defined.
- if iter is an iterator, *iter shall be pointing to an element of the container.
• The assignment operator = shall be defined.
- if iter1 and iter2 are iterators, iter1 = iter2 shall assign iter2 to iter1.
• The comparison operators == and != shall be defined.
- if iter1 and iter2 are iterators, we can use iter1 == iter2 and iter1 !=
iter2 to compare them for equality.
- iter1 == iter2 is true, then they shall be pointing at the same element,
i.e., *iter1 == *iter2.

37
Requirements of Iterators
• The increment operator ++ shall be defined.
- if iter is an iterator, ++iter and iter++ move the iterator to point to the
next element.
- The program shall be able to iterate through all the elements via ++iter
(or iter++) operations.
• For linearly-ordered container, the + (and +=) operator shall be defined.
- if iter is an iterator, iter+n points to the next n-th element in the linear
order.
• For iterator that can transverse backward, the decrement operator -- shall be
defined.
- if iter is an operator, --iter and iter-- move the iterator to point to the next
element in the reverse order (or previous element in the forward order).

38
Working with Iterators
• All STL container provides two member functions:
- begin() and end() that return the iterators pointing to the first
element and the pass-the-end element respectively.
• Hence, the following code to transverse all the elements in the container:

// Assume that c is a container


iter_type iter;
for (iter = c.begin(); iter != c.end(); ++iter) {
// Use *iter to reference each element
......
}
The type of iterator (iter_type)
depends on the container. In STL, the
iterator type can be obtained
via container<T>::iterator.
39
Auto and for_each in C++11
• In C++11, the auto keyword is used to derive the type of iterator
automatically, as follows:

for (auto iter = c.begin(); iter != c.end(); ++iter) {


// Use *iter to reference each element
......
}

• In C++11, you can also use the new for-each loop to iterate thru all the
element of a container:

for (auto item : container) {


// Use item to reference each element
......
}
40
The Vector Template Class
• In computing, a vector refers to an array-like structure that
holds
- a set of direct-access elements of the same kinds, instead
of mathematical n-component vector.
• Unlike array which is fixed-size, vector is dynamically-sized. 
• Supports fast insertion and deletion at back and direct access
to its elements.
• vector is a class template, declared in the vector header.

41
Vector Basics
// Demonstrate a vector. /* put more values onto the end of the vector, it will grow as
#include <iostream> needed */
#include <vector>  Header file for vector cout << "Expanding vector\n";
#include <cctype> for (i = 0; i < 5; i++)
using namespace std; v.push_back(i + 10 + 'a'); Insert at the end
int main() // display current size of v
Create a vector of type char
{ cout << "Size now = " << v.size() << endl;
vector<char> v(10); // create a vector of length 10 cout << "Capacity = " << v.capacity() << endl;
unsigned int i; // display contents of vector
// display original size of v Get the size of vector cout << "Current contents:\n";
cout << "Size = " << v.size() << endl; Get the capacity for (i = 0; i < v.size(); i++) What would be the
cout << "Capacity = " << v.capacity() << endl; cout << v[i] << " "; value of capacity here?
// assign the elements of the vector some values cout << "\n\n";
for (i = 0; i < 10; i++) // change contents of vector
v[i] = i + 'a'; for (i = 0; i < v.size(); i++)
// display contents of vector Access vector like an array v[i] = toupper(v[i]);
cout << "Current Contents:\n"; cout << "Modified Contents:\n";
for (i = 0; i < v.size(); i++) for (i = 0; i < v.size(); i++)
cout << v[i] << " "; cout << v[i] << " ";
cout << "\n\n"; cout << endl;
} 42
Iterator with Vector
#include <iostream> // display contents of vector // display contents of vector
#include <vector> cout << "Original contents:\n"; cout << "Modified Contents:\n";
#include <cctype> p = v.begin(); p = v.begin();
using namespace std; while (p != v.end()) while (p != v.end())
int main() { {
{ cout << *p << " "; cout << *p << " ";
vector<char> v(10); create an p++; p++;
// create an iterator iterator } }
vector<char>::iterator p; cout << "\n\n"; cout << endl;
int i; // change contents of vector return 0;
// assign elements in vector a value p = v.begin(); }
p = v.begin() Initialize (like a pointer) while (p != v.end())
i = 0; {
while (p != v.end()) *p = toupper(*p);
{ p++;
*p = i + 'a'; Access through Iterator }
p++;
i++; Advance to next element
}
Auto Type Deduction of Iterators in C++11
// Access the elements of a vector through an iterator. // Access the elements of a vector through an iterator.
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <cctype> #include <cctype>
using namespace std; using namespace std;
int main() { int main() {
vector<char> v(10); // create a vector of length 10 vector<char> v(10); // create a vector of length 10
int i=0; int i=0;
for (auto p = v.begin(); p != v.end(); ++p) { for (auto p = v.begin(); p != v.end(); ++p) {
*p = i + 'a'; *p = i + 'a';
i++; i++;
} }
// display contents of vector // display contents of vector
cout << "Original contents:\n"; cout << "Original contents:\n";
for (auto p = v.begin(); p != v.end(); ++p) { for (auto p : v) {
cout << *p << " "; cout << p << " ";
} Use of auto } for_each
cout << "\n\n"; cout << "\n\n";
return 0; return 0;
} }
Insert and Erase in Vector
#include <iostream> vector<char>::iterator p = v.begin(); // Insert v2 into v Insert from vector
#include <vector> p += 2; // point to 3rd element v.insert(p, v2.begin(), v2.end());
using namespace std; // insert 10 X's into v cout << "Size after v2's insertion = ";
int main() { v.insert(p, 10, 'X'); Insert elements cout << v.size() << endl;
vector<char> v(10); // display contents after insertion cout << "Contents after insert:\n";
vector<char> v2; cout << v.size() << endl; for (i = 0; i < v.size(); i++)
char str[] = "<Vector>"; cout << "Contents after insert:\n"; cout << v[i] << " ";
unsigned int i; for (i = 0; i < v.size(); i++) cout << endl;
// initialize v cout << v[i] << " "; return 0;
for (i = 0; i < 10; i++) cout << "\n\n"; }
v[i] = i + 'a'; // remove those elements
// copy characters in str into v2 p = v.begin();
for (i = 0; str[i]; i++) p += 2; // point to 3rd element
v2.push_back(str[i]); // remove next 10 elements
// display original contents of vector v.erase(p, p + 10); Erase from vector
cout << "Original contents of v:\n"; // display contents after deletion
for (i = 0; i < v.size(); i++) cout << v.size() << endl;
cout << v[i] << " "; cout << "Contents after erase:\n";
cout << "\n\n"; for (i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << "\n\n";
Store Objects in Vector
#include <iostream> int main() Create a vector of objects
#include <vector> {
#include <cstdlib> vector<DailyTemp> v;
using namespace std; unsigned int i; Insert objects
class DailyTemp { for (i = 0; i < 7; i++)
int temp; v.push_back(DailyTemp(60 + rand() % 30));
public: cout << "Fahrenheit temperatures:\n";
DailyTemp() { temp = 0; } for (i = 0; i < v.size(); i++) Access member function
DailyTemp(int x) { temp = x; } cout << v[i].get_temp() << " ";
DailyTemp &operator=(int x) { cout << endl;
temp = x; // convert from Fahrenheit to Centigrade
return *this; for (i = 0; i < v.size(); i++)
} v[i] = (int)(v[i].get_temp() - 32) * 5 / 9;
double get_temp() { return temp; } cout << "Centigrade temperatures:\n";
}; for (i = 0; i < v.size(); i++)
bool operator<(DailyTemp a, DailyTemp b) {
return a.get_temp() < b.get_temp(); cout << v[i].get_temp() << " ";
} return 0;
bool operator==(DailyTemp a, DailyTemp b) { }
return a.get_temp() == b.get_temp();
}
Functions in Vector Template Class
Constructors
vector (const allocator_type & alloc = allocator_type()); // Default Constructor: construct a vector object
vector (size_type n, const value_type & val = value_type(), const allocator_type & alloc = allocator_type()); // Fill
Constructor: construct a vector object with n-element filled with val
vector (const vector & v); // Copy Constructor
template <class InputIterator> vector (InputIterator first, InputIterator last, const allocator_type & alloc =
allocator_type()); // Range Copy Constructor

Size and Capacity


size_type size () const; // Return the size (number of elements)
size_type capacity () const; // Return the storage allocated (in term of element)
bool empty () const; // Return true if size is 0
void reserve (size_type n); // Request for storage to hold n elements
void resize (size_type n, value_type val = value_type());
// resize to n, remove extra element or fill with val
size_type max_size () const; // Return the maximum number of element
void shrink_to_fit (); // (C++11) Request to shrink storage
Functions in Vector Template Class
Accessing Elements
value_type & operator[] (size_type n); // [n] operator (without index-bound check)
value_type & at (size_type n); // Return a reference to n-th element with index-bound check
value_type & front (); // Return a reference to the first element
value_type & back (); // Return a reference to the last element
Modifying Contents
void push_back (const value_type & val); // Append val at the end
void pop_back (); // Remove the last element
void clear (); // Remove all elements
Non-member Friend Functions
==, !=, <, >, <=, >= // Comparison Operators
// E.g.
template <class T, class Alloc>
bool operator== (const vector<T,Alloc> & left, const vector<T, Alloc> & right); // Compare two vectors. For == and !=, first
compare the size, then each element with equal algorithm. Stop at the first mismatch. For <, >, <=, >=, use
lexicographical_compare algorithm. Stop at first mismatch.
template <class T, class Alloc>
void swap (vector<T,Alloc> & v1, vector<T,Alloc> v2); // Swap the contents of containers v1 and v2. Both shall has the same
type, but can have different sizes.
Functions in Vector Template Class
Iterator
iterator begin(); // Return an iterator pointing to the first element
iterator end(); // Return an iterator pointing to the pass-the-end element
reverse_iterator rbegin(); // Return a reverse iterator pointing to the reverse beginning (last element), increasing a reverse
iterator to transverse in reverse order
reverse_iterator rend(); // Return a reverse iterator pointing to the reverse past-the-end

Iterator-based Operations
iterator insert (iterator pos, const value_type & val); // Single-Element: insert element val before iterator pos
void insert (iterator pos, size_type n, const value_type & val); // Fill: insert n copies of val before pos
template <class InputIterator>
void insert (iterator pos, InputIterator first, InputIterator last)
// Range-copy: copy the range [first, last) and insert before pos.

iterator erase (iterator pos); // Single-element: remove element pointed to by iterator pos
iterator erase (iterator first, iterator last); // Range: remove elements between [first,last)

void assign (size_type n, const value_type & val); // Fill: clear old contents and assign n copies of val
template <class InputIterator>
void assign (InputIterator first, InputIterator last); // Range: assign [first, last)
The List Template Class
• list is a class template, declared in the list header.
• The list class supports a bidirectional, linear list.
• Unlike a vector, which supports random access, a list can be
accessed sequentially only.
• Since lists are bidirectional, they may be accessed front to back
or back to front.

50
List Basics
// List basics. // change contents of list
#include <iostream> p = lst.begin();
#include <list> while (p != lst.end())
using namespace std; {
int main() Create a list of integers *p = *p + 100;
{ p++;
list<int> lst; // create an empty list }
int i; cout << "Contents modified: ";
for (i = 0; i < 10; i++) p = lst.begin();
lst.push_back(i); Insert elements while (p != lst.end())
cout << "Size = " << lst.size() << endl; {
cout << "Contents: "; cout << *p << " ";
list<int>::iterator p = lst.begin(); p++;
while (p != lst.end()) }
{ return 0;
cout << *p << " "; Access with iterator }
p++;
}
cout << "\n\n";
// Understanding end().
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lst; // create an empty list
?drawkcab
How wouldtsil
youa print
tnirp int i;
for (i = 0; i < 10; i++)
auoy
listdluow
backward?
woH lst.push_back(i);
cout << "List printed backwards:\n";
list<int>::iterator p = lst.end();

?
while (p != lst.begin()) {
p--; // decrement pointer before using
cout << *p << " ";
}
return 0;
}
Push_Back() and Push_Front()
/* Demonstrating the difference between list<int>::iterator p;
push_back() and push_front(). */ cout << "Contents of lst1:\n";
#include <iostream> p = lst1.begin();
#include <list> while (p != lst1.end())
using namespace std; {
int main() cout << *p << " ";
{ p++;
list<int> lst1, lst2; }
int i; cout << "\n\n";
for (i = 0; i < 10; i++) cout << "Contents of lst2:\n";
lst1.push_back(i); p = lst2.begin();
for (i = 0; i < 10; i++) while (p != lst2.end())
lst2.push_front(i); {
cout << *p << " ";
p++;
}
return 0;
}
Sort a List
// Sort a list. // sort the list
#include <iostream> lst.sort(); Sort list
#include <list> cout << "Sorted contents:\n";
#include <cstdlib> p = lst.begin();
using namespace std; while (p != lst.end())
int main() {
{ cout << *p << " ";
list<int> lst; p++;
int i; }
// create a list of random integers return 0;
for (i = 0; i < 10; i++) }
lst.push_back(rand());
cout << "Original contents:\n";
list<int>::iterator p = lst.begin();
while (p != lst.end()) {
cout << *p << " ";
p++;
}
cout << endl << endl;
Merge Two Lists
// Merge two lists. cout << "Contents of lst2:\n";
#include <iostream> p = lst2.begin();
#include <list> while (p != lst2.end()) {
using namespace std; cout << *p << " ";
int main() { p++;
list<int> lst1, lst2; }
int i; cout << endl << endl;
for (i = 0; i < 10; i += 2) lst1.push_back(i); // now, merge the two lists
for (i = 1; i < 11; i += 2) lst2.push_back(i); lst1.merge(lst2); Merge lists
cout << "Contents of lst1:\n"; if (lst2.empty()) cout << "lst2 is now empty\n";
list<int>::iterator p = lst1.begin(); cout << "Contents of lst1 after merge:\n";
while (p != lst1.end()) { p = lst1.begin();
cout << *p << " "; while (p != lst1.end()) {
p++; cout << *p << " ";
} p++;
cout << endl << endl; }
return 0;
}
Store Objects in List
class myclass { int main() {
int a, b, sum; Mandatory
int i;
public: list<myclass> lst1; // create first list
myclass() { a = b = 0; } for (i = 0; i < 10; i++) lst1.push_back(myclass(i, i));
myclass(int i, int j) { cout << "First list: ";
a = i; b = j; sum = a + b; list<myclass>::iterator p = lst1.begin();
} Mandatory while (p != lst1.end()) { cout << p->getsum() << " "; p++; }
int getsum() { return sum; } cout << endl;
friend bool operator<(const myclass &o1, const myclass &o2) { list<myclass> lst2; // create a second list
return o1.sum < o2.sum; for (i = 0; i < 10; i++) lst2.push_back(myclass(i * 2, i * 3));
} cout << "Second list: ";
friend bool operator>(const myclass &o1, const myclass &o2) { p = lst2.begin();
return o1.sum > o2.sum; while (p != lst2.end()) { cout << p->getsum() << " "; p++; }
} cout << endl;
friend bool operator==(const myclass &o1, const myclass &o2) { lst1.merge(lst2); // now, merget lst1 and lst2
return o1.sum == o2.sum; cout << "Merged list: ";
} p = lst1.begin();
friend bool operator!=(const myclass &o1, const myclass &o2) { while (p != lst1.end()) { cout << p->getsum() << " "; p++; }
return o1.sum != o2.sum; return 0;
} }
};
The Stack Template Class
• A container adaptor that permits LIFO access #include <iostream>
#include <stack>
• Uses vector, deque (by default) or list as using namespace std;
underlying container int main() {
    stack<int> stack;
• Defined in header stack     stack.push(21);
    stack.push(22);
template <class Type, class Container = deque<Type> >
    stack.push(24);
class stack;
    stack.push(25);
    int num = 0;
• Supported functions are     stack.push(num);
• empty()     stack.pop();
    stack.pop();
• size()
    stack.pop();
• top()
• push(), emplace(C++11), push_range (C+     while (!stack.empty())     {
        cout << stack.top() << " ";
+23)         stack.pop();
• pop()   }
• swap (C++11) }
57
The Queue Template Class
• A container adaptor that permits FIFO access #include <iostream>
#include <queue>
• Uses deque (by default) or list as underlying using namespace std;
container // Print the queue
void print_queue(queue<int> q){
• Defined in header queue     queue<int> temp = q;
template <class Type, class Container = deque<Type> >     while (!temp.empty()) {
class queue;         cout << temp.front()<<“ "<<temp.back()<<'\n';
        temp.pop();
• Supported functions are   }
• front()     cout << '\n';
}
• back()
int main(){
• empty()     queue<int> q1;
• size()     q1.push(1);
    q1.push(2);
• push(), emplace(C++11), push_range (C+     q1.push(3);
+23)     cout << "The first queue is : ";
• pop()     print_queue(q1);       
    return 0;
• swap() } 58
The Priority Queue Template Class
• A container adaptor that provides constant #include <iostream>
time lookup of the largest (by default) or #include <queue>
using namespace std;
smallest element int main(){
• Uses vector (by default) as underlying     priority_queue<int> q;
container     q.push(1);
    q.push(2);
• Defined in header queue     q.push(3);
    cout << "The priority queue is : ";
template< class T, class Container = std::vector<T>,
    while (!q.empty()) {
class Compare = std::less<typename Container::value_type>
        cout << q.top() <<" ";      
> class priority_queue;
        q.pop();
• Supported functions are   }
    cout << '\n';
• empty()
    return 0;
• size() }
• top()
• push(), emplace(C++11)
• pop()
59
The Pair Template Class teach yourself: tuple class
#include <iostream> #include <iostream>
#include <utility> #include <utility>
using namespace std; using namespace std;
int main(){ int main(){
    pair<int, char> PAIR1;     pair<char, int> pair1 = make_pair('A', 1);
    pair<string, double> PAIR2("GeeksForGeeks", 1.23);     pair<char, int> pair2 = make_pair('B', 2);
    pair<string, double> PAIR3;
    PAIR1.first = 100;     cout << "Before swapping:\n ";
    PAIR1.second = 'G';     cout << "Contents of pair1 = " << pair1.first << " "
    PAIR3 = make_pair("GeeksForGeeks is Best", 4.56);         << pair1.second;
    cout << PAIR1.first << " ";     cout << "Contents of pair2 = " << pair2.first << " "
    cout << PAIR1.second << endl;         << pair2.second;
    cout << PAIR2.first << " ";     pair1.swap(pair2);
    cout << PAIR2.second << endl;
    cout << PAIR3.first << " ";     cout << "\nAfter swapping:\n ";
    cout << PAIR3.second << endl;     cout << "Contents of pair1 = " << pair1.first << " "
        << pair1.second;
    return 0;     cout << "Contents of pair2 = " << pair2.first << " "
}         << pair2.second;

    return 0;
} 60
The Map Template Class
• The map class supports an associative container in which unique keys are
mapped with values.
• In essence, a key is simply a name that is given to a value.
• Once a value has been stored, it can be retrieved by using its key.
• Thus, in its most general sense, a map is a list of key/value pairs.
• A map can hold only unique keys. Duplicate keys are not allowed.
• To create a map that allows nonunique keys, use multimap.

61
Map Basics
// A simple map demonstration. char ch;
#include <iostream> cout << "Enter key: ";
#include <map> cin >> ch;
using namespace std; map<char, int>::iterator p;
int main() // find value given key
{ p = m.find(ch);
map<char, int> m; if (p != m.end())
int i; cout << "Its ASCII value is " << p->second;
// put pairs into map else
for (i = 0; i < 26; i++) cout << "Key not in map.\n";
{ return 0;
m.insert(pair<char, int>('A' + i, 65 + i)); }
}
Application of Maps
// Use a map to create a phone directory. int main(){
#include <iostream> map<name, phoneNum> directory;
#include <map> // put names and numbers into map
#include <cstring> directory.insert(pair<name, phoneNum>(name("Tom"), phoneNum("555-4533")));
using namespace std; directory.insert(pair<name, phoneNum>(name("Chris"), phoneNum("555-
class name { 9678")));
char str[40]; directory.insert(pair<name, phoneNum>(name("John"), phoneNum("555-8195")));
public: directory.insert(pair<name, phoneNum>(name("Rachel"), phoneNum("555-
name() { strcpy(str, ""); } 0809")));
name(char *s) { strcpy(str, s); } // given a name, find number
char *get() { return str; } char str[80];
}; cout << "Enter name: ";
// Must define less than relative to name objects. cin >> str;
bool operator<(name a, name b) { map<name, phoneNum>::iterator p;
return strcmp(a.get(), b.get()) < 0; p = directory.find(name(str));
} if (p != directory.end())
class phoneNum { cout << "Phone number: " << p->second.get();
char str[80]; else
public: cout << "Name not in directory.\n";
phoneNum() { strcmp(str, ""); } return 0;
phoneNum(char *s) { strcpy(str, s); } }
char *get() { return str; }
};
Algorithms in STL
• The STL defines a large number of algorithms for a variety of purposes (e.g.
searching, sorting, counting, manipulating) that operate on ranges of elements. 
• All of the algorithms are non-member template functions. This means that they
can be applied to any type of container.
• The algorithms operate on elements of STL container only indirectly through the
iterator. It accepts a pair of iterators, denoted as first and last, that mark the
range of operation as [first,last) (including first, but excluding last). For example,
sort(aVector.begin(), aVector.end()); // Sort the entire vector
sort(aVector.begin(), aVector.begin + aVector.size()/2); // Sort first half

• Some examples of algorithms are


• for_each, find, find_if, count, count_if, remove_copy, replace_copy, unique,
shuffle, transform, etc.
See https://en.cppreference.com/w/cpp/algorithm for the complete list
Algorithms: for_each
//Testing for_each algorithms (TestForEach.cpp)  // Invoke the given function (print, square)
#include <iostream>    // for each element in the range
#include <vector>    for_each(v.begin(), v.end, print);
#include <algorithm>    for_each(v.begin() + 1, v.begin() + 3, square);
using namespace std;    for_each(v.begin(), v.end, print);
     return 0;
void square(int & n); } 
void print(int & n); void square(int & n) { n *= n; } 
  void print(int & n) { cout << n << " "; }
int main() {
   vector<int> v;
   v.push_back(11);
   v.push_back(3);
   v.push_back(4);
   v.push_back(22);
 
 
Algorithms: count and count_if
// Demonstrate count(). // Demonstrate count_if().
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <cstdlib> #include <algorithm>
#include <algorithm> using namespace std;
using namespace std; /* This is a unary predicate that determines if number
int main() { is divisible by 3. */
    vector<bool> v; bool dividesBy3(int i){
    unsigned int i;     if ((i % 3) == 0) return true;
    for (i = 0; i < 10; i++) {     return false;
        if (rand() % 2) v.push_back(true); }
        else v.push_back(false); int main() {
  }     vector<int> v;
    cout << "Sequence:\n";     int i;
    for (i = 0; i < v.size(); i++)     for (i = 1; i < 20; i++) v.push_back(i);
        cout << boolalpha << v[i] << " ";     cout << "Sequence:\n";
    cout << endl;     for (i = 0; i < v.size(); i++) cout << v[i] << " ";
    i = count(v.begin(), v.end(), true);     cout << endl;
    cout << i << " elements are true.\n";     i = count_if(v.begin(), v.end(), dividesBy3);
    return 0;     cout << i << " numbers are divisible by 3.\n";
}     return 0;
}
Algorithms: remove_copy, replace_copy
#include <vector> // **** now, demonstrate replace_copy ****
#include <algorithm> cout << "Input sequence:\n";
using namespace std; for (i = 0; i < v.size(); i++) cout << v[i];
int main() cout << endl;
{ // replace spaces with colons
char str[] = "The STL is power programming."; replace_copy(v.begin(), v.end(), v2.begin(), ' ', ':');
vector<char> v, v2(30); cout << "Result after replacing spaces with colons:\n";
unsigned int i; for (i = 0; i < v2.size(); i++)
for (i = 0; str[i]; i++) v.push_back(str[i]); cout << v2[i];
// **** demonstrate remove_copy **** cout << endl
cout << "Input sequence:\n"; << endl;
for (i = 0; i < v.size(); i++) cout << v[i]; return 0;
cout << endl; }
// remove all spaces
remove_copy(v.begin(), v.end(), v2.begin(), ' ');
cout << "Result after removing spaces:\n";
for (i = 0; i < v2.size(); i++) cout << v2[i];
cout << endl << endl;
Algorithms: reverse and // An example of the transform algorithm.
transform #include <iostream>
#include <list>
// Demonstrate reverse. #include <algorithm>
#include <iostream> using namespace std;
#include <vector> // A simple transformation function.
#include <algorithm> double reciprocal(double i) { return 1.0 / i; // return reciprocal}
using namespace std; int main() {
int main() { list<double> vals;
vector<int> v; int i;
unsigned int i; // put values into list
for (i = 0; i < 10; i++) v.push_back(i); for (i = 1; i < 10; i++) vals.push_back((double)i);
cout << "Initial: "; // transform vals
for (i = 0; i < v.size(); i++) cout << v[i] << " "; p = transform(vals.begin(), vals.end(), vals.begin(), reciprocal);
cout << endl; cout << "Transformed contents of vals:\n";
reverse(v.begin(), v.end()); p = vals.begin();
cout << "Reversed: "; while (p != vals.end()) {
for (i = 0; i < v.size(); i++) cout << v[i] << " "; cout << *p << " ";
return 0; p++;
} }
return 0;
} Function ref: https://en.cppreference.com/w/cpp/algorithm/transform
Function Objects in STL
• Function Objects or Functors are objects that can be treated as though
they are a function or function pointer.
• Function objects are simply classes that define operator( ).
• The STL provides many built-in function objects, such as
• less, minus, negate, etc.
• It is also possible to define custom function objects.
• Functors that returns only true or false are called predicates
Function Objects - Unary
// Use a unary function object. // use the negate function object
#include <iostream> p = transform(vals.begin(), vals.end(), vals.begin(),
#include <list> negate<double>()); // call function object
#include <functional> cout << "Negated contents of vals:\n";
#include <algorithm> p = vals.begin();
using namespace std; while (p != vals.end())
int main() { {
list<double> vals; cout << *p << " ";
int i; p++;
// put values into list }
for (i = 1; i < 10; i++) vals.push_back((double)i); return 0;
cout << "Original contents of vals:\n"; } Function ref: https://en.cppreference.com/w/cpp/utility/functional/negate
list<double>::iterator p = vals.begin();
while (p != vals.end()) {
cout << *p << " ";
p++;
}
cout << endl;
Function Objects - Binary
// Use a binary function object. // transform vals
#include <iostream> p = transform(vals.begin(), vals.end(), divisors.begin(),
#include <list> vals.begin(), divides<double>()); // call
#include <functional> function object
#include <algorithm>
using namespace std; cout << "Divided contents of vals:\n";
int main() p = vals.begin();
{ while (p != vals.end())
list<double> vals; {
list<double> divisors; https://onlinegdb.com/GGmSfi-U1 cout << *p << " ";
int i; p++;
// put values into list }
for (i = 10; i < 100; i += 10) vals.push_back((double)i); return 0;
for (i = 1; i < 10; i++) divisors.push_back(3.0); }
Function Ref: https://en.cppreference.com/w/cpp/utility/functional/divides
cout << "Original contents of vals:\n";
list<double>::iterator p = vals.begin();
while (p != vals.end()) {
cout << *p << " ";
p++;
}
cout << endl;
User Defined Function Objects int main() {
list<double> vals;
// Create a reciprocal function object. int i;
#include <iostream> // put values into list
#include <list> for (i = 1; i < 10; i++) vals.push_back((double)i);
#include <functional> cout << "Original contents of vals:\n";
#include <algorithm> list<double>::iterator p = vals.begin();
using namespace std; while (p != vals.end()) {
// A simple function object. cout << *p << " ";
class reciprocal : unary_function<double, double> { p++;
public: }
result_type operator()(argument_type i) { cout << endl;
return (result_type)1.0 / i; // return reciprocal // use reciprocal function object
} p = transform(vals.begin(), vals.end(), vals.begin(),
}; reciprocal()); // call function object
cout << "Transformed contents of vals:\n";
p = vals.begin();
while (p != vals.end()) {
cout << *p << " ";
p++;
}
return 0;
}
Strings in C++
• C++ does not support a built-in string type like int, float etc.
• There are two ways of handling strings.
1. Using the traditional, null terminated character array; sometimes
referred to as a C string.

char str[] = "Hello world";

2. Using a class object of type string

string str("Hello World");


Why the String Class
• Null-terminated strings cannot be manipulated by any of the standard C+
+ operators.
• Nor can they take part in normal C++ expressions.
char s1[80], s2[80], s3[80];
s1 = "Alpha"; // can't do
s2 = "Beta"; // can't do
s3 = s1 + s2; // error, not allowed

• Using standard string class, it becomes possible to manage strings in the


same way as any other type of data: through the use of operators.
string s1, s2, s3;
s1 = "Alpha";
s2 = "Beta";  
s3 = s1 + s2;
cout << s1 << " " << s2 << " " << s3;
return 0;
Why the String Class (2)
• It is very easy to overrun the end of an array that holds a null-terminated
string due to programming error.
• For example, consider the standard string copy function strcpy( ). This
function contains no provision for checking the boundary of the target
array.
• If the source array contains more characters than the target array can
hold, then a program error or system crash is possible (likely).
• The standard string class prevents such errors.
The Strings Class
• The string class is not part of the STL, but has implemented many STL
features.
• string can be treated as a STL container of char.
• It defines member functions begin(), end(), rbegin(), rend() which
returns an iterator for forward and reverse transversal.
• Most of the algorithms (such as transform(), sort()) are applicable to
string, operating on individual characters.
• string is declared in the header <string>
Definition of The Strings Class For complete list check the link below
https://en.cppreference.com/w/cpp/string/basic_string

• The string class is a specialization of a more general template class called


basic_string.
template<
    class CharT,
    class Traits = std::char_traits<CharT>,
    class Allocator = std::allocator<CharT>
> class basic_string;

• Several typedefs for common character types are provided in header


<string> such as
Type Definition
std::string std::basic_string<char>
std::wstring std::basic_string<wchar_t>
std::u8string (C++20) std::basic_string<char8_t>
std::u16string (C++11) std::basic_string<char16_t>
std::u32string (C++11) std::basic_string<char32_t>
Basic String Usage
#include <iostream> // compare strings
#include <string>     if(str3 > str1) cout << "str3 > str1\n";
using namespace std;     if(str3 == str1+str2)
int main(){     cout << "str3 == str1+str2\n";
    string str1("Alpha");     /* A string object can also be assigned a normal
    string str2("Beta"); string. */
    string str3("Omega");     str1 = "This is a null-terminated string.\n";
    string str4;     cout << str1;
    // assign a string     // create a string object using another string
    str4 = str1; object
    cout << str1 << "\n"     string str5(str1);
         << str3 << "\n";     cout << str5;
    // concatenate two strings     // input a string
    str4 = str1 + str2;     cout << "Enter a string: ";
    cout << str4 << "\n";     cin >> str5;
    // concatenate a string with a C-string     cout << str5;
    str4 = str1 + " to " + str3;     return 0;
cout << str4 << "\n"; }
Some String Member Functions
// Demonstrate insert(), erase(), and replace(). #include <iostream>
#include <iostream> #include <string>
#include <string> using namespace std;
using namespace std; int main()
int main(){ {
    string str1("String handling C++ style.");     int i;
    string str2("STL Power");     string s1 ="Quick of Mind, Strong of Body, Pure of Heart";
    cout << "Initial strings:\n";     string s2;
    cout << "str1: " << str1 << endl;     i = s1.find("Quick");
    cout << "str2: " << str2 << "\n\n";     if (i != string::npos)   
    // demonstrate insert()         cout << "Match found at " << i << endl;
     cout << "Insert str2 into str1:\n";     // find last "of"
     str1.insert(6, str2);     i = s1.rfind("of");
     cout << str1 << "\n\n";     if (i != string::npos)
    // demonstrate erase()   {
    cout << "Remove 9 characters from str1:\n";         cout << "Match found at " << i << endl;
    str1.erase(6, 9);         cout << "Remaining string is:\n";
    cout << str1 << "\n\n";         s2.assign(s1, i, s1.size());
    // demonstrate replace         cout << s2;
    cout << "Replace 8 characters in str1 with str2:\n";   }
    str1.replace(7, 8, str2);     return 0;
    cout << str1 << endl; }
    return 0;
}
String as Containers
// Strings as containers.     // use the count() algorithm
#include <iostream>     i = count(str1.begin(), str1.end(), 'i');
#include <string>     cout << "There are " << i << " i's in str1\n";
#include <algorithm>     // use transform() to upper case the string
using namespace std;     transform(str1.begin(), str1.end(), str1.begin(), ::toupper);
int main()     p = str1.begin();
{     while (p != str1.end())
    string str1("Strings handling is easy in C++");         cout << *p++;
    string::iterator p;     cout << endl;
    unsigned int i;     return 0;
    // use size() }
    for (i = 0; i < str1.size(); i++)
        cout << str1[i];
    cout << endl;
    // use iterator
    p = str1.begin();
    while (p != str1.end())
        cout << *p++;
    cout << endl;
String in Other Containers
// Use a map of strings to create a phone directory.
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<string, string> directory;
    directory.insert(pair<string, string>("Tom", "555-4533"));
    directory.insert(pair<string, string>("Chris", "555-9678"));
    directory.insert(pair<string, string>("John", "555-8195"));
    directory.insert(pair<string, string>("Rachel", "555-0809"));
    string s;
    cout << "Enter name: ";
    cin >> s;
    map<string, string>::iterator p;
    p = directory.find(s);
    if (p != directory.end())
        cout << "Phone number: " << p->second;
    else cout << "Name not in directory\n";
    return 0;
}
C++ Input Output (IO)
Stream IO and File IO
Stream IO
• C/C++ IO are based on streams
• Streams are sequence of bytes flowing in and out of
the programs
• just like water and oil flowing through a pipe.

• In input operations, data bytes flow from an input


source (such as keyboard, file, network or another
program) into the program.
• In output operations, data bytes flow from the
program to an output sink (such as console, file,
network or another program).
• Streams acts as an intermediaries between the
programs and the actual IO devices, in such the way
that frees the programmers from handling the actual
devices, so as to achieve device independent IO
operations.
83
Ref: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html
C++ IO Headers, Templates and Classes For details check the link below:
https://en.cppreference.com/w/cpp/io

84
Ref: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp10_IO.html
Template Instantiations and typedef
• the basic_xxx template classes can be instantiated with a character type,
such as char and wchar_t.
• C++ further provides typedef statements to name these classes

typedef basic_ios<char> ios;


typedef basic_ios<wchar_t> wios;
typedef basic_istream<char> istream;
typedef basic_istream<wchar_t> wistream;
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
typedef basic_iostream<char> iostream;
typedef basic_iostream<wchar_t> wiostream;
typedef basic_streambuf<char> streambuf;
typedef basic_streambuf<wchar_t> wstreambuf;

85
C++ Predefined Streams
• When a C++ program begins execution, four built-in streams are
automatically opened. They are:

Stream Meaning Default


Device
cin Standard input Keyboard
cout Standard output Screen
cerr Standard error output Screen
clog Buffered version of cerr Screen

86
Formatted I/O
• C++ provides both the formatted and unformatted IO functions.
• In formatted or high-level IO, bytes are grouped and converted to types
such as int, double, string or user-defined types.
• In unformatted or low-level IO, bytes are treated as raw bytes and
unconverted.
• Formatted IO operations are supported via overloading the stream insertion
(<<) and stream extraction (>>) operators, which presents a consistent
public IO interface.

87
Formatted I/O
• The C++ I/O system allows to format I/O operations, such as
• set a field width,
• specify a number base, or
• determine how many digits after the decimal point will be displayed.
• There are two related but conceptually different ways to format
data.
1. Directly access members of the ios class. Specifically,
• setting various format status flags defined inside the ios class or
• calling various ios member functions.
2. Using special functions called manipulators that can be included as
part of an I/O expression.

88
Formatting Using ios Members
#include <iostream>
Flags using namespace std;
int main(){
• Adjustfield, • oct,     cout.setf(ios::showpoint);
• •     cout.setf(ios::showpos);
basefield, right,     cout << 100.0 <<"\n"; // displays +100.000
• boolalpha, • scientific,
• dec, • Showbase,     cout.setf(ios::uppercase | ios::scientific);
    cout << 100.12 <<"\n"; // displays 1.001200E+02
• Fixed, • showpoint,     cout.unsetf(ios::uppercase); // clear uppercase
• floatfield, • showpos,     cout << 100.12 <<"\n"; // displays 1.001200e+02
• hex, • skipws,     cout.unsetf(ios::showpos | ios::uppercase | ios::scientific);
• internal, • Unitbuf,     cout.precision(4);
• •     cout.width(10);
Left, uppercase     cout << 10.12345 << "\n"; // displays 10.12
    cout.fill('*');

Functions  
 
 
 
cout.width(10);
cout << 10.12345 << "\n"; // displays *****10.12
// field width applies to strings, too
• width( ),     cout.width(10);
• precision( ), and     cout << "Hi!" << "\n"; // displays *******Hi!
    cout.width(10);
• fill( )     cout.setf(ios::left); // left justify
    cout << 10.12345; // displays 10.12*****
    return 0;
} 89
Formatting Using Manipulators
#include <iostream>
C++ Manipulators #include <iomanip>
using namespace std;
• boolalpha • oct int main()
• dec • resetiosflags (fmtflags f) {
• endl • right     cout << hex << 100 << endl;
• ends • scientific     cout << setfill('?') << setw(10) << 2343.0;
• fixed • setbase(int base)     cout << setiosflags(ios::showpos);
• flush • setfill(int ch)     cout << setiosflags(ios::showbase);
• hex • setiosflags(fmtflags f)     cout << 123 << " " << hex << 123;
• internal • setprecision (int p)
    bool b;
• left • setw(int w)     b = true;
• nobooalpha • showbase     cout << b << " " << boolalpha << b << endl;
• noshowbase • showpoint     cout << "Enter a Boolean value: ";
• noshowpoint • showpos     cin >> boolalpha >> b;
    cout << "Here is what you entered:  " << b;
• noshowpos • skipws }
• noskipws • unitbuf
• nounitbuf • uppercase
• nouppercase • ws
90
Overloading << and >>
• The << and the >> operators are overloaded in C++ to perform I/O
operations on C++'s built-in types.
• It is possible to overload these operators so that they perform I/O
operations on types that you create.
• In the language of C++, the << output operator is referred to as the
insertion operator because it inserts characters into a stream.
• Likewise, the >> input operator is called the extraction operator because it
extracts characters from a stream.
• The functions that overload the insertion and extraction operators are
generally called inserters and extractors, respectively.

91
Creating Custom Inserter and Extractor
#include <iostream> int main()
using namespace std; {
class myclass     myclass ob1, ob2;
{     cin >> ob1 >> ob2;
    int x, y;     cout << ob1 << ob2;
public:     return 0;
    friend ostream &operator<<(ostream &out, myclass& ob); }
    friend istream &operator>>(istream &in, myclass& ob);
};
istream &operator>>(istream &in, myclass& ob)
{
    in >> ob.x >> ob.y;    
    return in;
} inserter

ostream &operator<<(ostream &out, myclass& ob)


{
    out << "x : " << ob.x << ", y : " << ob.y << endl;
    return out;
} extractor

92
C++ File I/O
• A computer file is stored on a secondary storage device (e.g., disk)
• permanent
• can be used to
• provide input data to a program
• or receive output data from a program
• or both;
• should reside in project directory for easy access;
• must be opened before it is used

93
C++ File I/O
• C++ provides three classes to perform output and input of characters
to/from files:
• ofstream: Stream class to write on files
• ifstream: Stream class to read from files
• fstream: Stream class to both read and write from/to files.
• These classes are derived directly or indirectly from the classes istream and
ostream
• Done with the same operations (insertion, extraction) as keyboard input
and monitor output
• Simply open input or output object with connection to a file and use it
where you would use cin or cout

94
C++ File I/O
• To work with files one needs to -
• include <fstream>

• create input object of type ifstream

• or output object of type ofstream

95
C++ File I/O
• A file needs to be opened by ifstream before read or ofstream to write or
fstream to read and write

• void ifstream::open(const char *filename, openmode mode=ios::in)

• void ofstream::open(const char *filename, openmode mode=ios::out|ios::trunc)

• void fstream::open(const char *filename, openmode mode=ios::in|ios::out)

96
C++ File I/O
• The value of mode determines how the file is opened
• Type openmode is an enumeration defined by ios that contains the
following values:
• ios::app
• ios::ate
• ios::binary
• ios::in
• ios::out
• ios::trunc
• You can combine two or more of these value together by ORing them
• If open() fails the stream will evaluate to false

97
C++ File I/O: Writing and Reading
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
using namespace std; using namespace std;
int main() int main()
{ {   
    ofstream myfile;     char ch;
    myfile.open("example.txt");     ifstream myfile("example.txt");
    myfile << "Writing this to a file.\n";     if (myfile.is_open())
    myfile.close();     {
    return 0;         while (!myfile.eof())
}         {
            myfile >> ch;
            cout << ch;
        }
        cout << endl;
        myfile.close();
    }
    else
        cout << “Unable to open file” return 0;

    return 0;
}
98
C++ File I/O: Writing and Reading (Unformatted Binary)
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <cstdlib> #include <cstdlib>
using namespace std; using namespace std;
int main() int main()
{ {
    char str[100] = "I love Bangladesh";     char ch;
    ofstream out("myfile.txt", ios::out |     ifstream in("myfile.txt", ios::in |
ios::binary); ios::binary);
    if (!out.is_open())     if (!in.is_open())
    {     {
        cout << "Cannot open file" << endl;         cout << "Cannot open file" << endl;
        exit(1);         exit(1);
    }     }
    for (int i = 0; str[i]; i++)     while (!in.eof())
        out.put(str[i]);     {
    out.close();         in.get(ch);
        cout << ch;
    return 0;     }
}     cout << endl;
    in.close();

    return 0;
} 99
C++ File I/O (Unformatted Binary) Random Access
• istream &seekg(off_type offset, seekdir origin)
• A member function of ifstream and fstream
• Moves the current get pointer offset number of bytes from the specified origin
• ostream &seekp(off_type offset, seekdir origin)
• A member function of ofstream and fstream
• Moves the current put pointer offset number of bytes from the specified origin
• seekdir is an enumeration defined in ios with the following values:
• ios::beg
• ios::cur
• ios::end

100
C++ File I/O (Unformatted Binary) Random Access
• pos_type tellg()
• Returns current position of get pointer
• pos_type tellp()
• Returns current position of put pointer

• istream &seekg(pos_type position)


• ostream &seekp(pos_type position)
• Ovreloaded versions of seekg and seekp

101
C++ File I/O (Unformatted Binary) Random Access
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>

using namespace std; using namespace std;

int main(int argc, char **argv) int main(int argc, char **argv)
{ {
    fstream myFile("test.txt", ios::in |    
ios::out | ios::trunc);     long position;
    fstream file;
    myFile << "Hello World";
    file.open("myfile.txt");
    myFile.seekg(6, ios::beg);
    file.write("this is an apple", 16);
    char A[6];     position = file.tellp();
    myFile.read(A, 5);
    A[5] = '\0';     file.seekp(position - 7);
    file.write(" sam", 4);
    cout << A << endl;     file.close();
}
    myFile.close();

} 102
C++ File I/O: Status Checking
• C++ I/O System maintains status information about the outcome of each
I/O operation
• The current status of an I/O stream is described in an object of type iostate,
which is an enumeration defined in ios with the following values:
• ios::goodbit
• ios::eofbit
• ios::failbit
• ios::badbit
• To read the I/O status you can use rdstate() function
• iostate rdstate()
• It is a member of ios and inherited by all the streams

103
C++ File I/O: Status Checking
#include <iostream> void checkstatus(ifstream &in)
#include <fstream> {
#include <cstdlib>     ios::iostate s;
using namespace std;     s = in.rdstate();
void checkstatus(ifstream &in);     if (s & ios::eofbit)
int main(){         cout <<"EOF encountered" << endl;
    char ch;     else if (s & ios::failbit)
    ifstream in("myfile.txt");         cout<<"Non - Fatal I / O error encountered"<<endl;
    if (!in.is_open()){     else if (s & ios::badbit)
        cout << "Cannot open file" << endl;         cout <<"Fatal I / O error encountered" << endl;
        exit(1); }
    }
    while (!in.eof()){
        ch = in.get();
        checkstatus(in);
        cout << ch;
    }

    cout << endl;


    in.close();
    return 0;
}
104
C++ File I/O: Status Checking
• The status can be determined by using following ios member functions
those have also been inherited by all the streams
• bool eof()

• bool good()

• bool fail()

• bool bad()

105
C++ File I/O: Status Checking
 while (!in.eof())
    {
        ch = in.get();
        if (in.fail() || in.bad())
        {
            cout <<“I / O Error … terminating” << endl;
            return 1;
        }
        cout << ch;
    }

106
C++
Miscellaneous Topics
Static Members

108
Static Member
• A data member that is declared static is shared by all
instances of that class and is uniquely stored in one place.
• Non-static data members are created for each instance of
the class.
• A static member (function or variable) can be accessed in the
form -- class_name::member, provided it has public visibility
instead of using its instance or object
• Without static data member, data that was required by all
instances of a class would have to be global.

109
Static Member Variables
• The same static member variable will be used by any classes
derived from the class that contains the static variable
• A static member variable in a sense exists before any object of
its class is created
• Declaration of a static member is not enough; you must define
it outside the class. To do this you must re-declare the static
variable.
• All static member variables are initialized to 0 by default.

110
Static Member Variable (Syntax)
Declaration of
Static Variable
class StaticTest{ main(){
static int i; StaticTest s1,s2;
public: s1.seti(30);
void seti (int n){i=n;} cout<< s2.geti();
int geti(){return i;} }
} Definition of
Static Variable

int StaticTest::i;

111
Static Member Data in Memory
c1 c2 c3
data1
data1
data1 data2
class c { … }; data2
data2

data1
data2 data3
static data3 data4
static data4

c c1, c2, c3;

112
Static Member Functions
• A static member function can have access to only other static
members (functions or variables). Off course it can access global
data & functions.
• A Static member function does not have a this pointer
• Virtual is not allowed
• Can not be declared as const or volatile
• Can be invoked by any object of its class or can be called
independent of any object via class name and the scope
resolution operator.

113
Static Member Functions
#include <iostream> int main()
using namespace std; {
StaticTest s1, s2;
class StaticTest s1.seti(30);
{ cout << s2.geti()<<endl;
static int i; cout << s1.getVal()<<endl;
cout<<StaticTest::getVal()<<endl;
public: return 0;
void seti(int n) { i = n; } }
int geti() { return i; }
static int getVal(){return i;}
};

int StaticTest::i;

114
Conversion Function

115
User-defined Type conversions
• A conversion operator can be used to convert an object of one
class into
• an object of another class
• a built-in type
• Syntax
operator type() { return a ‘type’ value}
• Return type is the name of the function

116
Conversion Example
class String{
char *str;
public: void main(){
Default Constructor String(){… … …} String str1("Hello");
String (char *s){ String str2="Bye";
int len=strlen(s); String str3=str1;
Conversion Constructor
str=new char[len+1]; str3=“Hello”;
strcpy(str,s);
char* p= str3;
}
strcpy(p,str3);
String (const String &st){
Copy Constructor
int len=strlen(st.str);
str=new char[len+1];
strcpy(str,st.str);
}
Overloaded = operator operator=(char* p){… ... …}
Conversion operator operator char*(){return str;}
}; 117
Namespaces

118
Namespaces
• Namespaces allows same name to be used in different
context
• Localizes the visibility of names declared within it
• Syntax:
namespace name{
//declarations
}

119
Example
using namespace std;
namespace myNS1{
main(){
int i=10;
………
cout<< myNS1::i;
} cout<<myNS2::i;
namespace myNS2{ }
int i=20; main(){
……… std::cout<< myNS1::i;
} std::cout<<myNS2::i;
}

120
Rules and Restrictions
• Namespaces must be declared outside of all other scopes
• ‘using namespace’ is only valid in the box where it is declared
• Namespaces can be nested with one another
• Namespaces can be split files or within a single file
• Unnamed namespaces allows to create identifiers that are
unique within a file

121
Thank You

122

You might also like