On 2016-11-14 08:51 AM, Mason wrote: > On 12/11/2016 08:04, nick wrote: > >> On 2016-11-12 01:37 AM, Andrew Pinski wrote: >> >>> Anyways I think the problem is you assume >>> new Record*[N]; will NULL out the array. It does not. >> >> Shouldn't new overwrite that memory with a null block >> or is new so stupid that it doesn't do this [...] > > Hello, > > First, while compiler bugs (or bugs in low-level supporting libraries) > do exist, they are rare. Bugs lurk in user code 99.44% of the time. > (I'm told that's a real statistic.) > > Second, you expect dynamically-allocated memory to be zeroed. Consider the > case where an app requests a large memory block, and intends to initialize > it to non-0 values. Zeroing such a block would be a pure waste of CPU. > > cf. also short-comings of strncpy() > > Regards. > It was my fault actually anyhow I do have one more question with my code which I will paste below which has been causing me issues. I for some reason have not figured out how to copy over the buckets for the table, if you have any ideas please let me known and this is what is causing issues: while(entry!=nullptr && entry->next_){ insert=new Record(entry->key_,entry->data_); std::cout<<table_[i]->next_->key_<<table_[i]->data_; entry=entry->getNext(); insert=insert->getNext(); } #include <stdio.h> #include <string> #include <utility> #include<iostream> using namespace std; /*The functions I updated for Simple Table are 1.search 2.grow 3.update 4.Bothe Copy Constructor and Copy Assignment 5.Destructor */ template <class TYPE> class Table { public: Table() {} virtual bool update(const string& key, const TYPE& value) = 0; virtual bool remove(const string& key) = 0; virtual bool find(const string& key, TYPE& value) = 0; virtual ~Table() {} }; template <class TYPE> class SimpleTable :public Table<TYPE> { struct Record { TYPE data_; string key_; Record(const string& key, const TYPE& data) { key_ = key; data_ = data; } }; Record** records_; //the table int max_; //capacity of the array int size_; //current number of records held int search(const string& key); void sort(); void grow(); public: SimpleTable(int maxExpected); SimpleTable(const SimpleTable& other); SimpleTable(SimpleTable&& other); virtual int numRecords(); virtual bool isEmpty(); virtual bool update(const string& key, const TYPE& value); virtual bool remove(const string& key); virtual bool find(const string& key, TYPE& value); virtual const SimpleTable& operator=(const SimpleTable& other); virtual const SimpleTable& operator=(SimpleTable&& other); virtual ~SimpleTable(); }; //returns index of where key is found. template <class TYPE> int SimpleTable<TYPE>::search(const string& key) { int rc = -1; for (int i = 0; i<size_; i++) { if (records_[i]->key_ == key) { rc = i; break; } } return rc; } //checks if array is empty template <class TYPE> bool SimpleTable<TYPE>::isEmpty(){ return size_==0; } template <class TYPE> //return size of array int SimpleTable<TYPE>::numRecords(){ return size_; } //sort the according to key in table template <class TYPE> void SimpleTable<TYPE>::sort() { int minIdx = 0; for (int i = 0; i<size_; i++) { minIdx = i; for (int j = i + 1; j<size_; j++) { if (records_[j]->key_ < records_[minIdx]->key_) { minIdx = j; } } Record* tmp = records_[i]; records_[i] = records_[minIdx]; records_[minIdx] = tmp; } } //grow the array by one element template <class TYPE> void SimpleTable<TYPE>::grow() { Record** newArray = new Record*[max_ + 1]; max_ = max_ + 1; for (int i = 0; i<size_; i++) { newArray[i] = records_[i]; } records_ = std::move(newArray); } /* none of the code in the function definitions below are correct. You can replace what you need */ template <class TYPE> SimpleTable<TYPE>::SimpleTable(int maxExpected) : Table<TYPE>() { records_ = new Record*[maxExpected]; max_ = maxExpected; size_ = 0; } template <class TYPE> SimpleTable<TYPE>::SimpleTable(const SimpleTable<TYPE>& other) { records_ = new Record*[other.max_]; max_ = other.max_; size_ = 0; for (int i = 0; i<other.size_; i++) { update(other.records_[i]->key_, other.records_[i]->data_); } } template <class TYPE> SimpleTable<TYPE>::SimpleTable(SimpleTable<TYPE>&& other) { size_ = swap(other.size_); max_ = swap(other.max_); records_ = swap(other.records_); } template <class TYPE> bool SimpleTable<TYPE>::update(const string& key, const TYPE& value) { int idx = search(key); if (idx == -1) { if (size_ == max_) { grow(); } records_[size_++] = new Record(key, value); for(int i=0;i<size_;i++) { if(records_[i]->key_ > records_[size_-1]->key_) { Record* tmp = records_[i]; records_[i] = records_[size_-1]; records_[i] = tmp; } } } else { records_[idx]->data_ = value; } return true; } template <class TYPE> bool SimpleTable<TYPE>::remove(const string& key) { int idx; idx=search(key); if(idx!=-1){ delete records_[idx]; for(int i=idx;i<size_-1;i++){ records_[i]=records_[i+1]; } size_--; return true; } else { return false; } } template <class TYPE> bool SimpleTable<TYPE>::find(const string& key, TYPE& value) { int idx = search(key); if (idx == -1) { return false; } else { value = records_[idx]->data_; return true; } } template <class TYPE> const SimpleTable<TYPE>& SimpleTable<TYPE>::operator=(const SimpleTable<TYPE>& other) { if (this != &other) { if(records_){ delete[] records_; } records_ = new Record*[other.max_]; max_ = other.max_; size_ = 0; for (int i = 0; i<other.size_; i++) { update(other.records_[i]->key_, other.records_[i]->data_); } } return *this; } template <class TYPE> const SimpleTable<TYPE>& SimpleTable<TYPE>::operator=(SimpleTable<TYPE>&& other) { swap(records_, other.records_); swap(size_, other.size_); swap(max_, other.max_); return *this; } template <class TYPE> SimpleTable<TYPE>::~SimpleTable() { if (records_) { int sz=size_; for(int i=0;i<sz;i++){ remove(records_[0]->key_); } } } template <class TYPE> class HashTable :public Table<TYPE> { // This is the internal structure for array elements for hastable struct Record { TYPE data_; // data per array element string key_;//key to lookup for data element Record* next_; // next record to create linkly linked list for bucketing // Constructor to set values of Record Record(const string& key, const TYPE& data) { key_ = key; data_ = data; next_=nullptr; } //Returns key of Record string getKey() const { return key_; } //Sets key of Record string setKey(string key) { key_=key; } //Returns data member of Record TYPE getData() const { return data_; } //Sets data member of Record void setData(TYPE data) { data_=data; } //Gets next element in linked list for bucketing Record *getNext() const { return next_; } //Sets next element in linked list for bucketing void setNext(Record *next) { next_ = next; } }; Record** table_; //the table int size_;//size_ int cap;//max number of records allowed in table std::hash<std::string> hash;//hash function used public: HashTable(int maxExpected); HashTable(const HashTable& other); HashTable(HashTable&& other); int numRecords(); bool isEmpty(); virtual bool update(const string& key, const TYPE& value); virtual bool remove(const string& key); virtual bool find(const string& key, TYPE& value); virtual const HashTable& operator=(const HashTable& other); virtual const HashTable& operator=(HashTable&& other); virtual ~HashTable(); }; /* none of the code in the function definitions below are correct. You can replace what you need */ //returns size of table template <class TYPE> int HashTable<TYPE>::numRecords() { return size_; } //returns if hashtable has no records been inserted template <class TYPE> bool HashTable<TYPE>::isEmpty(){ return size_==0; } //Constructor that allocates memory equal to passed amount in maxExpected and sets hashtable to empty state template <class TYPE> HashTable<TYPE>::HashTable(int maxExpected) : Table<TYPE>() { int size_=0; table_=new Record*[maxExpected](); cap=maxExpected; } //Copy Constructor that creates a copy of passed hashtable as argument to create a new copy of including memory allocations template <class TYPE> HashTable<TYPE>::HashTable(const HashTable<TYPE>& other) { table_ = new Record*[other.cap]; size_=other.size_; hash = other.hash; cap=other.cap; for(int i=0;i<other.cap;i++){ if(other.table_[i]==nullptr){ table_[i]=nullptr; continue; } string key=other.table_[i]->getKey(); TYPE data=other.table_[i]->getData(); table_[i]=new Record(key,data); Record* entry=other.table_[i]->getNext(); Record* insert=table_[i]->getNext();; while(entry!=nullptr && entry->next_){ insert=new Record(entry->key_,entry->data_); std::cout<<table_[i]->next_->key_<<table_[i]->data_; entry=entry->getNext(); insert=insert->getNext(); } } } //Move constructor that moves the hashtable passed into the current table being constructed template <class TYPE> HashTable<TYPE>::HashTable(HashTable<TYPE>&& other) { swap(size_,other.size_); swap(cap,other.cap); swap(table_,other.records_); swap(hash,other.hash); } //Updates record with the string passed to the new data for the record's data element and returns true if found/updated otherwise false template <class TYPE> bool HashTable<TYPE>::update(const string& key, const TYPE& value) { int hashvalue=hash(key)%cap; Record* prev=nullptr; Record* entry=table_[hashvalue]; while (entry != nullptr && entry->getKey() != key) { prev=entry; entry=entry->getNext(); } if (entry == nullptr) { entry = new Record(key, value); if (prev == nullptr) { // insert as first bucket table_[hashvalue] = entry; } else { prev->setNext(entry); } } else { // just update the value entry->setData(value); } size_++; return true; } //Removes the record with the string passed for the key value and returns true if removed otherwise false if not found template <class TYPE> bool HashTable<TYPE>::remove(const string& key) { int hashValue = hash(key)%cap; Record *prev = nullptr; Record *entry = table_[hashValue]; while (entry != nullptr && entry->getKey() != key) { prev = entry; entry = entry->getNext(); } if (entry == nullptr) { // key not found return false; } else { if (prev == nullptr) { // remove first bucket of the list table_[hashValue] = entry->getNext(); } else { prev->setNext(entry->getNext()); } delete entry; } size_--; return true; } //Finds value in table and updates with the value passed if found returns true otherwise false template <class TYPE> bool HashTable<TYPE>::find(const string& key, TYPE& value) { int hashValue = hash(key)%cap; Record* entry =table_[hashValue]; while (entry != nullptr) { if (entry->getKey() == key) { value=entry->getData(); return true; } entry = entry->getNext(); } return false; } //Copy Assignment Operator creates copy of hashtable passed into current hashtable template <class TYPE> const HashTable<TYPE>&HashTable<TYPE>::operator=(const HashTable<TYPE>& other) { if (table_) { delete[] table_; } table_ = new Record*[other.cap]; size_=other.size_; hash = other.hash; cap=other.cap; for(int i=0;i<cap;i++){ if(other.table_[i]==nullptr){ table_[i]=nullptr; continue; } string key=other.table_[i]->getKey(); TYPE data=other.table_[i]->getData(); table_[i]=new Record(key,data); Record* entry=other.table_[i]->getNext(); while(other.table_[i]->getNext()){ table_[i]->next_=new Record(entry->key_,entry->data_); entry=entry->getNext(); } } return *this; } //Moves Assignment Operator which moves passed hashtable into current hashtable template <class TYPE> const HashTable<TYPE>& HashTable<TYPE>::operator=(HashTable<TYPE>&& other) { swap(size_,other.size_); swap(table_,other.table_); swap(hash,other.hash); swap(cap,other.cap); return *this; } //Destructor this destroys the hashtable when it goes out of scope or is called directly template <class TYPE> HashTable<TYPE>::~HashTable() { // destroy all buckets one by one for (int i = 0; i < cap; ++i) { Record *entry = table_[i]; while (entry != nullptr) { Record *prev = entry; entry = entry->getNext(); delete prev; } table_[i] = nullptr; } // destroy the hash table delete [] table_; }