// 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指針的值)。
*/