diff --git a/.idea/misc.xml b/.idea/misc.xml
index 79b3c94..0b76fe5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 23a1873..6b86449 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,4 +18,6 @@ add_executable(08_team_project main.cpp
Stack.h
StackNode.cpp
StackNode.h
+ fio.h
+ fio.cpp
)
diff --git a/CPU.h b/CPU.h
index afce0b6..51f4924 100644
--- a/CPU.h
+++ b/CPU.h
@@ -64,19 +64,18 @@ public:
return os;
}
- friend int key_to_index(const CPU &key, int size);
+ friend int key_to_index(const CPU &key, int size) {
+ std::string k = key.getCpuId();
+ int sum = 0;
+ for (int i = 0; k[i]; i++)
+ sum += k[i];
+ return sum % size;
+ };
};
/*~*~*~*
Hash function: takes the key and returns the index in the hash table
*~**/
-int key_to_index(const CPU &key, int size)
-{
- std::string k = key.getCpuId();
- int sum = 0;
- for (int i = 0; k[i]; i++)
- sum += k[i];
- return sum % size;
-};
+int key_to_index(const CPU &key, int size);
#endif // INC_08_TEAM_PROJECT_CPU_H
diff --git a/fio.cpp b/fio.cpp
new file mode 100644
index 0000000..e2d4ea0
--- /dev/null
+++ b/fio.cpp
@@ -0,0 +1,202 @@
+#include
+#include "fio.h"
+
+bool isInteger(const string &str);
+
+bool isDouble(const string &str);
+
+using std::stringstream, std::ifstream, std::getline, std::cout, std::endl, std::stoi, std::stod, std::cin;
+
+int findHashSize(const string& filename) {
+ ifstream inputFile(filename);
+
+ if (!inputFile) {
+ cout << "Error opening the input file: \"" << filename << "\"" << endl;
+ return -1;
+ }
+ cout << "Reading data from \"" << filename << "\"" << endl;
+
+ int count = 0;
+ string line;
+ while (getline(inputFile, line)) {
+ if (line.size() != 0) {
+ count++;
+ }
+ }
+
+ count *= 2;
+
+ if (count < 5) {
+ return 5;
+ }
+
+ bool found = false;
+
+ while (!found) {
+ // Every prime number occurs only 1 number before or after a multiple of six. Every other number is divisible by either 2 or 3.
+ if ((count % 6) == 1) {
+ count += 4;
+ } else if ((count % 6) == 5) {
+ count += 2;
+ } else if ((count % 6) >= 2) {
+ count = count - (count % 6) + 5;
+ } else {
+ count += 1;
+ }
+
+ found = true;
+ for (int i = 5; i < count / 2;) {
+ if (count % i == 0) {
+ found = false;
+ break;
+ }
+
+ i += 2;
+
+ if (count % i == 0) {
+ found = false;
+ break;
+ }
+
+ i += 4;
+ }
+ }
+
+ return count;
+}
+
+void insertFile(const string& filename, BinarySearchTree &bst, HashTable &hash) {
+ ifstream inputFile(filename);
+ cout << "Reading data from \"" << filename << "\"" << endl;
+
+ if (!inputFile) {
+ cout << "Error opening the input file: \"" << filename << "\"" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ string line;
+ while (getline(inputFile, line)) {
+ int releaseYear, coreCount;
+ string name, architecture, strToNum;
+ double baseClock;
+
+ stringstream temp(line);
+
+ getline(temp, name, ';');
+
+ temp.ignore();
+ getline(temp, strToNum, ';');
+ releaseYear = stoi(strToNum);
+
+ temp.ignore();
+ getline(temp, strToNum, ';');
+ coreCount = stoi(strToNum);
+
+ temp.ignore();
+ getline(temp, architecture, ';');
+
+ temp.ignore();
+ getline(temp, strToNum, ';');
+ baseClock = stod(strToNum);
+
+
+ // create a CPU object and initialize it with data from file
+ CPU aCPU(name, releaseYear, coreCount, architecture, baseClock);
+ bst.insert(name);
+
+ hash.insert(aCPU, key_to_index);
+ }
+
+ inputFile.close();
+}
+
+
+void insertCPU(BinarySearchTree &bst, HashTable &hash) {
+ string tester, name, architecture;
+ int releaseYear, coreCount;
+ double baseClock;
+
+ cout << "Please enter the name of the CPU: ";
+ cin >> name;
+
+ CPU key(name, -1, -1, "", -1);
+ CPU checker;
+
+ if (hash.search(checker, key, key_to_index) != -1) {
+ cout << "Duplicate CPUs are not allowed!\n";
+ return;
+ }
+
+
+ cout << "Please enter the year the CPU was released: ";
+ cin >> tester;
+
+ while (!(isInteger(tester))) {
+ cout << "Please enter an integer: ";
+ cin >> tester;
+ }
+
+ releaseYear = stoi(tester);
+
+
+ cout << "Please enter the number of cores in the CPU: ";
+ cin >> tester;
+
+ while (!(isInteger(tester))) {
+ cout << "Please enter an integer: ";
+ cin >> tester;
+ }
+
+ coreCount = stoi(tester);
+
+
+ // Strings don't need to be tested
+ cout << "Please enter the architecture of the CPU: ";
+ cin >> architecture;
+
+
+ cout << "Please enter the base clock of the CPU: ";
+ cin >> tester;
+
+ while (!(isDouble(tester))) {
+ cout << "Please enter a decimal: ";
+ cin >> tester;
+ }
+
+ baseClock = stod(tester);
+
+
+ CPU aCPU(name, releaseYear, coreCount, architecture, baseClock);
+ bst.insert(name);
+
+ hash.insert(aCPU, key_to_index);
+}
+
+bool isInteger(const string& str) {
+ for (int i = 0; i < str.length(); i++) {
+ if (!(isdigit(str[i]))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool isDouble(const string& str) {
+ int chance = 0;
+
+ for (int i = 0; i < str.length(); i++) {
+ if (!(isdigit(str[i]))) {
+ if (str[i] == '.') {
+ if (chance >= 1) {
+ return false;
+ } else {
+ chance++;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+}
diff --git a/fio.h b/fio.h
new file mode 100644
index 0000000..e084433
--- /dev/null
+++ b/fio.h
@@ -0,0 +1,27 @@
+// Unit 5: File I/O
+// - Determine hash size based on the number of records in the file
+// - Read data from the input file and insert them into the hash table and BST
+// - Save to file (in hash table sequence)
+// - Re-hashing
+//
+// Written by: Kevin Cremin
+
+#ifndef INC_08_TEAM_PROJECT_FIO_H
+#define INC_08_TEAM_PROJECT_FIO_H
+
+#include
+#include
+#include
+#include "CPU.h"
+#include "HashTable.h"
+#include "BinarySearchTree.h"
+
+using std::string;
+
+int findHashSize(const string& filename);
+
+void insertFile(const string& filename, BinarySearchTree &bst, HashTable &hash);
+
+void insertCPU(BinarySearchTree &bst, HashTable &hash);
+
+#endif //INC_08_TEAM_PROJECT_FIO_H
diff --git a/main.cpp b/main.cpp
index f960fc7..ff12eb9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -32,13 +32,13 @@
#include "HashTable.h"
#include "BinarySearchTree.h"
#include "Stack.h"
+#include "fio.h"
using std::cin, std::cout, std::string, std::vector;
void processInput(char command, HashTable &table, BinarySearchTree &tree, Stack &stack);
-int main()
-{
+int main() {
// Print help table for commands
printHelp();
@@ -47,18 +47,15 @@ int main()
Stack undoStack;
char command = ' ';
- while (command != 'Q')
- {
+ while (command != 'Q') {
cout << "Enter an option (H - for help): ";
cin >> command;
command = toupper(command, std::locale());
// Temporary try catch block to handle unimplemented commands
- try
- {
+ try {
processInput(command, cpuTable, cpuTree, undoStack);
}
- catch (std::logic_error &e)
- {
+ catch (std::logic_error &e) {
cout << e.what() << '\n';
}
}
@@ -69,90 +66,82 @@ int main()
return 0;
}
-void insertCPU(HashTable &hashTable, BinarySearchTree &tree);
+void handleInsert(HashTable &hashTable, BinarySearchTree &tree);
+
+void handleFileInput(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack);
void deleteCPU(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack);
void undoDelete(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack);
-void processInput(char command, HashTable &cpuTable, BinarySearchTree &cpuTree, Stack &undoStack)
-{
- switch (command)
- {
- case 'H':
- printHelp();
- break;
- case 'I': // Insert a new record
- insertCPU(cpuTable, cpuTree);
- break;
- case 'F': // File input: add data from a file
- throw std::logic_error("Not yet implemented: File input: add data from a file");
- break;
- case 'D': // Delete one record
- deleteCPU(cpuTable, cpuTree, undoStack);
- break;
- case 'U': // Undo delete
- undoDelete(cpuTable, cpuTree, undoStack);
- break;
- case 'L': // List all CPUs sorted by primary key
- throw std::logic_error("Not yet implemented: List all CPUs sorted by primary key");
- break;
- case 'S': // Search for a CPU by the primary key
- throw std::logic_error("Not yet implemented: Search for a CPU by the primary key");
- break;
- case 'W': // Write data to a file
- throw std::logic_error("Not yet implemented: Write data to a file");
- break;
- case 'T': // Hashtable statistics
- // throw std::logic_error("Not yet implemented: Hashtable statistics");
- cout << "Load factor: " << cpuTable.getLoadFactor() << std::endl;
- cout << "Total number of collisions: " << cpuTable.getTotalCollisions() << std::endl;
- cout << "Longest collision path: " << cpuTable.getMaxCollisions() << std::endl;
- break;
- case 'P': // Print indented tree
- throw std::logic_error("Not yet implemented: Print indented tree");
- break;
- case 'Z': // Display names of team members
- printTeam();
- break;
- case 'Q': // Quit
- break;
- default:
- cout << "Invalid command. Press 'H' to view available commands.\n";
+void processInput(char command, HashTable &cpuTable, BinarySearchTree &cpuTree, Stack &undoStack) {
+ switch (command) {
+ case 'H':
+ printHelp();
+ break;
+ case 'I': // Insert a new record
+ handleInsert(cpuTable, cpuTree);
+ break;
+ case 'F': // File input: add data from a file
+ handleFileInput(cpuTable, cpuTree, undoStack);
+ break;
+ case 'D': // Delete one record
+ deleteCPU(cpuTable, cpuTree, undoStack);
+ break;
+ case 'U': // Undo delete
+ undoDelete(cpuTable, cpuTree, undoStack);
+ break;
+ case 'L': // List all CPUs sorted by primary key
+ throw std::logic_error("Not yet implemented: List all CPUs sorted by primary key");
+ break;
+ case 'S': // Search for a CPU by the primary key
+ throw std::logic_error("Not yet implemented: Search for a CPU by the primary key");
+ break;
+ case 'W': // Write data to a file
+ throw std::logic_error("Not yet implemented: Write data to a file");
+ break;
+ case 'T': // Hashtable statistics
+ cout << "Load factor: " << cpuTable.getLoadFactor() << std::endl;
+ cout << "Total number of collisions: " << cpuTable.getTotalCollisions() << std::endl;
+ cout << "Longest collision path: " << cpuTable.getMaxCollisions() << std::endl;
+ break;
+ case 'P': // Print indented tree
+ throw std::logic_error("Not yet implemented: Print indented tree");
+ break;
+ case 'Z': // Display names of team members
+ printTeam();
+ break;
+ case 'Q': // Quit
+ break;
+ default:
+ cout << "Invalid command. Press 'H' to view available commands.\n";
}
}
-void insertCPU(HashTable &hashTable, BinarySearchTree &tree)
-{
- string cpuId;
- int releaseYear, coreCount;
- string architecture;
- double baseClock;
- cout << "Enter CPU ID: ";
- cin >> cpuId;
- cout << "Enter release year: ";
- cin >> releaseYear;
- cout << "Enter core count: ";
- cin >> coreCount;
- cout << "Enter architecture: ";
- cin >> architecture;
- cout << "Enter base clock: ";
- cin >> baseClock;
- CPU cpu(cpuId, releaseYear, coreCount, architecture, baseClock);
-
- hashTable.insert(cpu, key_to_index);
- tree.insert(cpuId);
+void handleInsert(HashTable &hashTable, BinarySearchTree &tree) {
+ insertCPU(tree, hashTable);
}
-void deleteCPU(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack)
-{
+void handleFileInput(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack) {
+ string filename;
+ cout << "Enter filename: ";
+ cin >> filename;
+ int hashSize = findHashSize(filename);
+ hashTable = HashTable(hashSize);
+ tree = BinarySearchTree();
+ undoStack = Stack();
+
+ insertFile(filename, tree, hashTable);
+ cout << "Data from file \"" << filename << "\" added.\n";
+}
+
+void deleteCPU(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack) {
string cpuId;
cout << "Enter CPU ID to delete: ";
cin >> cpuId;
CPU cpu(cpuId, 0, 0, "", 0.0);
CPU cpuFound;
- while (!hashTable.search(cpuFound, cpu, key_to_index))
- {
+ while (hashTable.search(cpuFound, cpu, key_to_index) == -1) {
cout << "CPU ID not found. Enter a valid CPU ID: ";
cin >> cpuId;
cpu = CPU(cpuId, 0, 0, "", 0.0);
@@ -164,10 +153,8 @@ void deleteCPU(HashTable &hashTable, BinarySearchTree &tree, Stack<
cout << "CPU ID \"" << cpuId << "\" deleted.\n";
}
-void undoDelete(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack)
-{
- if (undoStack.isEmpty())
- {
+void undoDelete(HashTable &hashTable, BinarySearchTree &tree, Stack &undoStack) {
+ if (undoStack.isEmpty()) {
cout << "No deletions to undo.\n";
return;
}