SimpleLogin

A.Second Edition
This is second edition of assignment 3 of comp352 and it is a simple solution.
B.The problem
กก
C.The idea of program
D.The major functions
C.Further improvement
//the file name is assignment3.cpp
#include <iostream>
#include <fstream>
#include "BST.h"
#include "Elem.h"



using namespace std;

//char* inputFileName= "c:\\userids.dat";
char* inputFileName= "c:\\laura.dat";
char* outputFileName = "c:\\laura.dat";

class Login
{
private:
	BST<char*, Account, MyKEComp, MyEEComp> tree;
	
	int number;
	ifstream in;
	ofstream out;
	Account myAccount;
	void printNode(BinNode<Account>* ptr);
	void preOrder(BinNode<Account>* ptr);
	void inOrder(BinNode<Account>* ptr);
	void writeNode(BinNode<Account>* ptr);
	void displayLogin();
public:
	void choices();
	bool addUser();
	bool deleteUser();
	bool verifyUser();
	void print();
	void quit();
	void readFile(const char* fileName);

};

bool Login::verifyUser()
{
	Account a;
	char id[20];
	char password[20];
	cout <<"Enter your user ID: " << endl;
	cin >>  id;
	cout<<"\nand password:";
	cin>> password;
	if (tree.find(id, a))
	{
		if (strcmp(a.getPassword(), password)==0)
		{
			cout<<"valid user\n";
			return true;
		}
	}
	cout<<"invalid user!\n";

	return false;
}

void Login::printNode(BinNode<Account>* ptr)
{
	cout<<ptr->val().getID()<<"  "<<ptr->val().getPassword()<<endl;
}

void Login::print()
{
	BinNode<Account> *ptr;
	ptr = tree.getRoot();
	inOrder(ptr);//BinNode need to access the left and right
}


bool Login::addUser()
{
	Account a;	//because "find" uses call by reference

	char id[8];
	char password[7];
	cout <<"Enter your user ID: " << endl;
	cin >>  id;
	cout<<"\nand password:";
	cin>> password;

	if  (!(tree.find(id, a)))	//if not found, insert and return true
		{
			Account* newAccount = new Account;
			newAccount->setUserID(id);
			newAccount->setPassword(password);
			tree.insert( *newAccount);
			cout<<"id added successfully!\n";
			return true;
		}
	else
	{
		cout<<"id failed to add!\n";
		return false;
	}

}

bool Login::deleteUser()
{
	Account a;	//"find" return by reference

	char id[20];
	cout <<"Enter your user ID: " << endl;
	cin >>  id;

	if (tree.find(id, a )) //if this is true, remove should also return true
	{
		return (tree.remove(id, a));
	}	
	else
	{
		return false;
	}
}



void Login::writeNode(BinNode<Account>* ptr)
{
	char id[10], pwd[10];
	strcpy(id, ptr->val().getID());
	strcpy(pwd, ptr->val().getPassword());
	out<<id<<" "<<pwd<<"  ";
}
	

void Login::inOrder(BinNode<Account>* ptr)
{
	BinNode<Account>* l, *r;
	if (ptr!=NULL)
	{
		l = ptr->getLeft();
		r= ptr->getRight();
		inOrder(l);//BinNode need to access the left and right
		printNode(ptr);//you need to write the node into file
	//	delete ptr;
	//	ptr = NULL;
	
		inOrder(r);
	}
}



void Login::preOrder(BinNode<Account>* ptr)
{
	BinNode<Account>* l, *r;
	if (ptr!=NULL)
	{
		l = ptr->getLeft();
		r= ptr->getRight();

		writeNode(ptr);//you need to write the node into file
		//which is the in
	//	delete ptr;
	//	ptr = NULL;
		preOrder(l);//BinNode need to access the left and right
		preOrder(r);
	}
}

void Login::quit()
{
	
	out.open(outputFileName);
	preOrder(tree.getRoot());
}

void Login::displayLogin()
{
	cout << "(1) add new user" << endl;
	cout << "(2) delete user"  << endl;
	cout << "(3) verify user"  << endl;
	cout << "(4) print users"  << endl;
	cout << "(5) quit" << endl;

	cout << "Select the desired choice:" << endl;
}

void Login::choices()
{
	displayLogin();
	
	while (true)
	{
		cin >> number;

		switch (number)
		{
			case 1:
			addUser();
			break;

			case 2:
			deleteUser();
			break;

			case 3:
			verifyUser();
			break;

			case 4:
			print();
			break;

			case 5:
			quit();
			return;

		//	cout<< "Choose a number on the given list" << endl;		
		}
		displayLogin();		
	}

}


void Login::readFile(const char* fileName)
{
	Account* ptr;
	in.open(fileName);
	char id[10];
	char password[10];
	while (!in.eof())
	{
		in>>id>>password;
		ptr = new Account(id, password);

		//here you use id and password to create a account
		tree.insert(*ptr); //establish the tree
	}
	in.close();
}





int main()
{
	Login I;
	I.readFile(inputFileName);//a const
	I.choices();

	return 0;
}

//filename is elem.h
class Account
{
private:
	char userID[7+1];	//+1 for the NULL character
	char password[6+1];

public:
	Account() {;}	//default constructor
	Account(char* ID, char* Psword) {strcpy(userID, ID); strcpy(password, Psword);}

	const char* getID() const{return userID;}
	const char* getPassword() const{return password;}
	void setUserID(char* ID) {strncpy(userID, ID, 8);}
	void setPassword(char* newPsword) {strncpy(password, newPsword, 7);}

};


class MyKEComp
{
public:
	static bool lt(char* key, const Account& elem) {return strcmp(key, elem.getID())<0;}
	static bool eq(char* key, const Account& elem) {return strcmp(key, elem.getID())==0;}
	static bool gt(char* key, const Account& elem) {return strcmp(key, elem.getID())>0;}

};


class MyEEComp
{
public:
	static bool lt(const Account& elem1, const  Account& elem2)
		{return strcmp(elem1.getID(), elem2.getID())<0;}
	static bool eq(const Account& elem1, const  Account& elem2)
		{return strcmp(elem1.getID(), elem2.getID())==0;}
	static bool gt(const Account& elem1, const Account& elem2)
		{return strcmp(elem1.getID(), elem2.getID())>0;}
};

//filename BST.h
// This file includes all of the pieces of the BST implementation

#include "dictionary.h"

#include "binnode.h"

// Binary Search Tree implementation for the Dictionary ADT
template <class Key, class Elem, class KEComp, class EEComp>
class BST : public Dictionary<Key, Elem, KEComp, EEComp> {
private:
  BinNode<Elem>* root;   // Root of the BST
  int nodecount;         // Number of nodes in the BST
  // Private "helper" functions
  void clearhelp(BinNode<Elem>*);
  BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&);
  BinNode<Elem>* deletemin(BinNode<Elem>*, BinNode<Elem>*&);
  BinNode<Elem>* removehelp(BinNode<Elem>*, const Key&,
                            BinNode<Elem>*&);
  bool findhelp(BinNode<Elem>*, const Key&, Elem&) const;
  void printhelp(BinNode<Elem>*, int) const;
public:
	//add one function here
	BinNode<Elem>* getRoot(){ return root;}
	//add one function here
  BST() { root = NULL; nodecount = 0; }  // Constructor
  ~BST() { clearhelp(root); }            // Destructor
  void clear()
    { clearhelp(root); root = NULL; nodecount = 0; }
  bool insert(const Elem& e) {
    root = inserthelp(root, e);
    nodecount++;
    return true;
  }
  bool remove(const Key& K, Elem& e) {
    BinNode<Elem>* t = NULL;
    root = removehelp(root, K, t);
    if (t == NULL) return false;  // Nothing found
    e = t->val();
    nodecount--;
    delete t;
    return true;
  }
  bool removeAny(Elem& e) { // Delete min value
    if (root == NULL) return false; // Empty tree
    BinNode<Elem>* t;
    root = deletemin(root, t);
    e = t->val();
    delete t;
    nodecount--;
    return true;
  }
  bool find(const Key& K, Elem& e) const
    { return findhelp(root, K, e); }
  int size() { return nodecount; }
  void print() const {
    if (root == NULL) cout << "The BST is empty.\n";
    else printhelp(root, 0);
  }
};

template <class Key, class Elem, class KEComp, class EEComp>
void BST<Key, Elem, KEComp, EEComp>::
clearhelp(BinNode<Elem>* subroot) {
  if (subroot == NULL) return;
  clearhelp(subroot->left());
  clearhelp(subroot->right());
  delete subroot;
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
inserthelp(BinNode<Elem>* subroot, const Elem& val) {
  if (subroot == NULL)            // Empty tree: create node
    return (new BinNodePtr<Elem>(val, NULL, NULL));
  if (EEComp::lt(val, subroot->val())) // Insert on left
    subroot->setLeft(inserthelp(subroot->left(), val));
  else subroot->setRight(inserthelp(subroot->right(), val));
  return subroot;  // Return subtree with node inserted
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) {
  if (subroot->left() == NULL) { // Found min
    min = subroot;
    return subroot->right();
  }
  else {                         // Continue left
    subroot->setLeft(deletemin(subroot->left(), min));
    return subroot;
  }
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
removehelp(BinNode<Elem>* subroot, const Key& K,
           BinNode<Elem>*& t) {
  if (subroot == NULL) return NULL; // Val is not in tree
  else if (KEComp::lt(K, subroot->val())) // Check left
    subroot->setLeft(removehelp(subroot->left(), K, t));
  else if (KEComp::gt(K, subroot->val())) // Check right
    subroot->setRight(removehelp(subroot->right(), K, t));
  else {                           // Found it: remove it
    BinNode<Elem>* temp;
    t = subroot;
    if (subroot->left() == NULL)       // Only a right child
      subroot = subroot->right();      //  so point to right
    else if (subroot->right() == NULL) // Only a left child
      subroot = subroot->left();       //  so point to left
    else {                    // Both children are non-empty
      subroot->setRight(deletemin(subroot->right(), temp));
      Elem te = subroot->val();
      subroot->setVal(temp->val());
      temp->setVal(te);
      t = temp;
    }
  }
  return subroot;
}

template <class Key, class Elem, class KEComp, class EEComp>
bool BST<Key, Elem, KEComp, EEComp>:: findhelp(
      BinNode<Elem>* subroot, const Key& K, Elem& e) const {
  if (subroot == NULL) return false;         // Empty tree
  else if (KEComp::lt(K, subroot->val()))    // Check left
    return findhelp(subroot->left(), K, e);
  else if (KEComp::gt(K, subroot->val()))    // Check right
    return findhelp(subroot->right(), K, e);
  else { e = subroot->val();  return true; } // Found it
}

template <class Key, class Elem, class KEComp, class EEComp>
void BST<Key, Elem, KEComp, EEComp>::
printhelp(BinNode<Elem>* subroot, int level) const {
  if (subroot == NULL) return;          // Empty tree
  printhelp(subroot->left(), level+1);  // Do left subtree
  for (int i=0; i<level; i++)           // Indent to level
    cout << "  ";
  cout << subroot->val() << "\n";       // Print node value
  printhelp(subroot->right(), level+1); // Do right subtree
}
//filename Binnode.h
// Binary tree node abstract class
template <class Elem> class BinNode {
public:
  // Return the node's element
  virtual Elem& val() = 0;
  // Set the node's element
  virtual void setVal(const Elem&) = 0;
  // Return the node's left child
  virtual BinNode* left() const = 0;
  // Set the node's left child
  virtual void setLeft(BinNode*) = 0;
  // Return the node's right child
  virtual BinNode* right() const = 0;
  // Set the node's right child
  virtual void setRight(BinNode*) = 0;
  // Return true iff the node is a leaf
  virtual bool isLeaf() = 0;
  virtual BinNode<Elem>* getLeft()=0;
  virtual BinNode<Elem>* getRight()=0;
};

// Binary tree node class
template <class Elem>
class BinNodePtr : public BinNode<Elem> {
private:
  Elem it;                     // The node's value
  BinNodePtr* lc;              // Pointer to left child
  BinNodePtr* rc;              // Pointer to right child
public:
  // Two constructors -- with and without initial values
  BinNodePtr() { lc = rc = NULL; }
  BinNodePtr(Elem e, BinNodePtr* l =NULL,
                     BinNodePtr* r =NULL)
    { it = e; lc = l; rc = r; }
  ~BinNodePtr() {}             // Destructor
  Elem& val() { return it; }
  void setVal(const Elem& e) { it = e; }
  inline BinNode<Elem>* left() const { return lc; }
  void setLeft(BinNode<Elem>* b) { lc = (BinNodePtr*)b; }
  inline BinNode<Elem>* right() const { return rc; }
  void setRight(BinNode<Elem>* b) { rc = (BinNodePtr*)b; }
  bool isLeaf() { return (lc == NULL) && (rc == NULL); }

  //add two functions
  BinNode<Elem>* getLeft(){ return lc;}
  BinNode<Elem>* getRight(){ return rc;}

};
กก
//filename dictionary.h
// The Dictionary abstract class.  KEComp compares a key
// and an element. EEComp compares two elements.  
template <class Key, class Elem, class KEComp, class EEComp>
class  Dictionary {
public:
  // Reinitialize dictionary
  virtual void clear() = 0;
  // Insert an element.  Return true if insert is
  // successful, false otherwise.
  virtual bool insert(const Elem&) = 0;
  // Remove some element matching Key.  Return true if such
  // exists, false otherwise.  If multiple entries match
  // Key, an arbitrary one is removed.
  virtual bool remove(const Key&, Elem&) = 0;
  // Remove and return an arbitrary element from dictionary.
  // Return true if some element is found, false otherwise.
  virtual bool removeAny(Elem&) = 0;
  // Return a copy of some Elem matching Key.  Return true
  // if such exists, false otherwise.  If multiple elements
  // match Key, return an arbitrary one.
  virtual bool find(const Key&, Elem&) const = 0;
  // Return the number of elements in the dictionary.
  virtual int size() = 0;
};

                                 back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)