/*#HA*/ /*#HB*/ /*#HC*/ /*#HD*/ /*#HE*/ // There's an error in this file. Can you use the TM to spot it
// and figure out the fix?
class MyStr{
public:
	MyStr(const char* p);	// Construct using a standard string
	MyStr();			// "default" (no arguement) constructor
	MyStr(const MyStr& orig);		// Copy constructor
	~MyStr();		// standard destructor to deal with heap

// Accessor functions - used to read object data without changing it
	int getLength() const;
	char getChar(int i) const;	// get char at location i
	void get(char* buff) const;	// Get the string & put it into user buff
	bool compare(const MyStr& other) const;	// true if equal
	
// Mutator functions - used to change string objects
	void setChar(int i, char c); // Change char at i to c
	void changeTo(const char* newString);	// Change the whole string
	
	/* Notice the change to pass by ref to improve efficiency */
	void changeTo(const MyStr& newString);	// Function overload

private:
	char* pStr;		// pointer into the heap where the actual string will be
	int len;	    // length of the string
};
/*#DA*/ // A class of users for network management
class User{
public:
	User(char* n, char* u, char* p);

// Accessors
	MyStr& getName();	// return reference
	int getAllocation();	// Disk space allowed
	MyStr getPassword();	// return value
	MyStr getUserName() ;
	bool confirm(const MyStr& uName, const MyStr& pass);
// Mutators
	bool setPassword(const MyStr& p1, const MyStr& p2);
	void setAllocation(int a);
private:
	MyStr name;		// Notice attributes that are OBJECTS!
	MyStr uName;
	MyStr passwrd;
	int alloctn;	// Memory allocation, in MBytes
};/*#HA*/

#include <iostream>
using namespace std;

int main(){
/*#DC*/	User mpbl("Michael", "mpbl", "bftplx");
	User theo("Theodore", "theo", "charl1eB");/*#HC*/
/*#DD*/	User mpblClone(mpbl);/*#HD*/
	mpbl.setAllocation(100);
/*#DE*/	//mpblClone.setPassword(MyStr("unlucky"), MyStr("unlucky"));
	MyStr noLuck("unlucky");
	mpblClone.setPassword(noLuck, noLuck);/*#HE*/
	
	return 0;
}

/***************************************************************
			Implementation of User 
			(normally in a separate file)
******************************************************************/

// Constructors in the form
//	 <Name>(<argument list>) : <initialization list> {
//		special code
//	}

/*#DB*/ User::User(char* n, char* u, char* p) : name(n),
	uName(u),passwrd(p){
	
}/*#HB*/

// Accessors
MyStr& User::getName() {return name;}	// Note returning reference
MyStr User::getUserName() {return uName;} // returning value
MyStr User::getPassword(){return passwrd;}
int User::getAllocation() {return alloctn;}	// Disk space allowed

// A little more complex accessor, used to confirm username, password pairs
bool User::confirm(const MyStr& un, const MyStr& pass) {
	return(uName.compare(un) && passwrd.compare(pass));
}

// Mutators
// Set password assumes two identical password strings
bool User::setPassword(const MyStr& new1, const MyStr& new2){
	if (new1.getLength()<6 || !new1.compare(new2)) return false;
	passwrd.changeTo(new1);	// change password
	return true;
}

void User::setAllocation(int a){
	alloctn = a;
}

/***************************************************************
			Implementation of MyStr 
			(normally in a separate file)
******************************************************************/

// These would normally be declared by including <cstring>
long strLen(const char* pStr);
void strCpy(char* dest,  const char* source);

MyStr::MyStr(){
	len = 0;
	if(pStr = new char[1])
		*pStr = '\0';
}

MyStr::MyStr(const char* p){
	len = strLen(p);
	if (pStr = new char[len+1])
	strCpy(pStr,p);
	else
		len = 0;
}

MyStr::MyStr(const MyStr& original){
	if (pStr = new char[original.len + 1]){ // Request heap space
		len = original.len;	// Success
		strCpy(pStr, original.pStr);	// Copy actual string
	}
	else len = 0;	// Consistent with constructor
}

MyStr::~MyStr(){
	delete []pStr;
}

int MyStr::getLength() const {return len;}
char MyStr::getChar(int i) const{
	if (i < 0 || i >= len)
		return '\0';
	return *(pStr + i);
}

bool MyStr::compare(const MyStr& other) const{
	if (len != other.len) return false;
	for (int i = 0; i < len; i++){
		if (*(pStr+i) != *(other.pStr+i))
			return false;	// exit as soon as a difference
	}
	return true; // everything the same if arrive here
}

void MyStr::get(char* buff)const {strCpy(buff,pStr);}

void MyStr::setChar(int i, char c){
	if (i >= 0 && i < len)
		*(pStr + i) = c;
}

void MyStr::changeTo(const char* newString){
	long l = strLen(newString); 
	if (l != len){	// if diff, re-allocate memory
		char* pTemp = new char[l+1];
		if (!pTemp) return; //punt!!
		delete [] pStr;	// Release old storage
		pStr = pTemp;	// hook-up to new
	}
	strCpy(pStr, newString);	
}

// Overloaded version of changeTo to allow the string to
// be changed to equal another MyStr object

void MyStr::changeTo(const MyStr& newString){
	changeTo(newString.pStr);  // Just convert to conventional call
}

void strCpy(char* dest, const char* source){
	while(*dest++ = *source++)
		;
}

long strLen(const char* pStr){
	long count = 0;
	while (*(pStr + count))
		count++;
	return count;
}/*#/H*/
 
