add initial implementation of File I/O

This commit is contained in:
Iurii Tatishchev 2024-06-17 15:35:06 -07:00
parent 30454d624c
commit 31e276a066
Signed by: CaZzzer
GPG Key ID: E0EBF441EA424369
6 changed files with 310 additions and 90 deletions

3
.idea/misc.xml generated
View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@ -18,4 +18,6 @@ add_executable(08_team_project main.cpp
Stack.h
StackNode.cpp
StackNode.h
fio.h
fio.cpp
)

17
CPU.h
View File

@ -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

202
fio.cpp Normal file
View File

@ -0,0 +1,202 @@
#include <sstream>
#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<string> &bst, HashTable<CPU> &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<string> &bst, HashTable<CPU> &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;
}

27
fio.h Normal file
View File

@ -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 <string>
#include <fstream>
#include <iostream>
#include "CPU.h"
#include "HashTable.h"
#include "BinarySearchTree.h"
using std::string;
int findHashSize(const string& filename);
void insertFile(const string& filename, BinarySearchTree<string> &bst, HashTable<CPU> &hash);
void insertCPU(BinarySearchTree<string> &bst, HashTable<CPU> &hash);
#endif //INC_08_TEAM_PROJECT_FIO_H

149
main.cpp
View File

@ -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<CPU> &table, BinarySearchTree<string> &tree, Stack<CPU> &stack);
int main()
{
int main() {
// Print help table for commands
printHelp();
@ -47,18 +47,15 @@ int main()
Stack<CPU> 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<CPU> &hashTable, BinarySearchTree<string> &tree);
void handleInsert(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree);
void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack);
void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack);
void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack);
void processInput(char command, HashTable<CPU> &cpuTable, BinarySearchTree<string> &cpuTree, Stack<CPU> &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<CPU> &cpuTable, BinarySearchTree<string> &cpuTree, Stack<CPU> &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<CPU> &hashTable, BinarySearchTree<string> &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<CPU> &hashTable, BinarySearchTree<string> &tree) {
insertCPU(tree, hashTable);
}
void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack)
{
void handleFileInput(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack) {
string filename;
cout << "Enter filename: ";
cin >> filename;
int hashSize = findHashSize(filename);
hashTable = HashTable<CPU>(hashSize);
tree = BinarySearchTree<string>();
undoStack = Stack<CPU>();
insertFile(filename, tree, hashTable);
cout << "Data from file \"" << filename << "\" added.\n";
}
void deleteCPU(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &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<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<
cout << "CPU ID \"" << cpuId << "\" deleted.\n";
}
void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack)
{
if (undoStack.isEmpty())
{
void undoDelete(HashTable<CPU> &hashTable, BinarySearchTree<string> &tree, Stack<CPU> &undoStack) {
if (undoStack.isEmpty()) {
cout << "No deletions to undo.\n";
return;
}