510 likes | 792 Views
CSE 30331 Lecture 8 – Pointers, Lists & Ncurses. C++ Pointers Dynamic Memory Allocation Pointers within Classes Copy Constructors Destructors STL list class Iterators Ncurses I/O The text-based GUI. Pointer Illustration. // x is an int and // ip points to an int int x, *ip;
E N D
CSE 30331Lecture 8 – Pointers, Lists & Ncurses • C++ Pointers • Dynamic Memory Allocation • Pointers within Classes • Copy Constructors • Destructors • STL list class • Iterators • Ncurses I/O • The text-based GUI
Pointer Illustration // x is an int and // ip points to an int int x, *ip; x = 37; ip = &x; the data // fp points to a // dynamically allocated and // nameless float float *fp; the pointer fp = new float; *fp = -87.5;
Declaring Pointer Variables • Pointer declaration format <type> * <ptr_name>; • The declared pointer is a variable whose value is the address of a data item of the designated type. int *intPtr; char *charPtr;
Assigning Values to Pointers int m = 50, *intPtr; // here intPtr “points to” nothing intPtr = &m;// &m is the address of m // now intPtr “point to” m
Arrays and Pointers The amount the pointer is incremented is based on the sizeof() the base type of the array Ex: arr+5 is really &arr[0] + 5*sizeof(element_type)
Dynamic Memory • Pointer • Variable whose value is the address of another data value • Heap • System managed store of memory available to be allocated and deallocated while program is running • New • operator to dynamically allocate memory from the heap for program use • Delete • operator to dynamically deallocate memory no longer needed by program and return it to the heap
“new” and “delete” operators • Allocating & deallocating a single data location int *p = new int;// allocates it delete p;// deallocates it • Allocating & deallocating a dynamic array • Note square brackets used with delete operator. These ensure system deallocates ALL locations in array, not just the first one. // allocate space for 300 ints int *arr = new int[300]; // deallocate all 300 int locations delete [] arr;
Pointers and classes • Use # 1 • Dynamically allocate and de-allocate class objects • Use # 2 • Dynamically allocate and de-allocate storage used by class member variables • Why is this important? • When execution exits a block within which an object is declared, a destructor is called automatically. • The default destructor takes care of returning memory to the heap in usage # 1. • In usage # 2 we must write our own destructor to return the memory used by member variables, else it is lost to the program creating a memory leak.
Illustrating the Destructor Dynamic class from Ford & Topp (member 1 is data -- member 2 is a pointer)
The destructor template<typename T> class myVector // super simple vector class { public: // the constructor allocates the array myVector(int n=0) : dSize(n), data(NULL) { if (dSize > 0) data = new T(dSize); } // the destructor deallocates the array ~myVector() { if (data != NULL) delete [] data; } private: T *data; // the dynamically allocated array int dSize; // the size of the array };
Assignment & Copy Constructor • C++ provides for every class, default … • destructor, • assignment operator • copy constructor • All of these are “shallow” • They only copy or deallocate member variables, • NOT what they “point to” • For all classes that contain member variables that point to dynamically allocated memory, we must create our own destructor, assignment operator and copy constructor
Shallow Copy // object A has 10 data locations and B is a copy of A // (but BOTH point to the same dynamically allocated array) myVector<int> A(10), B(A); A B nSize data nSize data dynamically allocated array (10 locations)
Copy Constructors • The Copy Constructor is called whenever …. • 1)objects are passed as value parameters • 2) an object is returned as the function value • 3) an object is created and initialized with another object of the same class
Copy Constructor • Example: expanded myVector class • Note: parameter MUST be a reference parameter, because the copy constructor itself is used in passing by value template<typename T> myVector<T>::myVector(const myVector<T>& v) : dSize(v.dSize) { data = new T[v.dSize]; // allocate space for(int i=0; i<dSize; i++) data[i] = v.data[i]; // copy values }
IS the object *this objA; this-> memberl Points to the Object The Pointer ‘this’
Vectors vs. Lists • Vector • Direct access to elements by index • Dynamically resizable at end • Push_back, pop_back, and [ ] are Θ(1) • Insert, delete are Θ(n) because they require shifting of elements (n/2 on average) • List • Sequential access to all elements • Resizable by addition anywhere in list • Element access is Θ(n) requiring list traversal • Insert & delete are Θ(1), once we have access to the element
Model of a list object with links to next and previous elements
The List ADT • The list API • provides three constructors to declare a list object.
list(); Create an empty list. This is the default constructor. CLASS list <list> Constructors list(int n, const T&value = T()); Create a list with n elements, each having a specified value. If the value argument is omitted, the elements are filled with the default value for type T. Type T must have a default constructor, and the default value of type T is specified by the notation T(). list(T *first, T *last); Initialize the list, using the address range [first, last).
T& back(); Return the value of the item at the rear of the list. Precondition: The vector must contain at least one element. CLASS list <list> Operations bool empty() const; Return true if the vector is empty, false otherwise. T& front(); Return the value of the item at the front of the list. Precondition: The vector must contain at least one element.
void push_back(const T& value); Add a value at the rear of the list. Postcondition: The list has a new element at the rear, and its size increases by 1. CLASS list <list> Operations void pop_back(); Remove the item at the rear of the list. Precondition: The list is not empty. Postcondition: The list has a new element at the rear or is empty.
void push_front(const T& value); Add a value at the front of the list. Postcondition: The list has a new element at the front, and its size increases by 1. CLASS list <list> Operations void pop_front(); Remove the item at the front of the list. Precondition: The list is not empty. Postcondition: The list has a new element at the front or is empty. int size() const; Return the number of elements in the vector.
iterator begin(); Returns an iterator that references the first position (front) of the list. If the list is empty, the iterator value end() is returned. CLASS list <list> Operations const_iterator begin(); Returns a const_iterator that points to the first position (front) of a constant list. If the list is empty, the const_iterator value end() is returned. iterator end(); Returns an iterator that signifies a location immediately out of the range of actual elements. A program must not dereference the value of end() with the * operator.
iterator end(); Returns an iterator that signifies a location immediately out of the range of actual elements. A program must not dereference the value of end() with the * operator. CLASS list <list> Operations const_iterator end(); Returns a const_iterator that signifies a location immediately out of the range of actual elements in a constant list. A program must not dereference the value of end() with the * operator.
void erase(iterator pos); Erase the element pointed to by pos. Precondition: The list is not empty. Postcondition: The list has one fewer element. CLASS list <list> Operations void erase(iterator first, iterator last); Erase all list elements within the iterator range [first, last]. Precondition: The list is not empty. Postcondition: The size of the list decreases by the number of elements in the range.
CLASS list <list> Operations iterator insert(iterator pos, const T& value); Insert value before pos, and return an iterator pointing to the position of the new value in the list. The operation does not affect any existing iterators. Postcondition: The list has a new element.
*: Accesses the value of the item currently pointed to by the iterator. *iter; CLASS list::iterator <list> Operations ++: Moves the iterator to the next item in the list. iter++; --: Moves the iterator to the previous item in the list. iter--; ==: Takes two iterators as operands and returns true when they both point at the same item in the list. iter1 == iter2 !=: Returns true when the two iterators do not point at the same item in the list. iter1 != iter2
Palindromes • Strings that read the same forwards and backwards • Spaces and punctuation are ignored • Approaches (using lists) • 1 – Pop matching pairs of 1st & last chars • 2 – Scan inward to middle, matching corresponding outermost pairs
Palindrome (pop matches) // Assume spaces & punctuation removed // by caller; all letters in lower case template<typename T> bool isPal_1(const list<T>& alist) { list<T> copyList; copyList = alist; while (copyList.size() > 0) { if (copyList.front() != copyList.back()) return false; // mismatch, not a palindrome // pop matching pair copyList.pop_front(); copyList.pop_back(); } return true; // all pairs matched & popped }
Palindrome (scan inward) // Assume spaces & punctuation removed // by caller; all letters in lower case template<typename T> bool isPal_2(const list<T>& alist) { list<T>::iterator left, right; left = alist.begin(); right = alist.end(); right--; while (left != right) { if (*left != *right) return false; // mismatch, not a palindrome right--; // move right iter 1 posit left if (left == right) return true; // even length string, we’re done left++; // move left 1 posit right } return true; // all pairs matched & popped }
SeqSearch(no binary search possible here) // search values [*first,*last)- sequentially template<typename T> List<T>::iterator seqSearch ( list<T>::iterator& first, list<T>::iterator& last, const T& target) { list<T>::iterator iter = first; while((iter != last) && (*iter != target)) iter++; return iter; }
Ordered Lists • Values maintained in order by key • Numerical • Alphabetical • Lexicographical • Insertion is a two step process • Search for first list value (V) greater than or equal to the new value • Insertion of new value in front of list value (V) • Ordered List Examples • Inserting • Removing duplicates
Inserting in Ordered List template<typename T> void insertOrder (list<T>& orderedList, const T& item) { list<T>::iterator curr = orderedList.begin(), stop = orderedList.end(); // find insertion spot, 1st value >= item while((curr != stop) && (*curr < item)) curr++; // insert item ahead of *curr orderedList.insert(curr, item); }
Removing Duplicates // assume list is ordered. This way we can jump curr // ahead as soon as we find *p != *curr template<typename T> void removeDups (list<T>& orderedList) { list<T>::iterator curr, p; curr = orderedList.begin(); while (curr != orderedList.end()) { p = curr; p++; while ((p != orderedList.end() && (*p == *curr)) // pass p, move p forward, and call erase orderedList.erase(p++); curr = p; } }
Curses Library • Allows “text-based” GUI • Curses or Ncurses for Unix/Linux/AIX • Defined in “curses.h” header file • PDCurses (Public Domain Curses) for Dos/Windows • Supports mouse, keypads, color, buffered & non-buffered input, and some simple graphics (lines, boxes, etc)
Curses (Windows, etc) • Curses works by creating a window / screen / console data structure within which the program moves the cursor and performs output • A refresh() function updates the actual window / screen / console to reflect the logical one • See class web site for URLs of Curses resources / tutorials / examples/ etc.
Curses Basics – Hello World! #include<curses.h> int main() { // always do this first initscr(); // initialize curses // these are optional cbreak(); // input keys immediately available noecho(); // stop echoing inputs nonl(); // faster cursor movement clear(); // clear the screen // move cursor to location and output message // upper left screen corner is 0,0 move(12,5); // move cursor to row 12, column 5 printw(“Hello World\n”); // instead of cout << ... refresh(); // make it visible to us getch(); // wait for a key to be hit endwin(); // release window back to shell return 0; }
CursesInitialization & Shutdown • Must use … • initscr();// first, to initialize curses • endwin();// last, to return screen to normal • Probably use … • cbreak();// enable direct keystroke access • noecho();// prevent echoing of input • nonl();// speeds cursor movement • getmaxyx(stdscr,h,w);// get screen limits • Notes: • stdscris the default screen/window
CursesMoving cursor & I/O • Cursor & position • move(y,x);// move cursor to line y, char posit x • Upper left of screen is at position 0,0 • getyx(y,x);// returns current cursor location • I/O • printw(“%d %s”, num, str);// cout << • Parameters are same as printf() • Prints in window from current cursor location • scanw(“%f”,&realNum);// cin >> • Parameters are same as scanf() • Reads input stream as directed by format string • getch();// reads single keystroke • wgetch(stdscr);// reads single keystroke • From indicated window
CursesMoving cursor & I/O • Combined movement and I/O • mvprintw(y,x,“%d %s”, num, str); • Prints in window from cursor location y, x • mvscanw(y,x,“%f”,&realNum); • Reads input stream as directed by format string • Making it visible • refresh();// updates console • Makes it match logical window data structure
Curses Color • Only supported on certain terminal types (xterm is good bet) • set term=xterm at unix prompt before running program • Or run in separate xterm using ... • xterm -geometry 80x50 -e tttCM • start_color();// initializes color • init_pair(num,fg_color,bg_color); • Creates a COLOR_PAIR of foreground and background colors • xterm has 8 colors and 64 color pairs, max • attron(COLOR_PAIR(num)); • makes color pair the output attribute until turned off • attroff(COLOR_PAIR(num));
Curses COLORS • COLOR_BLACK • COLOR_RED • COLOR_GREEN • COLOR_YELLOW • COLOR_BLUE • COLOR_MAGENTA • COLOR_CYAN • COLOR_WHITE
Curses Using Special Keys • To use function keys, arrows, etc. Initialize with • keypad(stdscr,TRUE); • Must be used before both special key input • And before mouse event capture • prevents immediate translation to ASCII • Get key with • int key = getch(); • Test key with keycodes • KEY_DOWN, KEY_UP, KEY_LEFT, KEY_RIGHT • KEY_HOME, KEY_BACKSPACE • KEY_F(n) Function keys, for 0 <= n >= 63 • KEY_DC Delete character • KEY_IC Insert char or enter insert mode • KEY_ENTER Enter or send
Curses Mouse Support • Only in Ncurses (Linux & AIX) • Initialize for capture of events with • mousemask(ALL_MOUSE_EVENTS,NULL); • Specific masks (BUTTON1_CLICKED, ...) • Read mouse click with • int key = getch(); or • int key =wgetch(stdscr);
Curses Mouse Events • Processing event • Value read will equal KEY_MOUSE • Use getmouse(&event) to recover event from event queue • Use event.bstate to determine button state (which event) • Use event.x and event.y to determine where mouse was clicked in window MEVENT event;// data type for mouse event int key = getch(); if (key == KEY_MOUSE)// if it was the mouse if (getmouse(&event) == OK) { // get the event if (event.bstate & BUTTON1_CLICKED) { // so do something with // event.y; and event.x;
Example Curses Programs(on class web site) • hi.cpp • Simple curses “Hello World” program • bigHi.cpp • Shows big “HI” on screen • hw4_sample.cpp • Shows size of curses window, once open • mvbox.cpp • Moving star shape: Uses keyboard (letter) inputs • mvbox2.cpp • Moving star and box shapes: Uses keyboard (letter) inputs • mvbox3.cpp • Like mvbox2.cpp but also uses arrow keys and mouse • tttCM (executable only) • TicTacToe: Uses Color, mouse and keyboard inputs