C++ SparseArray class template for an array of arrays
#include <string> #include <iostream> #include <memory> using std::string; template<typename T> class SparseArray { class Node;//from w w w . j a v a 2s.co m using PNode = std::shared_ptr < Node >; private: PNode pFirst; // Pointer to first element node PNode pLast; // Pointer to last element node public: SparseArray() = default; // Constructor SparseArray(const SparseArray& array); // Copy constructor SparseArray& operator=(const SparseArray& array); // Assignment operator T& operator[](int index); // Subscript SparseArray bool element_exists(int index); // Return true if element exists void show(); // display array elements void insert(T* pObj); // Insert an element after the last private: // Node class definition class Node { public: int index {}; // Index of element T* pObject; // Address of object PNode pNext; // Pointer to next node PNode pPrevious; // Pointer to previous node Node(int newIndex) : index(newIndex), pObject(new T) {} // Constructor Node(const Node& node) : index(node.index), pObject(new T(*node.pObject)) {} // Copy constructor ~Node(){ delete pObject; } // Destructor }; }; // Copy constructor template template<typename T> SparseArray<T>::SparseArray(const SparseArray& array) { if (array.pFirst) { // If there is a first element pLast = pFirst = std::make_shared<Node>(*array.pFirst); // Duplicate it PNode pTemp; PNode pCurrent {array.pFirst}; while (pCurrent = pCurrent->pNext) { // Duplicate any further nodes pTemp = pLast; // Save the address of the last pLast = std::make_shared<Node>(*pCurrent); // Make the new one the last pTemp->pNext = pLast; // Set the next pointer of old last pLast->pPrevious = pTemp; // Set previous pointer of new last } } } // Assignment operator template template<typename T> SparseArray<T>& SparseArray<T>::operator=(const SparseArray& array) { if (this == &array) // Check for rhs same as lhs return *this; PNode pCurrent; if (array.pFirst) { pLast = pFirst = std::make_shared<Node>(*array.pFirst); Node* pTemp; pCurrent = array.pFirst; while (pCurrent = pCurrent->pNext) { pTemp = pLast; pLast = std::make_shared<Node>(*pCurrent); pTemp->pNext = pLast; pLast->pPrevious = pTemp; pTemp = pLast; } } return *this; } // Subscript operator for non-const objects template<typename T> T& SparseArray<T>::operator[](int index) { // Search the list for a node corresponding to index PNode pCurrent {pFirst}; while (pCurrent) { if (pCurrent->index == index) return *pCurrent->pObject; if (pCurrent->index > index) break; pCurrent = pCurrent->pNext; } PNode pNode = std::make_shared<Node>(index); pNode->pObject = new T; if (pCurrent) // If its not the end of the list we must insert the element { if (pCurrent->pPrevious) // If current has a previous node just insert the new node { pCurrent->pPrevious->pNext = pNode; pNode->pPrevious = pCurrent->pPrevious; pCurrent->pPrevious = pNode; pNode->pNext = pCurrent; } else // Current must be the first so add new node as first { pNode->pNext = pCurrent; pCurrent->pPrevious = pNode; pFirst = pNode; } } else { // We must append the element if (pLast) { pLast->pNext = pNode; pNode->pPrevious = pLast; pLast = pNode; } else pFirst = pLast = pNode; } return *pNode->pObject; // Return the new element } // Display the elements of a SparseArray template<typename T> void SparseArray<T>::show() { PNode pCurrent {pFirst}; while (pCurrent) { std::cout << "\n[" << std::setw(2) << pCurrent->index << "] = " << *pCurrent->pObject; pCurrent = pCurrent->pNext; } std::cout << std::endl; } // Test for existence of element at index template<typename T> bool SparseArray<T>::element_exists(int index) { PNode p {pFirst}; while (p) { if (p->index == index) return true; p = p->pNext; } return false; } // Insert an element after the last template<typename T> void SparseArray<T>::insert(T* pObj) { PNode pNode; if (pLast) // If there is a last element add the new one after it { pNode = std::make_shared<Node>(pLast->index + 1); pLast->pNext = pNode; pNode->pPrevious = pLast; pLast = pNode; } else // Otherwise the new one is the first pFirst = pLast = pNode = std::make_shared<Node>(0); if (pObj) // If there is an object pNode->pObject = new T(*pObj); // Create a duplicate else pNode->pObject = new T; // Otherwise, create a default T } int main() { string text; // Stores input prose or poem std::cout << "\nEnter a poem or prose over one or more lines." << "Terminate the input with #:\n"; getline(std::cin, text, '#'); SparseArray< SparseArray<string> > arrays; // Sparse array of arrays of strings string letters {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; // Extract words and store in the appropriate list string word; // Stores a word string separators {" \n\t,.\"?!;:"}; // Separators between words int start {}; // Start of a word int end {}; // separator position after a word while (string::npos != (start = text.find_first_not_of(separators, start))) { end = text.find_first_of(separators, start + 1); word = text.substr(start, end - start); arrays[letters.find(toupper(word[0]))].insert(&word); start = end; } // List the words in order 5 to a line const int perline {5}; int count {}; // Word counter int j {}; for (int i {}; i < 26; ++i) { if (!arrays.element_exists(i)) continue; j = 0; count = 0; while ((word = arrays[i][j++]).length()) { std::cout << word << ' '; if (!(++count % perline)) std::cout << std::endl; } std::cout << std::endl; } std::cout << std::endl; }