Population

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;
    };