From 31e276a06644582254919acd8229340eda9306b0 Mon Sep 17 00:00:00 2001 From: Iurii Tatishchev Date: Mon, 17 Jun 2024 15:35:06 -0700 Subject: [PATCH] add initial implementation of File I/O --- .idea/misc.xml | 3 + CMakeLists.txt | 2 + CPU.h | 17 ++--- fio.cpp | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ fio.h | 27 +++++++ main.cpp | 149 +++++++++++++++++------------------- 6 files changed, 310 insertions(+), 90 deletions(-) create mode 100644 fio.cpp create mode 100644 fio.h 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; }