implement file output

This commit is contained in:
Iurii Tatishchev 2024-06-18 12:22:47 -07:00
parent 46f8a4c043
commit 261acea264
Signed by: CaZzzer
GPG Key ID: E0EBF441EA424369
7 changed files with 146 additions and 121 deletions

View File

@ -15,3 +15,11 @@ int key_to_index(const CPU &key, int size) {
sum += k[i]; sum += k[i];
return sum % size; return sum % size;
} }
std::string to_string(const CPU &cpu) {
return cpu.cpuId + "; " +
std::to_string(cpu.releaseYear) + "; " +
std::to_string(cpu.coreCount) + "; " +
cpu.architecture + "; " +
std::to_string(cpu.baseClock) + ";";
}

9
CPU.h
View File

@ -57,7 +57,7 @@ public:
// Friend function declarations // Friend function declarations
friend void display(const CPU &cpu); friend void display(const CPU &cpu);
friend void iDisplay(const CPU& cpu, int level) { friend void iDisplay(const CPU &cpu, int level) {
for (int i = 1; i < level; i++) for (int i = 1; i < level; i++)
std::cout << ".."; std::cout << "..";
std::cout << level << "). " << cpu.cpuId << std::endl; std::cout << level << "). " << cpu.cpuId << std::endl;
@ -65,7 +65,10 @@ public:
friend std::ostream &operator<<(std::ostream &os, const CPU &cpu); friend std::ostream &operator<<(std::ostream &os, const CPU &cpu);
friend int key_to_index(const CPU &key, int size) ; friend int key_to_index(const CPU &key, int size);
friend std::string to_string(const CPU &cpu);
}; };
std::ostream &operator<<(std::ostream &os, const CPU &cpu); std::ostream &operator<<(std::ostream &os, const CPU &cpu);
@ -75,4 +78,6 @@ std::ostream &operator<<(std::ostream &os, const CPU &cpu);
*~**/ *~**/
int key_to_index(const CPU &key, int size); int key_to_index(const CPU &key, int size);
std::string to_string(const CPU &cpu);
#endif // INC_08_TEAM_PROJECT_CPU_H #endif // INC_08_TEAM_PROJECT_CPU_H

View File

@ -1,57 +1,65 @@
#ifndef INC_08_TEAM_PROJECT_HASHTABLE_H #ifndef INC_08_TEAM_PROJECT_HASHTABLE_H
#define INC_08_TEAM_PROJECT_HASHTABLE_H #define INC_08_TEAM_PROJECT_HASHTABLE_H
#include <stdexcept> #include <fstream>
#include "HashNode.h" #include "HashNode.h"
#include "CPU.h"
template <typename T> using std::string, std::ofstream, std::cout, std::endl;
class HashTable
{ template<typename T>
class HashTable {
private: private:
HashNode<T> *hashAry; HashNode<T> *hashAry;
int hashSize; int hashSize;
int count; int count;
public: public:
HashTable() HashTable() {
{
count = 0; count = 0;
hashSize = 97; hashSize = 97;
hashAry = new HashNode<T>[hashSize]; hashAry = new HashNode<T>[hashSize];
} }
HashTable(int n)
{ HashTable(int n) {
count = 0; count = 0;
hashSize = n; hashSize = n;
hashAry = new HashNode<T>[hashSize]; hashAry = new HashNode<T>[hashSize];
} }
~HashTable() { delete[] hashAry; } ~HashTable() { delete[] hashAry; }
int getCount() const { return count; } int getCount() const { return count; }
int getHashSize() const { return hashSize; } int getHashSize() const { return hashSize; }
double getLoadFactor() const { return 100.0 * count / hashSize; } double getLoadFactor() const { return 100.0 * count / hashSize; }
bool isEmpty() const { return count == 0; } bool isEmpty() const { return count == 0; }
bool isFull() const { return count == hashSize; } bool isFull() const { return count == hashSize; }
int getTotalCollisions() const; int getTotalCollisions() const;
int getMaxCollisions() const; int getMaxCollisions() const;
bool insert(const T &itemIn, int h(const T &key, int size)); bool insert(const T &itemIn, int h(const T &key, int size));
bool remove(T &itemOut, const T &key, int h(const T &key, int size)); bool remove(T &itemOut, const T &key, int h(const T &key, int size));
int search(T &itemOut, const T &key, int h(const T &key, int size)) const; int search(T &itemOut, const T &key, int h(const T &key, int size)) const;
void outputFile(const string &filename, string visit(const T &));
}; };
/*~*~*~* /*~*~*~*
Get total number of collisions throughout hash table Get total number of collisions throughout hash table
*~**/ *~**/
template <typename T> template<typename T>
int HashTable<T>::getTotalCollisions() const int HashTable<T>::getTotalCollisions() const {
{
int total = 0; int total = 0;
for (int i = 0; i < hashSize; i++) for (int i = 0; i < hashSize; i++) {
{ if (hashAry[i].getOccupied() == 1) {
if (hashAry[i].getOccupied() == 1)
{
total += hashAry[i].getNumCollisions(); total += hashAry[i].getNumCollisions();
} }
} }
@ -61,14 +69,11 @@ int HashTable<T>::getTotalCollisions() const
/*~*~*~* /*~*~*~*
Get longest collision length in hash table Get longest collision length in hash table
*~**/ *~**/
template <typename T> template<typename T>
int HashTable<T>::getMaxCollisions() const int HashTable<T>::getMaxCollisions() const {
{
int high = 0; int high = 0;
for (int i = 0; i < hashSize; i++) for (int i = 0; i < hashSize; i++) {
{ if (hashAry[i].getOccupied() == 1 && hashAry[i].getNumCollisions() > high) {
if (hashAry[i].getOccupied() == 1 && hashAry[i].getNumCollisions() > high)
{
high = hashAry[i].getNumCollisions(); high = hashAry[i].getNumCollisions();
} }
} }
@ -79,17 +84,14 @@ int HashTable<T>::getMaxCollisions() const
Insert an item into the hash table Insert an item into the hash table
It does not reject duplicates It does not reject duplicates
*~**/ *~**/
template <typename T> template<typename T>
bool HashTable<T>::insert(const T &itemIn, int h(const T &key, int size)) bool HashTable<T>::insert(const T &itemIn, int h(const T &key, int size)) {
{
if (count == hashSize) if (count == hashSize)
return false; return false;
int ind = h(itemIn, hashSize); int ind = h(itemIn, hashSize);
for (int i = 0; i < hashSize; i++) for (int i = 0; i < hashSize; i++) {
{ if (hashAry[(ind + i) % hashSize].getOccupied() != 1) {
if (hashAry[(ind + i) % hashSize].getOccupied() != 1)
{
hashAry[(ind + i) % hashSize].setOccupied(1); hashAry[(ind + i) % hashSize].setOccupied(1);
hashAry[(ind + i) % hashSize].setItem(itemIn); hashAry[(ind + i) % hashSize].setItem(itemIn);
hashAry[(ind + i) % hashSize].setNumCollisions(i); hashAry[(ind + i) % hashSize].setNumCollisions(i);
@ -110,25 +112,19 @@ bool HashTable<T>::insert(const T &itemIn, int h(const T &key, int size))
if not found: if not found:
- returns false - returns false
*~**/ *~**/
template <typename T> template<typename T>
bool HashTable<T>::remove(T &itemOut, const T &key, int h(const T &key, int size)) bool HashTable<T>::remove(T &itemOut, const T &key, int h(const T &key, int size)) {
{
int ind = h(key, hashSize); int ind = h(key, hashSize);
for (int i = 0; i < hashSize; i++) for (int i = 0; i < hashSize; i++) {
{ if (hashAry[(ind + i) % hashSize].getOccupied() == 1) {
if (hashAry[(ind + i) % hashSize].getOccupied() == 1) if (hashAry[(ind + i) % hashSize].getItem() == key) {
{
if (hashAry[(ind + i) % hashSize].getItem() == key)
{
itemOut = hashAry[(ind + i) % hashSize].getItem(); itemOut = hashAry[(ind + i) % hashSize].getItem();
hashAry[(ind + i) % hashSize].setOccupied(-1); hashAry[(ind + i) % hashSize].setOccupied(-1);
// Do not access a node with occupied of -1 // Do not access a node with occupied of -1
count--; count--;
return true; return true;
} }
} } else if (hashAry[(ind + 1) % hashSize].getOccupied() == 0) {
else if (hashAry[(ind + 1) % hashSize].getOccupied() == 0)
{
// If using linear probing and we come across a spot that has been empty since start, the item is not in the table // If using linear probing and we come across a spot that has been empty since start, the item is not in the table
break; break;
} }
@ -144,22 +140,16 @@ bool HashTable<T>::remove(T &itemOut, const T &key, int h(const T &key, int size
- returns the number of collisions for this key - returns the number of collisions for this key
if not found, returns -1 if not found, returns -1
*~**/ *~**/
template <typename T> template<typename T>
int HashTable<T>::search(T &itemOut, const T &key, int h(const T &key, int size)) const int HashTable<T>::search(T &itemOut, const T &key, int h(const T &key, int size)) const {
{
int ind = h(key, hashSize); int ind = h(key, hashSize);
for (int i = 0; i < hashSize; i++) for (int i = 0; i < hashSize; i++) {
{ if (hashAry[(ind + i) % hashSize].getOccupied() == 1) {
if (hashAry[(ind + i) % hashSize].getOccupied() == 1) if (hashAry[(ind + i) % hashSize].getItem() == key) {
{
if (hashAry[(ind + i) % hashSize].getItem() == key)
{
itemOut = hashAry[(ind + i) % hashSize].getItem(); itemOut = hashAry[(ind + i) % hashSize].getItem();
return hashAry[(ind + i) % hashSize].getNumCollisions(); return hashAry[(ind + i) % hashSize].getNumCollisions();
} }
} } else if (hashAry[(ind + 1) % hashSize].getOccupied() == 0) {
else if (hashAry[(ind + 1) % hashSize].getOccupied() == 0)
{
// If using linear probing and we come across a spot that has been empty since start, the item is not in the table // If using linear probing and we come across a spot that has been empty since start, the item is not in the table
break; break;
} }
@ -168,4 +158,31 @@ int HashTable<T>::search(T &itemOut, const T &key, int h(const T &key, int size)
return -1; return -1;
} }
template<class T>
void HashTable<T>::outputFile(const string &filename, string visit(const T &)) {
ofstream outputFile(filename);
cout << "Outputting data to \"" << filename << "\"" << endl;
if (!outputFile.good()) {
cout << "Error opening the output file: \"" << filename << "\"" << endl;
exit(EXIT_FAILURE);
}
T aT;
if (hashAry[0].getOccupied() == 1) {
aT = hashAry[0].getItem();
outputFile << visit(aT);
}
for (int i = 1; i < hashSize; i++) {
if (hashAry[i].getOccupied() == 1) {
aT = hashAry[i].getItem();
outputFile << endl << visit(aT);
}
}
outputFile.close();
}
#endif // INC_08_TEAM_PROJECT_HASHTABLE_H #endif // INC_08_TEAM_PROJECT_HASHTABLE_H

View File

@ -1,56 +0,0 @@
#include "Stack.h"
// Destructor
template<typename T>
Stack<T>::~Stack() {
while (!isEmpty()) {
pop();
}
}
// Push an element onto the stack
template<typename T>
void Stack<T>::push(const T &data) {
auto *newNode = new StackNode<T>(data);
newNode->next = top;
top = newNode;
count++;
}
// Pop the top element from the stack
template<typename T>
T Stack<T>::pop() {
if (isEmpty()) {
throw std::out_of_range("Stack is empty. Cannot pop.");
}
T data = top->data;
StackNode<T> *temp = top;
top = top->next;
delete temp;
count--;
return data;
}
// Get the top element of the stack without removing it
template<typename T>
T Stack<T>::peek() {
if (isEmpty()) {
throw std::out_of_range("Stack is empty. Cannot peek.");
}
return top->data;
}
// Get the number of elements in the stack
template<typename T>
int Stack<T>::getCount() const {
return count;
}
// Check if the stack is empty
template<typename T>
bool Stack<T>::isEmpty() const {
return count == 0;
}
// Explicit instantiation of the template class for the desired type(s)
template class Stack<CPU>;

50
Stack.h
View File

@ -13,17 +13,59 @@ private:
public: public:
Stack() : top(nullptr), count(0) {}; Stack() : top(nullptr), count(0) {};
~Stack() { throw std::logic_error("Not implemented: ~Stack()"); }; // Destructor
~Stack();
// Check if the stack is empty
[[nodiscard]] bool isEmpty() const { return count == 0; }; [[nodiscard]] bool isEmpty() const { return count == 0; };
// Get the number of elements in the stack
[[nodiscard]] int getCount() const { return count; }; [[nodiscard]] int getCount() const { return count; };
void push(const T &data) { throw std::logic_error("Not implemented: Stack.push()"); }; // Push an element onto the stack
void push(const T &data);
T pop() { throw std::logic_error("Not implemented: Stack.pop()"); }; // Pop the top element from the stack
T pop();
T peek() { throw std::logic_error("Not implemented: Stack.peek()"); }; // Get the top element of the stack without removing it
T peek();
}; };
template<typename T>
Stack<T>::~Stack() {
while (!isEmpty()) {
pop();
}
}
template<typename T>
void Stack<T>::push(const T &data) {
auto *newNode = new StackNode<T>(data);
newNode->next = top;
top = newNode;
count++;
}
template<typename T>
T Stack<T>::pop() {
if (isEmpty()) {
throw std::out_of_range("Stack is empty. Cannot pop.");
}
T data = top->data;
StackNode<T> *temp = top;
top = top->next;
delete temp;
count--;
return data;
}
template<typename T>
T Stack<T>::peek() {
if (isEmpty()) {
throw std::out_of_range("Stack is empty. Cannot peek.");
}
return top->data;
}
#endif //INC_08_TEAM_PROJECT_STACK_H #endif //INC_08_TEAM_PROJECT_STACK_H

View File

@ -3,11 +3,11 @@
template<typename T> template<typename T>
class StackNode { class StackNode {
public:
T data; T data;
StackNode<T> *next; StackNode<T> *next;
StackNode(const T &data) : data(data), next(nullptr) {} StackNode(const T &data) : data(data), next(nullptr) {}
}; };
#endif //INC_08_TEAM_PROJECT_STACKNODE_H #endif //INC_08_TEAM_PROJECT_STACKNODE_H

View File

@ -65,11 +65,11 @@ int main() {
processInput(command, cpuTable, cpuTree, undoManager, displayManager, searchManager); processInput(command, cpuTable, cpuTree, undoManager, displayManager, searchManager);
} }
catch (std::logic_error &e) { catch (std::logic_error &e) {
cout << e.what() << '\n'; cout << "Error: " << e.what() << '\n';
} }
} }
// Quit command received // Quit command received
// TODO: Write data to a file cpuTable.outputFile("output.txt", to_string);
cout << "Exiting program...\n"; cout << "Exiting program...\n";
return 0; return 0;
@ -81,7 +81,7 @@ void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree);
void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoManager<CPU> &undoManager); void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoManager<CPU> &undoManager);
// void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoManager<CPU> &undoManager); void handleFileOutput(HashTable<CPU> &hashTable, UndoManager<CPU> &undoManager);
void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<string> &cpuTree, void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<string> &cpuTree,
UndoManager<CPU> &undoManager, DisplayManager<CPU> &displayManager, UndoManager<CPU> &undoManager, DisplayManager<CPU> &displayManager,
@ -110,7 +110,7 @@ void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<strin
throw std::logic_error("Not yet implemented: Search for a CPU by the primary key"); throw std::logic_error("Not yet implemented: Search for a CPU by the primary key");
break; break;
case 'W': // Write data to a file case 'W': // Write data to a file
throw std::logic_error("Not yet implemented: Write data to a file"); handleFileOutput(cpuTable, undoManager);
break; break;
case 'T': // Hashtable statistics case 'T': // Hashtable statistics
cout << "Load factor: " << cpuTable.getLoadFactor() << std::endl; cout << "Load factor: " << cpuTable.getLoadFactor() << std::endl;
@ -140,7 +140,7 @@ void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree)
cin >> filename; cin >> filename;
int hashSize = findHashSize(filename); int hashSize = findHashSize(filename);
hashTable = HashTable<CPU>(hashSize); hashTable = HashTable<CPU>(hashSize);
tree = BinarySearchTree<string>(); tree.clear();
insertFile(filename, tree, hashTable); insertFile(filename, tree, hashTable);
cout << "Data from file \"" << filename << "\" added.\n"; cout << "Data from file \"" << filename << "\" added.\n";
@ -163,3 +163,12 @@ void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, UndoMa
cout << "CPU ID \"" << cpuId << "\" deleted.\n"; cout << "CPU ID \"" << cpuId << "\" deleted.\n";
} }
void handleFileOutput(HashTable<CPU> &hashTable, UndoManager<CPU> &undoManager) {
string filename;
cout << "Enter filename: ";
cin >> filename;
hashTable.outputFile(filename, to_string);
undoManager.clearUndoStack();
cout << "Data written to file \"" << filename << "\".\n";
}