This project will implement a simple username/password lookup system using hash tables. You
should create the Hash Table from scratch. It may be helpful to create a separate class called
HashEntry, in which you can store a String username and String password. The Hash Table will
store these entries using the username as the key and the password as the value.
Create a hash code using the key to determine where the value is stored in the Hash Table. Here
is a sample hash method. Feel free to borrow it for your program:
privateint calcHashCode(String key) {
int mod = key.hashCode() % size;
return mod < 0 ? mod + size : mod;
}
You will be provided with a data file containing comma separated usernames and passwords.
Read the data in from the file and put it into the table. Once the table is populated, ask the user to
log into the system. If their username and password match the data in the table, alert the user that
access has been granted:
Login: trevor
User trevor not found.
Login: mary
Password: test
Authentication Failure
Login: mary
Password: contrary
Authentication Successful
Welcome mary
Provided Data File (containing comma separated usernames and passwords):
jack,broken.crown
jill,tumblin\'down
mary,contrary
bopeep,sheep!lost
Solution
//main.cpp
#include
#include
#include
#include
#include
#include \"HashTable.cpp\"
using namespace std;
/// the struct for the login and password
struct Account
{
/// variables
string login;
string password;
/// hash function
static unsigned int hash(const string& str)
{
unsigned int val = 0;
for (int i = 0; i < str.length(); ++i) {
val += str[i];
}
return val;
}
/// get key function
string getKey() const
{
return login;
}
};
int main()
{
string loginI;
string passwordI;
string temp;
/// open file
ifstream fin (\"password.dat\");
fin.clear();
/// make new account to read into
Account acct;
/// make the hash table
HashTable data (8);
/// read in
while (fin.good())
{
fin >> acct.login >> acct.password;
//cout << acct.login << \" \" << acct.password << endl;
data.insert(acct);
//data.showStructure();
}
data.showStructure();
/// read in
cout << \"Login: \";
cin >> loginI;
do
{
cout << \"Password: \";
cin >> passwordI;
/// check for login
if (data.retrieve(loginI, acct))
{
/// check if passwords are the same
if ((acct.password == passwordI))
{
/// same password, print success
cout << \"Authentication successful\" << endl;
}
else
{
/// different password, print failure
cout << \"Authentication failure\" << endl;
}
}
else
{
/// if the data login is not saved print failure
cout << \"Authentication failure\" << endl;
}
cout << \"Login: \";
cin >> loginI;
}
while(!cin.eof());
return 0;
}
=====================================================================
=====
#include
#include
#include
#include
#include \"HashTable.h\"
#include \"show10.cpp\"
using namespace std;
template
HashTable::HashTable(int initTableSize)
{
/// save size
tableSize = initTableSize;
/// initialize the array
dataTable = new BSTree[tableSize];
}
t.
This project will implement a simple usernamepassword lookup system.pdf
1. This project will implement a simple username/password lookup system using hash tables. You
should create the Hash Table from scratch. It may be helpful to create a separate class called
HashEntry, in which you can store a String username and String password. The Hash Table will
store these entries using the username as the key and the password as the value.
Create a hash code using the key to determine where the value is stored in the Hash Table. Here
is a sample hash method. Feel free to borrow it for your program:
privateint calcHashCode(String key) {
int mod = key.hashCode() % size;
return mod < 0 ? mod + size : mod;
}
You will be provided with a data file containing comma separated usernames and passwords.
Read the data in from the file and put it into the table. Once the table is populated, ask the user to
log into the system. If their username and password match the data in the table, alert the user that
access has been granted:
Login: trevor
User trevor not found.
Login: mary
Password: test
Authentication Failure
Login: mary
Password: contrary
Authentication Successful
Welcome mary
Provided Data File (containing comma separated usernames and passwords):
jack,broken.crown
jill,tumblin'down
mary,contrary
bopeep,sheep!lost
Solution
//main.cpp
#include
#include
#include
2. #include
#include
#include "HashTable.cpp"
using namespace std;
/// the struct for the login and password
struct Account
{
/// variables
string login;
string password;
/// hash function
static unsigned int hash(const string& str)
{
unsigned int val = 0;
for (int i = 0; i < str.length(); ++i) {
val += str[i];
}
return val;
}
/// get key function
string getKey() const
{
return login;
}
};
int main()
{
string loginI;
string passwordI;
string temp;
/// open file
ifstream fin ("password.dat");
fin.clear();
/// make new account to read into
Account acct;
/// make the hash table
3. HashTable data (8);
/// read in
while (fin.good())
{
fin >> acct.login >> acct.password;
//cout << acct.login << " " << acct.password << endl;
data.insert(acct);
//data.showStructure();
}
data.showStructure();
/// read in
cout << "Login: ";
cin >> loginI;
do
{
cout << "Password: ";
cin >> passwordI;
/// check for login
if (data.retrieve(loginI, acct))
{
/// check if passwords are the same
if ((acct.password == passwordI))
{
/// same password, print success
cout << "Authentication successful" << endl;
}
else
{
/// different password, print failure
cout << "Authentication failure" << endl;
}
}
else
{
/// if the data login is not saved print failure
cout << "Authentication failure" << endl;
4. }
cout << "Login: ";
cin >> loginI;
}
while(!cin.eof());
return 0;
}
=====================================================================
=====
#include
#include
#include
#include
#include "HashTable.h"
#include "show10.cpp"
using namespace std;
template
HashTable::HashTable(int initTableSize)
{
/// save size
tableSize = initTableSize;
/// initialize the array
dataTable = new BSTree[tableSize];
}
template
HashTable::HashTable(const HashTable& other)
{
/// copy size and create new table
tableSize = other.tableSize;
dataTable = new BSTree[tableSize];
*this = other;
}
template
5. HashTable& HashTable:: operator=(const HashTable& other)
{
/// if the same return
if (this = &other)
return *this;
/// clear
clear();
/// copy the size and create new table
tableSize = other.tableSize;
dataTable = new BSTree[tableSize];
/// go through tables and copy the trees
for (int i = 0; i < tableSize; ++i)
{
dataTable[i] = other.dataTable[i];
}
return *this;
}
template
HashTable::~HashTable()
{
clear();
delete[] dataTable;
}
template
void HashTable::insert(const DataType& newDataItem)
{
/// get hash
int location = newDataItem.hash(newDataItem.getKey()) % tableSize;
/// insert into tree
dataTable[location].insert(newDataItem);
}
template
bool HashTable:: remove(const KeyType& deleteKey)
{
6. /// get its location in the array
int location = DataType::hash(deleteKey) % tableSize;
/// check to delete it
return dataTable[location].remove(deleteKey);
}
template
bool HashTable:: retrieve(const KeyType& searchKey, DataType& returnItem) const
{
/// find location in the array
int location = DataType::hash(searchKey) % tableSize;
/// check if the item is there
return dataTable[location].retrieve(searchKey, returnItem);
}
template
void HashTable:: clear()
{
/// iterate through the complete hash table
for (int i = 0; i < tableSize; ++i)
{
dataTable[i].clear();
}
}
/**
* Not Used
*/
template
bool HashTable:: isEmpty() const
{
bool flag = true;
for (int i = 0; i < tableSize; ++i)
{
/// check to see if each tree insdie the table is empty
flag = dataTable[i].isEmpty();
9. *this = source;
}
template < typename DataType, class KeyType >
BSTree& BSTree::operator=(const BSTree& source)
{
if (this == &source)
return *this;
clear();
copyHelp(root, source.root);
return *this;
}
template < typename DataType, class KeyType >
void BSTree::copyHelp( BSTreeNode*& home, BSTreeNode* RHS )
{
/// Stopping condition, end of tree
if (RHS == NULL)
{
home = NULL;
return;
}
/// Create node
home = new BSTreeNode (RHS->dataItem, NULL, NULL);
/// Recall with the other parts of the tree
copyHelp(home->left, RHS->left);
copyHelp(home->right, RHS->right);
return;
}
template < typename DataType, class KeyType >
BSTree::~BSTree ()
{
clear();
}
template < typename DataType, class KeyType >
void BSTree::insert(const DataType& newDataItem)
10. {
insertHelper(root, newDataItem);
}
template < typename DataType, class KeyType >
void BSTree::insertHelper(BSTreeNode* & location, const DataType& newDataItem)
{
/// if reached location, create the new node
if (location==NULL)
location = new BSTreeNode(newDataItem, NULL, NULL);
/// if the current location is larger than data go left
if (location->dataItem.getKey() > newDataItem.getKey())
insertHelper(location->left, newDataItem);
/// if the current location is smaller than data, go right
if (location->dataItem.getKey() < newDataItem.getKey())
insertHelper(location->right, newDataItem);
}
template < typename DataType, class KeyType >
bool BSTree::retrieve(const KeyType& searchKey, DataType& searchDataItem) const
{
return retrieveHelper(root, searchKey, searchDataItem);
}
template < typename DataType, class KeyType >
bool BSTree::retrieveHelper(BSTreeNode* location, const KeyType& searchKey, DataType&
searchDataItem) const
{
/// if checked the complete tree, return false
if (location == NULL)
return false;
/// if found, return true
if (location->dataItem.getKey() == searchKey)
{
searchDataItem = location->dataItem;
return true;
}
/// if what were are looking for is smaller go left else go right
11. if (location->dataItem.getKey() > searchKey)
{
return retrieveHelper(location->left, searchKey, searchDataItem);
}
else
{
return retrieveHelper(location->right, searchKey, searchDataItem);
}
}
template < typename DataType, class KeyType >
bool BSTree:: remove ( const KeyType& deleteKey )
{
return removeHelper(root, deleteKey);
}
template < typename DataType, class KeyType >
bool BSTree:: removeHelper ( BSTreeNode* & location, const KeyType& deleteKey )
{
/// if at the end and not found, return false
if (location == NULL)
return false;
/// if found, delete
if (location->dataItem.getKey() == deleteKey)
{
/// if no children
if ((location->left == NULL) && (location->right == NULL))
{
delete location;
location = NULL;
return true;
}
/// if one child
/// left child, no right
if ((location->left != NULL) && (location->right == NULL))
{
12. BSTreeNode* temp;
temp = location;
location = location->left;
delete temp;
return true;
}
/// no left, right child
if ((location->left == NULL) && (location->right != NULL))
{
BSTreeNode* temp;
temp = location;
location = location->right;
delete temp;
return true;
}
/// if two children
if ((location->left != NULL) && (location->right != NULL))
{
BSTreeNode* temp;
temp = location;
/// get predecessor
temp = temp->left;
while (temp->right != NULL)
temp = temp->right;
/// overwrite the value to delete with the predecessor
location->dataItem = temp->dataItem;
/// delete the node with the value just written to the new location
return removeHelper(location->left, temp->dataItem.getKey());
}
}
/// keep searching
if (location->dataItem.getKey() > deleteKey)
return removeHelper(location->left, deleteKey);
else
return removeHelper(location->right, deleteKey);
}
13. template < typename DataType, class KeyType >
void BSTree:: writeKeys () const
{
writeKeysHelper(root);
cout << endl;
}
template < typename DataType, class KeyType >
void BSTree:: writeKeysHelper (BSTreeNode* location) const
{
if (!isEmpty())
{
/// go all the way to the left
if (location->left != NULL)
{
writeKeysHelper(location->left);
}
/// once all the way to the left print out the current
cout << location->dataItem.getKey() << " ";
/// check for the children to the right of the most left node
if (location->right != NULL)
{
writeKeysHelper(location->right);
}
}
}
template < typename DataType, class KeyType >
void BSTree:: clear()
{
clearHelper(root);
root = NULL;
}
template < typename DataType, class KeyType >
void BSTree:: clearHelper( BSTreeNode* & location )
{
if(!isEmpty())
14. {
/// if there is more to the left recall with child
if (location->left != NULL)
clearHelper(location->left);
/// if leftmost has a right child repeat process with the right child
if (location->right != NULL)
clearHelper(location->right);
/// deallocate
delete location;
}
}
template < typename DataType, class KeyType >
bool BSTree:: isEmpty () const
{
return (root == NULL);
}
template < typename DataType, class KeyType >
int BSTree:: getHeight () const
{
if (isEmpty())
return 0;
heightHelper(root);
}
template < typename DataType, class KeyType >
int BSTree:: heightHelper ( BSTreeNode* location) const
{
/// if we reached a null spot, return 0 since nothing is added
if (location == NULL)
return 0;
/// get the size of the left and right by recalling and going to the left and right
int leftTree = heightHelper(location->left);
int rightTree = heightHelper(location->right);
/// return which ever is larger plus one since the current node is part of the height
15. if (leftTree > rightTree)
return leftTree+1;
else
return rightTree+1;
}
template < typename DataType, class KeyType >
int BSTree:: getCount () const
{
return countHelper(root);
}
template < typename DataType, class KeyType >
int BSTree:: countHelper (BSTreeNode* location) const
{
if (location == NULL)
return 0;
else
return (countHelper(location->left)+countHelper(location->right)+1);
}
/**
* NOT USED
*/
template < typename DataType, class KeyType >
void BSTree:: writeLessThan ( const KeyType& searchKey ) const
{
}
==================================================================
//BSTree.h
#ifndef BSTREE_H
#define BSTREE_H
#include
#include
using namespace std;
template < typename DataType, class KeyType > // DataType : tree data item
16. class BSTree // KeyType : key field
{
public:
// Constructor
BSTree (); // Default constructor
BSTree ( const BSTree& other ); // Copy constructor
BSTree& operator= ( const BSTree& other );
// Overloaded assignment operator
// Destructor
~BSTree ();
// Binary search tree manipulation operations
void insert ( const DataType& newDataItem ); // Insert data item
bool retrieve ( const KeyType& searchKey, DataType& searchDataItem ) const;
// Retrieve data item
bool remove ( const KeyType& deleteKey ); // Remove data item
void writeKeys () const; // Output keys
void clear (); // Clear tree
// Binary search tree status operations
bool isEmpty () const; // Tree is empty
// !! isFull() has been retired. Not very useful in a linked structure.
// Output the tree structure -- used in testing/debugging
void showStructure () const;
// In-lab operations
int getHeight () const; // Height of tree
int getCount () const; // Number of nodes in tree
void writeLessThan ( const KeyType& searchKey ) const; // Output keys < searchKey
protected:
class BSTreeNode // Inner class: facilitator for the BSTree class
{
public:
// Constructor
BSTreeNode ( const DataType &nodeDataItem, BSTreeNode *leftPtr, BSTreeNode *rightPtr );
// Data members
DataType dataItem; // Binary search tree data item
BSTreeNode *left, // Pointer to the left child