【第十二章】C++ Primer plus 的編程練習題

// cow.h -- class Cow definition
#ifndef __COW_H__
#define __COW_H__

class Cow 
{
private:
	char name[20];
	char * hobby;
	double weight;
public:
	Cow();
	Cow(const char * nm, const char * ho, double wt);
	Cow(const Cow & c);
	~Cow();
	Cow & operator=(const Cow & c);
	void showCow() const;   // display all cow data
};

#endif /* __COW_H__ */

// cow.cpp -- class Cow methods definition
#include <iostream>
#include "cow.h"
#include <cstring>

using namespace std;

// constructor methods
Cow::Cow()
{
	//strset(name, 0x00); strset函數是從name開始直到
	        // 內存空間爲0才停止設置爲0,所以會可能設置超過長度20
	strnset(name, 0x00, 20);
	hobby = NULL;
	weight = 0.0;
	cout << "< " << name << " default create >\n";
}

Cow::Cow(const char * nm, const char * ho, double wt)
{
	strcpy(name, nm);	
	int len = strlen(ho);
	hobby = new char[len + 1];
	strcpy(hobby, ho);
	hobby[len] = '\0';
	weight = wt;
	cout << "< " << name << " custom create >\n";
}

Cow::Cow(const Cow & c)
{
	strcpy(name, c.name);
	int len = strlen(c.hobby);
	hobby = new char[len + 1];
	strcpy(hobby, c.hobby);
	hobby[len] = '\0';
	weight = c.weight;
	//cout << name << " copy create\n";
}

// destructor function
Cow::~Cow()
{
	cout << "< " << name << " delete >\n";
	delete [] hobby;
}

// overloade operator
Cow & Cow::operator=(const Cow & c)
{
	cout << "< " << " = operator be call >\n";
	if (this == &c)
		return *this;
	strcpy(name, c.name);

	int len = strlen(c.hobby);
	delete[] hobby;
	hobby = new char[len + 1];
	strcpy(hobby, c.hobby);
	hobby[len] = '\0';
	weight = c.weight;
	
	return *this;
}

// display class data message
void Cow::showCow() const
{
	using std::cout;
	using std::endl;

	cout << "name: " << name
		 << ", hobby: " << hobby
		 << ", weight: " << weight << endl;
}

/***********************************
	2017年11月24日 18:41:05
	Athor:xiyuan255
	Course:C++
	Contain:usecow.cpp
			cow.h
			cow.cpp
	Reference: C++ Primer plus
	說明:C++ Primer plus第十二章的練習題 第一題
	     【 參考 P478 】
*************************************/
// usecow.cpp -- using class Cow methods
#include <iostream>
#include "cow.h"

int main()
{
	using namespace std;
	{
		Cow stduent1( "xiaoming", "kanshu", 45.6 ); 
		// call Cow(const char * nm, const char * ho, double wt) function
		Cow stduent2( "zhangsan", "xuezi", 41.2 );
		stduent1.showCow();
		stduent2.showCow();
		
		Cow stduent3 = stduent1;
		// call Cow(const Cow & c) function 
		stduent3.showCow();

		Cow stduent4 = Cow(); // call Cow() function
		stduent4 = stduent2; // call Cow & operator=(const Cow & c) function
		stduent4.showCow();

	}
	cout << "Done.\n";

	return 0;
}

/**
輸出結果:
	< xiaoming custom create >
	< zhangsan custom create >
	name: xiaoming, hobby: kanshu, weight: 45.6
	name: zhangsan, hobby: xuezi, weight: 41.2
	name: xiaoming, hobby: kanshu, weight: 45.6
	<  default create >
	<  = operator be call >
	name: zhangsan, hobby: xuezi, weight: 41.2
	< zhangsan delete >
	< xiaoming delete >
	< zhangsan delete >
	< xiaoming delete >
	Done.
*/

#pragma once

// string2.h -- fixed and augmented string class definition
#ifndef __STRING2_H__
#define __STRING2_H__
#include <iostream>
using std::ostream;
using std::istream;

class String
{
private:
	char * str;              // pointer to string
	int len;                 // length of string
	static int num_strings;  // number of objects
	static const int CINLIM = 80;  // cin input limit
public:
	// constructors and other methods
	String(const char * s);   // constructor 
	String();                 // default constructor (默認構造函數)
	String(const String &);   // copy constructor (複製構造函數)
	~String();                // destructor (析構函數)
	int length() const { return len; }
	// overloaded operator methods
	String & operator=(const String &);
	String & operator=(const char *);
	char & operator[](int i);
	const char & operator[](int i) const;
	String operator+(const String & st);
	void stringup();
	void stringlow();
	int has(const char ch);
	// overloaded operator friends
	friend bool operator<(const String &st1, const String &st2);
	friend bool operator>(const String &st1, const String &st2);
	friend bool operator==(const String &st1, const String &st2);
	friend ostream & operator<<(ostream &os, const String &st);
	friend istream & operator >> (istream &os, String &st);
	friend String operator+(const char * s, const String & st);
	// static function 
	static int HowMany();
};

#endif /* __STRING2_H__ */


// string2.cpp -- String class methods
#include <cstring>         // string.h for some
#include "string2.h"       // include <iostream>
using std::cin;
using std::cout;

// initializing static class member
int String::num_strings = 0;

// static method
int String::HowMany()
{
	return num_strings;
}

// calss methods
String::String(const char * s)   // constructor String from C string 
{
	len = std::strlen(s);        // set size
	str = new char[len + 1];     // allot storage
	std::strcpy(str, s);         // initialize pointer
	str[len] = '\0';
	num_strings++;
	//cout << "< custom constructor > ";
	//cout << num_strings << ": \"" << str
		//<< "\" object created\n"; // For Your Information
}

String::String()                 // default constructor 
{
	len = 0;
	str = new char[1];
	str[0] = '\0';               // default string
	num_strings++;
	//cout << "< default constructor > ";
	//cout << num_strings << ": \"" << str
		//<< "\" object created\n"; // For Your Information
}

String::String(const String & st)
{
	num_strings++;               // handle static member update
	len = st.len;                // same length
	str = new char[len + 1];     // allot space
	std::strcpy(str, st.str);    // copy string to new location 
	str[len] = '\0';
	//cout << "< copy constructor > ";
	//cout << num_strings << ": \"" << str
		//<< "\" object created\n"; // For Your Information
}

String::~String()                // necessary destructor
{
	//cout << "\"" << str << "\" object deleted, ";  // FYI
	--num_strings;               // required
	//cout << num_strings << " left\n";  // FYI  // left: 剩下
	delete[] str;               // required
}

// overloaded operator methods
// assign a String to a String
String & String::operator=(const String & st)
{
	//cout << "< operator=(const String & st) >\n";
	if (this == &st)
		return *this;
	delete[] str;
	len = st.len;
	str = new char[len + 1];
	std::strcpy(str, st.str);
	str[len] = '\0';
	return *this;
}

// assign a C string to a String
String & String::operator=(const char * s)
{
	//cout << "< operator=(const char * s) >\n";
	delete[] str;
	len = std::strlen(s);
	str = new char[len + 1];
	std::strcpy(str, s);
	str[len] = '\0';
	return *this;
}

// read-write char access for non-const String
char & String::operator[](int i)
{
	return str[i];
}

// read-only char access for const String
const char & String::operator[](int i) const
{
	return str[i];
}

String String::operator+(const String & st)
{
	String temp;
	temp.len = len + st.length();
	temp.str = new char[temp.len + 1];
	strcpy(temp.str, str);
	strcpy(&(temp.str[len]), st.str);
	temp.str[temp.len] = '\0';
	return temp; // 將temp對象的值拷貝到返回值所佔的空間,會調用複製構造函數
}

void String::stringup()
{
	for (int i = 0; i < len; i++) {
		str[i] = toupper(str[i]);
	}
}

void String::stringlow()
{
	for (int i = 0; i < len; i++) {
		str[i] = tolower(str[i]);
	}
}

int String::has(const char ch)
{
	int count = 0;
	for (int i = 0; i < len; i++) {
		if (str[i] == ch)
			count++;
	}
	return count;
}

// overloaded operator friends
bool operator<(const String &st1, const String &st2)
{
	return (std::strcmp(st1.str, st2.str) < 0);
}

bool operator>(const String &st1, const String &st2)
{
	return (st2 < st1);
}

bool operator==(const String &st1, const String &st2)
{
	return (std::strcmp(st1.str, st2.str) == 0);
}

// simple String output
ostream & operator<<(ostream &os, const String &st)
{
	os << st.str;
	return os;
}

// quick and dirty String input 
istream & operator >> (istream & is, String & st)
{
	char temp[String::CINLIM];
	is.get(temp, String::CINLIM);
	if (is)
		st = temp; // 調用st.operator=(const char *)成員函數
	while (is && is.get() != '\n')
		continue;
	return is;
}

String operator+(const char * s, const String & st)
{
	//cout << "< operator+(const char * s, const String & st) >\n";
	String temp;  // 調用默認構造函數
	temp.len = strlen(s) + st.length();
	temp.str = new char[temp.len + 1];
	strcpy(temp.str, s);
	strcpy(&(temp.str[strlen(s)]), st.str);
	temp.str[temp.len] = '\0';
	return temp; // return temp,說明要將對象temp複製到函數返回值String所佔的內存空間,
	       // 因爲是按值複製的,所以會調用複製構造函數;由返回值String所佔的內存空間
	       // 的對象調用複製構造函數,即 返回值對象.String(const String & st) 將對象
	       // temp的值複製給返回對象。
}

/***********************************
	2017年11月24日 19:47:22
	Athor:xiyuan255
	Course:C++
	Contain:pe12_2.cpp
			string2.h
			string2.cpp
	Reference: C++ Primer plus
	說明:C++ Primer plus第十二章的練習題 第二題
	【 參考 P478 】
*************************************/
// pe12_2.cpp  
#include <iostream>
using namespace std;
#include "string2.h"

int main()
{
	String s1(" and I am a C++ student.");
	String s2 = "Please enter your name: ";
	String s3;
	cout << s2;              // overloaded << operator
	cin >> s3;               // overloaded >> operator
	s2 = "My name is " + s3; // overloaded =, + operator 
	// "My name is " + s3 調用operator+(const char * s, const String & st)
	// 該函數執行完畢後會自動釋放函數內部創建的臨時對象
	// 然後再執行s2 = 返回值對象(返回值對象的值等於"My name is " + s3所創建的對象)
	// s2 = 返回值對象調用的是operator=(const String & st),即st對象就是上述通過
	// operator+(const char * s, const String & st)函數返回的返回值對象;當執行該函數
	// 執行完畢後,會釋放st對象,因爲st是臨時對象;所以這個語句會創建兩個對象,並釋放
	// 兩次內容值相同的對象;(一個對象是temp,一個對象是返回值對象)
	cout << s2 << ".\n";

	s2 = s2 + s1; // s2 + s1調用函數s2.operator+(s1)返回一個返回對象,再調用s2.operator=(返回對象)
	     // 將返回對象的值複製到s2中,再釋放返回對象(返回對象是臨時對象)
	s2.stringup();           // convert string to uppercase
	cout << "The string\n" << s2 << "\ncontains " << s2.has('A')
		<< " 'A' characters in it.\n";
	//cout << endl;


	/* 編譯器可能用兩種方式:(1)調用s1.operator=("read")這種方式沒有創建對象,自然也不需要釋放 
	                        (2)調用構造函數String(const char *)創建一個臨時對象,然後再調用複製
							   構造函數賦值,即s1.String(const String &),最後是否臨時對象 
       具體編譯器會選擇何種方式,有不同的編譯器決定 */
	s1 = "red";              // String(const char *), 
							 // then String & operator=(const String &)
	String rgb[3] = { String(s1), String("green"), String("blue") };
	cout << "Enter the name of a primary color for mixing light: ";
	String ans;
	bool success = false;
	while (cin >> ans) {
		ans.stringlow();        // converts string to lowercase
		for (int i = 0; i < 3; i++) {
			if (ans == rgb[i]) { // overloaded == operator
				cout << "That's right!\n";
				success = true;
				break;
			}
		}
		if (success)
			break;
		else
			cout << "Try again!\n";
	}
	cout << "Bye\n";

	return 0;
}

/**
輸出結果:
	Please enter your name: Fretta Farbo
	My name is Fretta Farbo.
	The string
	MY NAME IS FRETTA FARBO AND I AM A C++ STUDENT.
	contains 6 'A' characters in it.
	Enter the name of a primary color for mixing light: yellow
	Try again!
	BLUE
	That's right!
	Bye
*/

#pragma once
// stock50.h -- augmented version
#ifndef __STOCK50_H__
#define __STOCK50_H__
#include <iostream>

class Stock
{
private:
	char * company;
	int shares;
	double share_val;
	double total_val;
	void set_tot() { total_val = shares * share_val; }
public:
	Stock();         // default constructor
	Stock(const Stock & st);
	Stock(const char * str, long n = 0, double pr = 0.0);
	~Stock();      
	Stock & operator=(const Stock & st);
	Stock & operator=(const char * str);

	void buy(long num, double price);
	void sell(long num, double price);
	void update(double price);
	const Stock & topVal(const Stock & s) const;
 // friend function 
	friend std::ostream & operator<<(std::ostream & os, const Stock & st);
};

#endif /* __STOCK50_H__ */

// stock50.cpp -- augmented version
#include <iostream>
#include "stock50.h"

// constructors
Stock::Stock()
{
	company = NULL;
	shares = 0;
	share_val = total_val = 0.0;
}

Stock::Stock(const char * str, long n, double pr)
{
	int len = strlen(str);
	company = new char[len + 1];
	strcpy(company, str);
	company[len] = '\0';

	if (n < 0) {
		std::cout << "Number of shares can't be negative; "
			      << company << " shares set to 0.\n";
		shares = 0;
	} else 
		shares = n;
	share_val = pr;
	set_tot();
}

Stock::Stock(const Stock & st)
{
	int len = strlen(st.company);
	company = new char[len + 1];
	strcpy(company, st.company);
	company[len] = '\0';

    shares = st.shares;
	share_val = st.share_val;
	set_tot();
}

// class destructor
Stock::~Stock()     // quiet class destructor
{
	delete[] company;
}

Stock & Stock::operator=(const Stock & st)
{
	if (this == &st)
		return *this;

	delete[] company;
	int len = strlen(st.company);
	company = new char[len + 1];
	strcpy(company, st.company);
	company[len] = '\0';

	shares = st.shares;
	share_val = st.share_val;
	set_tot();

	return *this;
}

Stock & Stock::operator=(const char * str)
{
	delete[] company;
	int len = strlen(str);
	company = new char[len + 1];
	strcpy(company, str);
	company[len] = '\0';
	
	return *this;
}

// other methods
void Stock::buy(long num, double price)
{
	if (num < 0) {
		std::cout << "Number of shares purchased can't be negative. "
			      << "Transaction set aborted.\n";
		shares = 0;
	} else {
		shares += num;
		share_val = price;
		set_tot();
	}
}

void Stock::sell(long num, double price)
{
	using std::cout;
	if (num < 0) {
		cout << "Number of shares sold can't be negative. "
			 << "Transaction set aborted.\n";
		shares = 0;
	}
	else if (num > shares) {
		cout << "You can't sell more than you have. "
			 << "Transaction set aborted.\n";
	} else {
		shares -= num;
		share_val = price;
		set_tot();
	}
}

void Stock::update(double price)
{
	share_val = price;
	set_tot();
}

const Stock & Stock::topVal(const Stock & s) const
{
	if (s.total_val > total_val)
		return s;
	else
		return *this;
}

std::ostream & operator<<(std::ostream & os, const Stock & st)
{
	using std::ios_base;
	// set format to #.###
	ios_base::fmtflags orig =
		os.setf(ios_base::fixed, ios_base::floatfield);
	std::streamsize prec = os.precision(3);

	os << "Company: " << st.company
		<< " Shares: " << st.shares << '\n';
	os << " Share price: $" << st.share_val;
	// set format to #.##
	os.precision(2);
	os << " Total Worth: $" << st.total_val << '\n';

	// restore original format
	os.setf(orig, ios_base::floatfield);
	os.precision(prec);

	return os;
}



/***********************************
	2017年11月24日 20:57:04
	Athor:xiyuan255
	Course:C++
	Contain:usestock50.cpp
			stock50.h
			stock50.cpp
	Reference: C++ Primer plus
	說明:C++ Primer plus第十二章的練習題 第三題
	【 參考 P478 】
*************************************/
// usestock50.cpp -- using the Stock class
// compile with stock50.cpp
#include <iostream>
#include "stock50.h"

const int STKS = 4;

int main()
{
// create an array of initialized objects
	Stock stocks[STKS] = {
		Stock("NanoSmart", 12, 20.0),
		Stock("Boffo Objects", 200, 2.0),
		Stock("Monolithic Obelisks", 130, 3.25),
		Stock("Fleep Enterprises", 60, 6.5),
	};
	std::cout << "Stock holdings:\n";
	int st;
	for (st = 0; st < STKS; st++)
		std::cout << stocks[st];
// set pointer to first element
	const Stock * top = &stocks[0];
	for (st = 1; st < STKS; st++)
		top = &top->topVal(stocks[st]);
// now top pointer to the most valuable holding
	std::cout << "\nMost valuable holding:\n";
	std::cout << *top;

	return 0;
}

/**
輸出結果:
	Stock holdings:
	Company: NanoSmart Shares: 12
	Share price: $20.000 Total Worth: $240.00
	Company: Boffo Objects Shares: 200
	Share price: $2.000 Total Worth: $400.00
	Company: Monolithic Obelisks Shares: 130
	Share price: $3.250 Total Worth: $422.50
	Company: Fleep Enterprises Shares: 60
	Share price: $6.500 Total Worth: $390.00

	Most valuable holding:
	Company: Monolithic Obelisks Shares: 130
	Share price: $3.250 Total Worth: $422.50
*/

#pragma once
// stack30.h -- class declaration for the stack ADT
#ifndef __STACK30_H__
#define __STACK30_H__
#include <iostream>

typedef unsigned long Item;

class Stack
{
private:
	enum { MAX = 10 };    // constant specific to class
	Item * pitems;        // holds stack items
	int size;             // number of elements in stack
	int top;              // index for top stack item
public:
	Stack(int n = MAX);   // create atack with n element
	Stack(const Stack & st);
	~Stack();
	bool isEmpty() const;
	bool isFull() const;
	// push() return false if stack already is full, true otherwise
	bool push(const Item & item);  // add item to stack
    // pop() return false if stack already is empty, true otherwise
	bool pop(Item & item);   // pop top into item
	Stack & operator=(const Stack & st);

	friend std::ostream & operator<<(std::ostream & os, const Stack & st);
};

#endif /* __STACK30_H__ */

// stack30.cpp -- class Stack methods for definition
#include "stack30.h"


// default constructor
Stack::Stack(int n)
{
	//std::cout << "< default constructor >\n";
	pitems = new Item[n];
	size = n;
	top = 0;
}

// copy constructor
Stack::Stack(const Stack & st)
{
	//std::cout << "< copy constructor >\n";
	pitems = new Item[st.size];
	for (int i = 0; i < st.top; i++)
		pitems[i] = st.pitems[i];
	size = st.size;
	top = st.top;
}

// destructor
Stack::~Stack()
{
	delete[] pitems;
}

// other methods
bool Stack::isEmpty() const
{
	return 0 == top;
}

bool Stack::isFull() const
{
	return size == top;
}

bool Stack::push(const Item & item)
{
	if (isFull())
		return false;
	pitems[top++] = item;
	return true;
}

bool Stack::pop(Item & item)
{
	if (isEmpty())
		return false;
	item = pitems[--top];
	return true;
}

Stack & Stack::operator=(const Stack & st)
{
	if (this == &st)
		return *this;
	delete[] pitems;
	pitems = new Item[st.size]; 
	for (int i = 0; i < st.top; i++)
		pitems[i] = st.pitems[i];
	top = st.top;
	size = st.size;
}

std::ostream & operator<<(std::ostream & os, const Stack & st)
{
	os << "stack content:< ";
	for (int i = 0; i < st.top; i++)
		os << st.pitems[i] << " ";
	os << ">size = " << st.size;

	return os;
}

/***********************************
	2017年11月24日 22:03:49
	Athor:xiyuan255
	Course:C++
	Contain:usestack30.cpp
			stack30.h
			stack30.cpp
	Reference: C++ Primer plus
	說明:C++ Primer plus第十二章的練習題 第四題
	【 參考 P478 】
*************************************/
// usestack30.cpp -- using class Stack methods 
// compile with stack30.cpp
#include <iostream>
#include "stack30.h"

int main()
{
	using std::cout;
	using std::endl;

	Stack obj1; // call default constructor
	cout << "obj1 is empty ?(1: Yes, 0: No)" << obj1.isEmpty() << endl;
	for (int i = 1; i < 9; i++)
		obj1.push(i);
	cout << obj1 << endl;
	cout << "obj1 is empty ?(1: Yes, 0: No)" << obj1.isEmpty() << endl;
	obj1.push(1200);
	obj1.push(1300);
	cout << "obj1 is full ?(1: Yes, 0: No)" << obj1.isFull() << endl;
	obj1.push(1400);
	cout << obj1 << endl;

	Stack obj2 = obj1; // call copy constructor 
	cout << obj2 << endl;
	Item temp;
	obj2.pop(temp);
	obj2.pop(temp);
	cout << "pop two element afther: ";
	cout << obj2 << endl;

	Stack obj3(15); // call default constructor
	for (int i = 2; i < 20; i+=2)
		obj3.push(i);
	cout << obj3 << endl;
	obj3 = obj1;   // call obj3.operator=(obj1);
	cout << obj3 << endl;

	return 0;
}

/**
輸出結果:
	obj1 is empty ?(1: Yes, 0: No)1
	stack content:< 1 2 3 4 5 6 7 8 >size = 10
	obj1 is empty ?(1: Yes, 0: No)0
	obj1 is full ?(1: Yes, 0: No)1
	stack content:< 1 2 3 4 5 6 7 8 1200 1300 >size = 10
	stack content:< 1 2 3 4 5 6 7 8 1200 1300 >size = 10
	pop two element afther: stack content:< 1 2 3 4 5 6 7 8 >size = 10
	stack content:< 2 4 6 8 10 12 14 16 18 >size = 15
	stack content:< 1 2 3 4 5 6 7 8 1200 1300 >size = 10
*/

#pragma once
// queue.h -- interface for a queue
#ifndef __QUEUE_H__
#define __QUEUE_H__
// This queue will contain Customer items
class Customer
{
private:
	long arrive;        // arrive time for customer // 客戶到達的時間
	int processtime;    // processing time for customer // 客戶處理的時間
public:
	Customer() { arrive = processtime = 0; }
	void set(long when);
	long when() const { return arrive; }
	int ptime() const { return processtime; }
};

typedef Customer Item;

class Queue
{
private:
	// calss scope definitions 
	// Node is a nested structure definition local to this c
	struct Node { Item item; struct Node * pNext; };
	enum { Q_SIZE = 10 };
	// private class members
	Node * front;       // pointer to front of Queue
	Node * rear;        // pointer to rear of Queue
	int items;          // current number of items in Queue
	const int qsize;    // maximum number of items in Queue
						// preemptive definitions to prevent public copying 
	Queue(const Queue & q) : qsize(0) { }
	Queue & operator=(const Queue & q) { return *this; }
public:
	Queue(int qs = Q_SIZE); // create queue with a qs limit 
	~Queue();
	bool isEmpty() const;
	bool isFull() const;
	int queueCount() const;
	bool enQueue(const Item & item);  // add item to rear
	bool deQueue(Item & item);        // remove item from front
};

#endif /* __QUEUE_H__ */

// queue.cpp -- Queue and Customer methods
#include "queue.h"
#include <cstdlib>    // (or stdlib.h) for rand()

// Queue methods
Queue::Queue(int qs) : qsize(qs)
{
	front = rear = NULL;   // or nullptr
	items = 0;
}

Queue::~Queue()
{
	Node * temp;
	while (front != NULL) {   // while queue is not yet empty
		temp = front;         // save address of front item
		front = front->pNext; // reset pointer to next item
		delete temp;          // delete former front
	}
}

bool Queue::isEmpty() const
{
	return 0 == items;
}

bool Queue::isFull() const
{
	return items == qsize;
}

int Queue::queueCount() const
{
	return items;
}


// add item to queue
bool Queue::enQueue(const Item & item)
{
	if (isFull())
		return false;
	Node * add = new Node;  // create node
							// on failure, new throws std::bad_alloc exception
	add->item = item;       // set node item
	add->pNext = NULL;      // or nullptr 
	items++;
	if (NULL == front)      // if queue is empty
		front = add;        // place item at front
	else
		rear->pNext = add;  // else place at rear
	rear = add;             // have rear point to new node

	return true;
}

// Place front item into item veriable and remove from queue
bool Queue::deQueue(Item & item)
{
	if (NULL == front)
		return false;
	item = front->item;     // set item to first in queue
	items--;
	Node * temp = front;    // save location of first item
	front = front->pNext;   // reset front to next item
	delete temp;
	if (0 == items)
		rear = NULL;

	return true;
}

// time set to a random value in the range 1 - 3
void Customer::set(long when)
{
	processtime = std::rand() % 3 + 1;
	arrive = when;
}


/***********************************
	2017年11月25日 14:35:30
	Athor:xiyuan255
	Course:C++
	Contain:bank2.cpp
			queue.h
			queue.cpp
	Reference: C++ Primer plus
	說明:C++ Primer plus第十二章的練習題 第五題
	【 參考 P478 】
*************************************/
// bank2.cpp -- using the Queue interface
// compile with queue.cpp
#include <iostream>
#include <cstdlib>   // for rand() and srand()
#include <ctime>     // for time()
#include "queue.h" 

const int MIN_PER_HR = 60;

bool newCustomer(double x);  // is there a new customer?

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	using std::ios_base;
	// setting things up
	std::srand(std::time(0));  // random initializing of rand()

	cout << "Case Study: Bank of Heather Automatic Teller\n";
	cout << "Enter maximum size of queue: ";
	int qs;
	cin >> qs;
	Queue line(qs);   // line queue holds up to qs people

	cout << "Enter the number of simulation hours: ";
	int hours;        // hours of simulation
	cin >> hours;     // 模擬多長時間(單位:小時)
	// simulation will run 1 cycle per minute
	long cyclelimit = MIN_PER_HR * hours;  // # of cycles // 模擬多長時間(單位:分鐘)

	cout << "Enter the average number of customer per hour: ";
	double perhour;      // average # of arrival per hour
	cin >> perhour;      // 每小時有多少個客戶到達
	double min_per_cust; // average time between arrivals
	min_per_cust = MIN_PER_HR / perhour; //每個客戶到達的平均時間(單位:分鐘)

	Item temp;           // new customer data
	long turnaways = 0;  // truned away by full queue // 因隊列已滿,被拒絕的客戶數目
	long customers = 0;  // joined the queue // 加入隊列的客戶數
	long served = 0;     // served during the simulation // 已經獲得服務的客戶數目
	long sum_line = 0;   // cumulative line length // 累積隊列的長度(每分鐘在隊列中等待的客戶數目
						 // 並不一定相同(因爲存在出隊和入隊),即每分鐘裏隊列的長度不相同,將每分鐘裏隊列的長度
						 // 相加,即是sum_line的值。
	int wait_time = 0;   // time until autoteller is free // 等待前一個客戶處理完成的等待時間
	long line_wait = 0;  // cumulative time in line  // 排隊等候的累積時間

						 // running the simulation
	for (int cycle = 0; cycle < cyclelimit; cycle++) { // 程序沒分鐘循環一次,檢查是否有客戶到達
		if (newCustomer(min_per_cust)) {  // have newcomer
			if (line.isFull())
				turnaways++;
			else {
				customers++;
				temp.set(cycle);    // cycle = time of arrival
				line.enQueue(temp); // add newcomer to line
			}
		}
		if (wait_time <= 0 && !line.isEmpty()) {
			line.deQueue(temp);       // attend next customer
			wait_time = temp.ptime(); // for wait_time minutes
			line_wait += cycle - temp.when();
			served++;
		}
		if (wait_time > 0)
			wait_time--;
		sum_line += line.queueCount(); // 正在排隊的客戶隊列長度,不包括出隊成員
	}

	// reporting results
	if (customers > 0) {
		cout << "customers accepted: " << customers << endl; // 同意入隊的客戶數目
		cout << "  customers served: " << served << endl;    // 已經獲得服務的客戶數目
		cout << "         turnaways: " << turnaways << endl; // 被拒絕的客戶數目
		cout << "average queue size: ";
		cout.precision(2);
		cout.setf(ios_base::fixed, ios_base::floatfield);
		cout << (double)sum_line / cyclelimit << endl;
		cout << "average wait time: "
			<< (double)line_wait / served << " minutes\n";
	}
	else {
		cout << "No customers!\n";
	}
	cout << "Done!\n";

	return 0;
}

// x = average time, in minutes, between customers
// return value is true if customer shows up this minute
bool newCustomer(double x)
{
	// stdlib.h頭文件中有宏 #define RAND_MAX 0x7fff; rand()產生一個0到0x7ffff
	// 即0到32767之間的隨機數,( rand() / RAND_MAX )就等於一個0到1之間的小數了,
	// 因爲rand()最大是32767最小是0, 再除以32767就是一個0到1之間的小數, 再乘以
	// x就是一個0到x之間的小數了.
	//double temp = std::rand() * x / RAND_MAX;
	//std::cout << "randtime: " << temp << std::endl;
	//return temp < 1;
	//std::cout << "x: " << x << std::endl;
	return (std::rand() * x / RAND_MAX < 1); // 該語句用來模擬是否有新客戶到達,如果
											 // std::rand() * x / RAND_MAX < 1 代表有新客戶到達了。
											 // 本程序中,在第一種輸出結果時,x=60/15=4;說明std::rand() * x / RAND_MAX的值將
											 // 0到4之間的小數,具體的說,平均每4次就會出現一次小於1的情況。

}
/**
輸出結果:
	Case Study: Bank of Heather Automatic Teller
	Enter maximum size of queue: 10
	Enter the number of simulation hours: 200
	Enter the average number of customer per hour: 19
	customers accepted: 3812
	  customers served: 3812
			 turnaways: 0
	average queue size: 0.34
	average wait time: 1.06 minutes  
	Done!
*/

/***********************************
	2017年11月25日 15:00:11
	Athor:xiyuan255
	Course:C++
	Contain:bank3.cpp
			queue.h
			queue.cpp
	Reference: C++ Primer plus
    說明:C++ Primer plus第十二章的練習題 第六題
	【 參考 P478 】		
*************************************/
// bank.cpp -- using the Queue interface
// compile with queue.cpp
#include <iostream>
#include <cstdlib>   // for rand() and srand()
#include <ctime>     // for time()
#include "queue.h" 

const int MIN_PER_HR = 60;

bool newCustomer(double x);  // is there a new customer?

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	using std::ios_base;
// setting things up
	std::srand(std::time(0));  // random initializing of rand()

	cout << "Case Study: Bank of Heather Automatic Teller\n";
	cout << "Enter maximum size of queue: ";
	int qs;
	cin >> qs;
	Queue line1(qs);   // line1 queue holds up to qs people
	Queue line2(qs);   // line2 queue holds up to qs people

	cout << "Enter the number of simulation hours: ";
	int hours;        // hours of simulation
	cin >> hours;
	// simulation will run 1 cycle per minute
	long cyclelimit = MIN_PER_HR * hours;  // # of cycles // 模擬多長時間(單位:分鐘)

	cout << "Enter the average number of customer per hour: ";
	double perhour;      // average # of arrival per hour
	cin >> perhour;      // 每小時有多少個客戶到達
	double min_per_cust; // average time between arrivals
	min_per_cust = MIN_PER_HR / perhour; //每個客戶到達的平均時間(單位:分鐘)

	Item temp;           // new customer data
	long turnaways = 0;  // truned away by full queue // 因隊列已滿,被拒絕的客戶數目
	long customers = 0;  // joined the queue // 加入隊列的客戶數
	long served = 0;     // served during the simulation // 已經獲得服務的客戶數目
	long sum_line = 0;   // cumulative line length // 累積隊列的長度(每分鐘在隊列中等待的客戶數目
	     // 並不一定相同(因爲存在出隊和入隊),即每分鐘裏隊列的長度不相同,將每分鐘裏隊列的長度
	     // 相加,即是sum_line的值。
	int wait_time_line1 = 0;   // 隊列1的等待時間
	int wait_time_line2 = 0;   // 隊列2的等待時間
	long line_wait = 0;  // cumulative time in line  // 排隊等候的累積時間

// running the simulation
	for (int cycle = 0; cycle < cyclelimit; cycle++) { // 程序沒分鐘循環一次,檢查是否有客戶到達
		if (newCustomer(min_per_cust)) {  // have newcomer
			if (line1.isFull() && line2.isFull())
				turnaways++;
			else {
				if (line1.queueCount() > line2.queueCount()) {
					customers++;
					temp.set(cycle);    // cycle = time of arrival
					line2.enQueue(temp); // add newcomer to line
				} else {
					customers++;
					temp.set(cycle);    // cycle = time of arrival
					line1.enQueue(temp); // add newcomer to line
				}
			}
		}
		if (wait_time_line1 <= 0 && !line1.isEmpty()) {
			line1.deQueue(temp);       // attend next customer
			wait_time_line1 = temp.ptime(); // for wait_time minutes
			line_wait += cycle - temp.when();
			served++;
		}
		if (wait_time_line2 <= 0 && !line2.isEmpty()) {
			line2.deQueue(temp);       // attend next customer
			wait_time_line2 = temp.ptime(); // for wait_time minutes
			line_wait += cycle - temp.when();
			served++;
		}
		if (wait_time_line1 > 0)
			wait_time_line1--;
		if (wait_time_line2 > 0)
			wait_time_line2--;
		sum_line += line1.queueCount()+ line2.queueCount(); // 正在排隊的客戶隊列長度,不包括出隊成員
	}

// reporting results
	if (customers > 0) {
		cout << "customers accepted: " << customers << endl; // 同意入隊的客戶數目
		cout << "  customers served: " << served << endl;    // 已經獲得服務的客戶數目
		cout << "         turnaways: " << turnaways << endl; // 被拒絕的客戶數目
		cout << "average queue size: ";
		cout.precision(2);
		cout.setf(ios_base::fixed, ios_base::floatfield);
		cout << (double) sum_line / cyclelimit << endl;
		cout << "average wait time: "
			 << (double) line_wait / served << " minutes\n";
	} else {
		cout << "No customers!\n";
	}
	cout << "Done!\n";

	return 0;
}

// x = average time, in minutes, between customers
// return value is true if customer shows up this minute
bool newCustomer(double x)
{
	// stdlib.h頭文件中有宏 #define RAND_MAX 0x7fff; rand()產生一個0到0x7ffff
	// 即0到32767之間的隨機數,( rand() / RAND_MAX )就等於一個0到1之間的小數了,
	// 因爲rand()最大是32767最小是0, 再除以32767就是一個0到1之間的小數, 再乘以
	// x就是一個0到x之間的小數了.
	//double temp = std::rand() * x / RAND_MAX;
	//std::cout << "randtime: " << temp << std::endl;
	//return temp < 1;
	//std::cout << "x: " << x << std::endl;
	return (std::rand() * x / RAND_MAX < 1); // 該語句用來模擬是否有新客戶到達,如果
	                        // std::rand() * x / RAND_MAX < 1 代表有新客戶到達了。
	// 本程序中,在第一種輸出結果時,x=60/15=4;說明std::rand() * x / RAND_MAX的值將
	// 0到4之間的小數,具體的說,平均每4次就會出現一次小於1的情況。
	
}
/**
輸出結果1:
	Case Study: Bank of Heather Automatic Teller
	Enter maximum size of queue: 10
	Enter the number of simulation hours: 200
	Enter the average number of customer per hour: 51
	customers accepted: 10232
	  customers served: 10231
			 turnaways: 0
	average queue size: 0.89
	average wait time: 1.04 minutes
	Done!
*/

/**
	總結:【 參考 P475 】
	1.在類的構造函數中,可以使用new爲數據分配內存,然後將內存地址賦值給類成員。
	  這樣,類便可以處理長度不同的字符串,而不是在類設計時提前固定數組的長度。
	2.在類的構造函數中使用new,也可能在對象過期時引發問題。如果對象包含成員指針,
	  同時它指向的內存是由new分配的,則釋放用於保存對象的內存並不會自動釋放對象
	  成員指針指向的內存。因此在類構造函數中使用new類來分配內存時,應在類的析構
	  函數中使用delete來釋放分配的內存。這樣,當對象過期時,將自動釋放其指針成員
	  指向的內存。
	3.如果對象包含指向new分配的內存的指針成員,則將一個已知對象初始化爲另一個對象,
	  或將一個對象賦給另一個對象時,將會出現問題。因默認情況下,C++提供的複製構造
	  函數的實現是逐個對成員進行初始化和賦值,這意味着被初始化或被賦值的對象將與
	  原始對象完全相同(這種只將指針成員的值進行復制,叫做淺複製)。如果原始對象存在
	  指針成員並指向一個數據塊,則副本對象的指針成員也指向同一塊數據塊。當程序最終
	  刪除這兩個對象時,類的析構函數將試圖刪除同一塊內存數據塊兩次,這將導致出錯。
	  解決方法是:定義一個特殊的複製構造函數來重新定義初始化,並重載賦值運算符。在
	  上述任何一種情況下,新定義都將創建指向數據的副本;並使新對象指向這些副本。這樣,
	  舊對象和新對象都將引用獨立的、相同的數據,而不會重疊。由於同一的原因,必須定義
	  賦值運算符。對於每種情況,最終的目的都是執行深度複製,也就是說,複製實際的數據;
	  而不僅僅是複製指向的數據指針。
	4.如果沒有顯示提供類方法,編譯器將自動生成那些類方法?
	  C++自動提供下面的成員函數:
	  (1) 如果沒有定義構造函數,將提供默認構造函數。
	  (2) 如果沒有定義複製構造函數,將提供複製構造函數。
	  (3) 如果沒有定義析構函數,將提供默認析構函數。
	  (4) 如果沒有定義賦值運算符,將提供賦值運算符。
	  (5) 如果沒有定義地址運算符,將提供地址運算符。
	  默認構造函數不完成任何工作,但使得能夠聲明數組和未初始化對象。
	  默認複製構造函數和默認賦值運算符使用成員賦值(如果有指針成員,則是淺複製非深度複製)。
	  默認析構函數也不完成任何工作(析構函數只能有一個,且沒有形參)。
	  默認隱式地址運算符返回調用對象的地址(即 this指針的值)。
	  
	  

*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章