【第十二章】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指针的值)。
	  
	  

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值