Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define...

34
Array Size Array Size Macro approach Macro approach 19 19 Macros Macros do not perform error checking. // macro approach // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0])) #define macro_array_size(array) (sizeof(array)/sizeof(array[0])) int ja[] = {0,1,2,3,4,5,6}; int ja[] = {0,1,2,3,4,5,6}; s = macro_array_size(ja); s = macro_array_size(ja); cout << “array_size = " << s << endl; cout << “array_size = " << s << endl; //correct, returns 7 //correct, returns 7 // int* pa = ja; int* pa = &ja[0]; s = macro_array_size(pa); cout << "macro_array_size = " << s << endl; //fails, //fails, returns 1 returns 1

Transcript of Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define...

Page 1: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

Array SizeArray SizeMacro approachMacro approach

1919

Macros Macros do not perform error checking.

// macro approach// macro approach

#define macro_array_size(array) (sizeof(array)/sizeof(array[0]))#define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

int ja[] = {0,1,2,3,4,5,6};int ja[] = {0,1,2,3,4,5,6}; s = macro_array_size(ja);s = macro_array_size(ja);cout << “array_size = " << s << endl; cout << “array_size = " << s << endl; //correct, returns 7//correct, returns 7

// int* pa = ja; int* pa = &ja[0]; s = macro_array_size(pa);

cout << "macro_array_size = " << s << endl; //fails, returns 1//fails, returns 1

Page 2: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

Array SizeArray SizeFunction template approachFunction template approach

1919

Here we pass an array by reference to array_size() array_size() that extracts the size of the array and returns it

template <typename T, size_t N>template <typename T, size_t N>inline size_t inline size_t array_sizearray_size(const T (&lhs)[N]) {(const T (&lhs)[N]) { return N;return N;}}

int ja[] = {0,1,2,3,4,5,6}; int ja[] = {0,1,2,3,4,5,6}; s = array_size(ja);s = array_size(ja);cout << "function template approach: " << s << endl; cout << "function template approach: " << s << endl; //correct, returns 7//correct, returns 7

// int* pa = ja; int* pa = &ja[0]; s = array_size(pa); cout << "macro_array_size = " << s << endl; // fails, no matching function for call // fails, no matching function for call // to `array_size(int*&) // to `array_size(int*&)

Page 3: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

Array SizeArray SizeClass template approachClass template approach

1919

Here, NN must be defined during the template class declaration, however.

template< typename T, size_t N >template< typename T, size_t N >class CalcArraySize{class CalcArraySize{

public: public: CalcArraySize(const T (&lhs)[N]) : size(N) { }CalcArraySize(const T (&lhs)[N]) : size(N) { } size_t getSize() { return size; } size_t getSize() { return size; } protected:protected: size_t size;size_t size;};};

int ia[10];

CalcArraySize<int, <int, 1010>> a(ia); s = a.getSize();

10 will be a fixed limit and that’s not exactly what we want.

Page 4: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

Array SizeArray SizeTwo arguments are still requiredTwo arguments are still required

1919

This works, but with two arguments required.

Vector(T* a, unsigned s) : size(s) { Vector(T* a, unsigned s) : size(s) { data = new T[size];data = new T[size]; for(int i=0; i < size; i++) {for(int i=0; i < size; i++) {

data[i] = a[i]; data[i] = a[i]; }}}}

int a[] = {11, 22, 33, 44, 55, 66, 77}; Vector<int> v(a, sizeof(a)/sizeof(a[0]));

Page 5: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

5

159.234159.234 LECTURE 17LECTURE 17

STLSTL

2121

Standard Template Library

Page 6: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

6

STLSTL

Standard Template LibraryStandard Template Library

1919

http://www.research.att.com/~bs/3rd_tour2.pdf

Bjarne Stroustrup, The C++ Programming Language (3rd Ed.), A Tour of the Standard Library

Page 7: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

7

STLSTLSome TermsSome Terms

What is STL?What is STL?

1919

STLSTL is a set of general-purpose template classes, built using the template mechanism.

What are its main parts?What are its main parts?

• Containers• Iterators• Algorithms

Page 8: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

8

STLSTLContainersContainers

1919

ContainersContainers are objects that hold other objects.

Sequence container: Sequence container: A container whose elements are kept in an ordinal sequence, like an array. The position of each element is independent of its value.

• vector (direct array access)• deque (double-ended queue)• list (linked-list, no indexed access, faster insertion/deletion)

What are they?What are they?

Different types of containers:Different types of containers:

Page 9: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

9

STLSTLContainersContainers

1919

Associative container:Associative container:

A container whose elements are kept in a sorted order for allowing efficient retrieval of values based on keys. The positions of the elements are completely determined by their values and those of the other elements in the container.

• map (look-up table structure)• sets (represent mathematical sets using union and intersection operations)

Page 10: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

10

STLSTLPreamble to IteratorsPreamble to Iterators

1919

#include <iostream>using namespace std;

template< class T> // a generic function to print an arrayvoid printArrayprintArray( T* a, int len ){ for(int j=0; j < len; j++) { cout << a[j] << " "; } cout << endl;}

Function Template

Page 11: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

11

STLSTLPreamble to IteratorsPreamble to Iterators

1919

int main(){

//typedef long int MyType; typedef long long int MyType;

const int Length = 10; MyType array[Length];

cout << "Size of MyType is: " << sizeof(MyType ) << endl; for( int i=0;i<Length;i++) { array[i] = i + 1; } printArray( array, Length );

This code will work regardless of what MyTypeMyType actually is.

Page 12: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

12

#include <iostream>using namespace std;

template< class T> // a generic func to print an arrayvoid printArray( T * a, int len ){ for(int j=0;j<len;j++) cout << a[j] << " "; cout << endl;}

int main(){

//typedef long int MyType; typedef long long int MyType;

const int Length = 10; MyType arrayarray[Length];

cout << "Size of MyType is: " << sizeof(MyType ) << endl;

for( int i=0;i<Length;i++){ arrayarray[i] = i + 1; }

printArray( arrayarray, Length );

MyType *ptr; MyType *start = arrayarray; MyType *end = array array + Length;

for( ptr = start; ptr != end; ptr++){for( ptr = start; ptr != end; ptr++){ *ptr * = -1;*ptr * = -1; cout << ptr << endl;cout << ptr << endl; }}

printArray( array,array, Length );

return 0;}

• Preamble to iterators:• Pointer arithmetic• Example Output:Size of MyType is: 81 2 3 4 5 6 7 8 9 10 0xbffffc100xbffffc180xbffffc200xbffffc280xbffffc300xbffffc380xbffffc400xbffffc480xbffffc500xbffffc58-1 -2 -3 -4 -5 -6 -7 -8 -9 -10

• This code will work regardless of what MyType actually is.

• The operators +,operators +, etc are all overloaded for pointers so that pointer arithmetic works as it should.

Page 13: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

13

Vector class

Vectors are dynamic arrays: arrays that can grow as needed.

The template specification for the vector class is:

template <class T>class vector{ //...};

When using the vector type the required header to be included is <<vectorvector>>

Page 14: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

14

Vector class

Vectors, being objects have additional advantages over ordinary arrays:

• it can be assigned values quickly (overloaded assignment operator)

• it can be passed by value

• it can be returned by value

Page 15: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

15

Vector class

vector(); //default constructor, creates an empty vector

vector(const vector* v); //copy constructor: creates a copy of the vector v;

//postcondition: *this == v;

vector(unsigned n, const T& x = T()); //constructor: creates a vector containing n copies of the element x;

//precondition: n >= 0;

//postcondition: size() == n;

~vector(); //destructor

Some important methods:

Page 16: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

16

Vector class

vector& operator=(const vector& v);

//assignment operator: assigns v to this vector, making a duplicate

//postcondition: *this == v;

unsigned size() const; //returns the number of elements in //this vector

unsigned capacity() const; //returns the maximum number of elements that this vector can have without being reallocated

void reserve(unsigned n); //reallocates this vector to a //capacity of n elements

//precondition: capacity() <= n

//postcondition: capacity() == n

bool empty() const; // true iff size() == 0;

Some important methods:

Page 17: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

17

Vector class

void assign(unsigned n, const T& x=T());

//clears this vector and then inserts n copies of the element x;

//postcondition: n >= 0;

//postcondition: size() == n;

T& operator[](unsigned i); //returns element at index i

//precondition: 0 <= i <= size();

//result is unpredictable if precondition is false;

T& at(unsigned i); // returns element at index i

//precondition: 0 <= i <= size();

//exception is thrown if precondition is false;

Some important methods:

Page 18: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

18

Vector class

T& front(); //returns the first element of this vector

T& back(); //returns the last element of this vector

iterator begin(); //returns an iterator pointing to the first element of this vector

iterator end(); //returns an iterator pointing to the dummy element that follows the last element of this vector

void push_back(const T& x); // appends a copy of the element x to the back of this vector;

//precondition: back() == x;

//postcondition: size() has been incremented;

Some important methods:

Page 19: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

19

Vector class

void push_back(const T& x); // appends a copy of the element x to the back of this vector;

//precondition: back() == x;

//postcondition: size() has been incremented;

void pop_back(); // removes the last element of this vector;

//precondition: size() > 0;

//postcondition: size() has been decremented;

Some important methods:

Page 20: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

20

Vector class

iterator insert(iterator p, const T& x); // inserts a copy of the element x at position p; returns p;

//precondition: begin() <= p <= end();

//postcondition: size() has been incremented;

Some important methods:

Page 21: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

21

Vector class

iterator erase(iterator p); // removes the element at position p; returns p;

//precondition: begin() <= p <= end();

//postcondition: size() has been decremented;

iterator erase(iterator p1, iterator p2); // removes the elements from position p1 to the position before p2;

//returns p1

//precondition: begin() <= p1 <= p2 <= end();

//postcondition: size() has been decremented by int(p2-p1);

void clear(); //removes all elements

//postcondition: size() == 0;

Some important methods:

Page 22: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

22

Vector class

Declaring/ defining a vector:

vector<int> iv;

vector<char> cv(5);

vector<char> cv(5, 'x');

vector<int> iv2(iv);

Page 23: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

23

Vector class

Using a vector:

// display original size of v cout << "Size = “ << v.size() v.size() <<endl;

/* put values onto end of a vector; the vector will grow as needed */ for(i=0; i<10; ++i) v.push_back(i);v.push_back(i);

// change contents of a vector for(i=0; i < v.size(); ++i) v[i] = v[i] + v[i];v[i] = v[i] + v[i];

Page 24: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

24

Vector class

// access using subscripting for(i=0; i<10; ++i) { cout << v[i]v[i] <<" "; } cout << endl;

// access via iterator vector<char>::iterator p = v.begin(); while(p != v.end()) { cout << *p*p << " "; ++p; }

Declaring an iterator:container_name :: iterator iterator_name

Page 25: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

25

Iterator

• An Iterator is just a convenient pseudo-pointer that is set up as a type to use associated with each container class.

• Various operators will have been set up to use with them e.g. =, ==, != and +=

• Standard idiomatic form:

int array[10];

for(int i=0; i<10; i++){

}

• Becomes:

vector<int> v(10);

vector<int>::iterator it;

for(it=v.begin();it != v.end();it++){

}

Page 26: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

26

IteratorsIterators

IteratorsIterators are objectsobjects designed to give us the ability to cycle through the content of a container. They act like pointers, locating one item in the container at a time.

All iterators have the same basic functionality, regardless of the type of container to which they are attached. The fundamental operations are:

• initialise the iterator at some initial position in the container

• return the data value stored at the current position

• change the data value stored at the current position

• determine whether there actually is an item at the iterator’s current position

• advance to the next position in the container

Page 27: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

Iterators can be adapted to provide backward traversal.

template <class ForwIterForwIter>void printprint(ForwIterForwIter first, ForwIterForwIter last, const char* title){ cout << title << endl; while ( first != last) cout << *first++ << '\t'; cout << endl;}

IteratorsIterators

Page 28: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

28

int main(){

int data[3] = { 9, 10, 11};

vector<int> d(data, data + 3); //auxiliary constructor

vector<int>::reverse_iterator p = d.rbegin();

print(p, d.rend(), "Reverse"); //...}

Example that uses a reverse iterator to traverse a sequence.

IteratorsIterators

See vector_2009.cpp

See vector_countries.cpp

Page 29: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

29

Let’s have a look at the Matrix class template implemented by connecting to the STL vector via composition.

SamplesSamples

2-D array using pure vector<vector<int>*>

See vector_of_vectors.cpp

See Matrix_stl.cpp

Page 30: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

30

• The standard template library (STLSTL) is the C++ library that provides generic programming for many standard data structures and algorithms.

• ContainersContainers come in two major families: sequence (are ordered) and associativeassociative (have keys for looking up elements).

• Iterators can be thought of as an enhanced pointer type.

• The algorithms use iterators to access containers.

SummarySummary

Page 31: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

31

Other standard components

STL relies upon several other standard components for support:

allocators: to manage memory allocation for a container

predicates: special functions returning true/false results

comparison functions, etc.

Page 32: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

32

C++ StandardC++Standard: http://www.cygnus.com/misc/wp/

International standard for the C++ programming language approved!

Morristown, New Jersey, USA, Friday, November 14, 1997

FOR IMMEDIATE RELEASE

This week, technical experts representing eight countries and about 40 companies involved with software technologies met in Morristown, New Jersey and completed the content of an international standard for the C++ programming language.

Page 33: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

33

Scope of the Standard:

The C++ standard covers both the C++ language itself and its standard library.

The standard library provides

•standard input/output,

•strings,

•containers (such as vectors, lists, and strings),

•non-numerical algorithms (such as sort, search, and merge), and support for numeric computation.

Page 34: Array Size Macro approach 19 Macros Macros do not perform error checking. // macro approach #define macro_array_size(array) (sizeof(array)/sizeof(array[0]))

34

The ISO/ANSI Standard for C++ was unanimously approved by the C++ Standardization Committee on June 23, 1998.

From: http://www.awl.com/cseng/meyerscd/cstandard.htm

The current status (June’99) is that C++ has an International Standard and the committee are in the process of handling Defect Reports. We shall continue to do this until 2003 when ISO rules require us to revise the Standard.

From: http://www.inquiry.com/techtips/cpp_pro/