习题选自:C++ Primer Plus(第六版)
内容仅供参考,如有错误,欢迎指正 !
- c++使用new和delete运算符来动态控制内存。
- 对于静态成员,要在类声明之外使用单独语句进行初始化,因为静态类成员函数是单独存储的,而不是对象的组成部分,而且初始化是在方法文件中,而不是在头文件中,这是因为类声明位于头文件中,程序可能将头文件包括在其他几个文件中,如果在头文件中初始化,将出现多个初始化语句副本,从而引发错误。但如果静态成员是整形或枚举型const,则可以在类声明中初始化。
- 私有静态变量有且仅在初始化时,才可以在外部访问。
- 复制构造函数用于将一个对象复制到新创建的对象中,它用于初始化过程中(包括按值传递参数)。
class String { private: char * str; //points to string allocated by new int len; //holds length of string //... };
String ::String() {}
String:: String (const char* s) { str = s: len = strlen(s); }
String: :String (const char* s) { strcpy(str, s); len = strlen(s); }
a. 语法是正确的,但该构造函数没有初始化str指针。该构造函数应该使用new[]来初始化它,或者将其设置为NULL。
b. 该构造函数没有创建新的字符串,只是复制了原有字符串的地址,它应当使用new[]和strcpy()。
c. 它虽然复制了字符串,但没有给他分配存储空间,应使用new char[len+1]
来分配适当数量的内存。
可能出现的:
问题一:当对象过期的时候,对象的成员指针指向的数据仍保留在内存中,造成内存泄漏。
在析构函数中删除构造函数中new分配的内存,来解决该问题。
问题二:如果使用对象初1始化为另一个对象2时,采用默认初始化的方式,则在对象1过期后,在对象2过期过程中,其析构函数会对同一块内存释放两次,造成错误。
定义一个复制构造函数,使初始化复制指针指向的数据,而不是复制指针指向的地址。
问题三:将一个对象赋给另一个对象也将导致两个指针指向同一个数据。
重载赋值运算符,使之复制数据,而不是指针。
如果没有显示提供方法,c++将自动生成以下成员函数:
class nifty { // data char personality[]; int talents; // methods nifty(); nifty(char * s); ostream & operator<<(ostream & os, nifty & n); } nifty:nifty() { personality = NULL; talents = 0; } nifty:nifty(char * s) { personality = new char [strlen(s)]; personality = s; talents = 0; } ostream & nifty:operator<<(ostream & os, nifty & n) { os << n; }
应将personality成员声明为字符数组或car指针,或者将其声明为String对象。该声明没有将方法设置为公有的。修改后:
#include
#include
using namespace std;
class nifty
{
private: // optional
char personality[40]; // provide array size
int talents;
public: // needed
// methods
nifty();
nifty(const char * s);
friend ostream & operator<<(ostream & os, const nifty & n);
}; // note closing semicolon
nifty::nifty()
{
personality[0] = '\0';
talents = 0;
}
nifty::nifty(const char * s)
{
strcpy(personality, s);
talents = 0;
}
ostream & operator<<(ostream & os, const nifty & n)
{
os << n.personality << '\n';
os << n.talent << '\n';
return os;
}
class Golfer { private: char * fullname; // points to string containing golfer's name int games; // holds number of golf games played int * scores; // points to first element of array of golf scores public: Golfer(); Golfer(const char * name, int g= 0); // creates empty dynamic array of g elements if g > 0 Golfer(const Golfer & g); ~Golfer(); };
Golfer nancy; // #1 Golfer lulu(“Little Lulu”); // #2 Golfer roy(“Roy Hobbs”, 12); // #3 Golfer * par = new Golfer; // #4 Golfer next = lulu; // #5 Golfer hazzard = “Weed Thwacker”; // #6 *par = nancy; // #7 nancy = “Nancy Putter”; // #8
a.
Golfer nancy; // 默认构造函数
Golfer lulu("Little Lulu"); // Golfer(const char * name, int g)
Golfer roy("Roy Hobbs", 12); // Golfer(const char * name, int g)
Golfer* par = new Golfer; // 默认构造函数
Golfer next = lulu; // Golfer(const Golfer &g)
Golfer hazard = "Weed Thwacker"; // Golfer(const char * name, int g)
*par = nancy; // 默认赋值运算符
nancy = "Nancy Putter"; // 先调用Golfer(const char * name, int g), 再默认赋值运算符
b. 有以下两个方法:
class Cow { 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 };
cow.h:
#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() { delete [] hobby; }
Cow & operator=(const Cow & c);
void show() const;
};
#endif
cow.cpp:
#include "cow.h"
#include
#include
Cow::Cow() {
name[0] = '\0';
hobby = nullptr;
weight = 0.0;
}
Cow::Cow(const char* nm, const char* ho, double wt) {
std::strncpy(name, nm, 20);
int len = std::strlen(ho) + 1;
hobby = new char[len];
std::strcpy(hobby, ho);
weight = wt;
}
Cow::Cow(const Cow& c) {
std::strncpy(name, c.name, 20);
int len;
len = std::strlen(c.hobby);
hobby = new char[len];
std::strcpy(hobby, c.hobby);
weight = c.weight;
}
Cow& Cow::operator=(const Cow& c) {
if (this == &c) return *this; // object assigned to itself
std::strncpy(name, c.name, 20);
delete[] hobby;
int len;
len = std::strlen(c.hobby);
hobby = new char[len];
std::strcpy(hobby, c.hobby);
weight = c.weight;
return *this;
}
void Cow::show() const {
std::cout << "name: " << name << std::endl;
std::cout << "hobby: " << hobby << std::endl;
std::cout << "weight: " << weight << std::endl;
}
main.cpp:
#include
#include "cow.h"
int main() {
Cow c1("xiao", "eating", 100);
c1.show();
Cow c2 = c1;
c2.show();
Cow c3;
c3 = c2;
c3.show();
return 0;
}
// pe12_2.cpp #include
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 =, + operators cout << s2 << ".\n"; s2 = s2 + s1; s2.stringup(); // converts string to uppercase cout << "The string\n" << s2 << "\ncontains " << s2.has('A') << " 'A' characters in it.\n"; 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
string2.h:
#ifndef STRING2_H_
#define STRING2_H_
#include
using std::istream;
using std::ostream;
class String {
private:
char *str;
int len;
static int num_strings;
static const int CINLIM = 80;
public:
String(const char *s);
String();
String(const String &s);
~String();
int length() const { return len; }
void stringlow();
void stringup();
int has(char x);
String &operator=(const String &s);
String &operator=(const char *s);
char &operator[](int i);
const char &operator[](int i) const;
String operator+(const String &s) const;
String operator+(const char *s) const;
friend bool operator<(const String &s1, const String &s2);
friend bool operator>(const String &s1, const String &s2);
friend bool operator==(const String &s1, const String &s2);
friend ostream &operator<<(ostream &os, const String &st);
friend istream &operator>>(istream &is, String &st);
friend String operator+(const char *, const String &);
static int HowMany();
};
#endif // STRING2_H_
string.cpp:
#include "string2.h"
// #include
#include
// initialize static members
int String::num_strings = 0;
int String::HowMany() { return num_strings; }
String::String(const char *s) {
len = std::strlen(s);
str = new char[len + 1];
std::strcpy(str, s);
num_strings++;
}
String::String() {
len = 1;
str = new char[1];
str[0] = '\0';
num_strings++;
}
String::String(const String &s) {
len = s.len;
str = new char[len + 1];
std::strcpy(str, s.str);
num_strings++;
}
String::~String() {
--num_strings;
delete[] str;
}
void String::stringlow() {
for (int i = 0; i < len; ++i) {
if (std::isupper(str[1])) str[i] = std::tolower(str[i]);
}
}
void String::stringup() {
for (int i = 0; i < len; ++i)
if (std::islower(str[i])) str[i] = std::toupper(str[i]);
}
int String::has(char x) {
int count = 0;
for (int i = 0; i < len; ++i) {
if (str[i] == x) count++;
}
return count;
}
String &String::operator=(const String &s) {
if (this == &s) return *this;
delete[] str;
len = s.len;
str = new char[len + 1];
std::strcpy(str, s.str);
return *this;
}
String &String::operator=(const char *s) {
delete[] str;
len = std::strlen(s);
str = new char[len + 1];
std::strcpy(str, s);
return *this;
}
char &String::operator[](int i) { return str[i]; }
const char &String::operator[](int i) const { return str[i]; }
String String::operator+(const String &s) const {
int total_len = len + s.len;
char *tmp = new char[total_len + 1];
std::strcpy(tmp, str);
std::strcat(tmp, s.str);
String str_new = tmp;
delete[] tmp;
return str_new;
}
String String::operator+(const char *s) const {
String tmp = s;
String sum = *this + tmp;
return sum;
}
bool operator<(const String &s1, const String &s2) {
return (std::strcmp(s1.str, s2.str) < 0);
}
bool operator>(const String &s1, const String &s2) {
return (std::strcmp(s1.str, s2.str) > 0);
}
bool operator==(const String &s1, const String &s2) {
//比较相等的时候不考虑大小写,使用strcasecmp(linux)/stricmp(windows)
return (strcasecmp(s1.str, s2.str) == 0);
}
ostream &operator<<(ostream &os, const String &st) {
os << st.str;
return os;
}
istream &operator>>(istream &is, String &st) {
char tmp[String::CINLIM];
is.get(tmp, String::CINLIM);
if (is) st = tmp;
while (is && is.get() != '\n') continue;
return is;
}
String operator+(const char *s1, const String &s2) { return String(s1) + s2; }
载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。
stock20.h:
// stock20.h -- augmented version
#ifndef STOCK20_H_
#define STOCK20_H_
#include
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 char* co, long n = 0, double pr = 0.0);
~Stock(); // do-nothing destructor
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
friend std::ostream& operator<<(std::ostream& os, const Stock& st);
const Stock& topval(const Stock& s) const;
};
#endif
stock.cpp:
// stock20.h -- augmented version
#ifndef STOCK20_H_
#define STOCK20_H_
#include
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 char* co, long n = 0, double pr = 0.0);
~Stock(); // do-nothing destructor
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
friend std::ostream& operator<<(std::ostream& os, const Stock& st);
const Stock& topval(const Stock& s) const;
};
#endif
usestock20.cpp:
// stock20.cpp -- augmented version
#include "stock20.h"
#include
// constructors
Stock::Stock() // default constructor
{
company = new char[std::strlen("no name") + 1];
std::strcpy(company, "no name");
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const char* co, long n, double pr) {
company = new char[std::strlen(co) + 1];
std::strcpy(company, co);
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();
}
// class destructor
Stock::~Stock() // quiet class destructor
{
delete[] company;
}
// other methods
void Stock::buy(long num, double price) {
if (num < 0) {
std::cout << "Number of shares purchased can’t be negative. "
<< "Transaction is aborted.\n";
} 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 is aborted.\n";
} else if (num > shares) {
cout << "You can’t sell more than you have! "
<< "Transaction is aborted.\n";
} else {
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price) {
share_val = price;
set_tot();
}
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;
}
const Stock& Stock::topval(const Stock& s) const {
if (s.total_val > total_val)
return s;
else
return *this;
}
// stack.h -- class declaration for the stack ADT 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); // creates stack with n elements Stack(const Stack & st); ~Stack(); bool isempty() const; bool isfull() const; // push() returns false if stack already is full, true otherwise bool push(const Item & item); // add item to stack // pop() returns false if stack already is empty, true otherwise bool pop(Item & item); // pop top into item Stack & operator=(const Stack & st); };
stack.h:
// stack.h -- class declaration for the stack ADT
#ifndef STACK_H_
#define STACK_H_
#include
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); // creates stack with n elements
Stack(const Stack& st);
~Stack();
bool isempty() const;
bool isfull() const;
// push() returns false if stack already is full, true otherwise
bool push(const Item& item); // add item to stack
// pop() returns 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 // STACK_H_
stack.cpp:
// stack.cpp -- Stack member functions
#include "stack.h"
Stack::Stack(int n) // create an empty stack
{
size = MAX;
top = 0;
pitems = new Item[size];
for (int i = 0; i < size; ++i) pitems[i] = 0;
}
Stack::Stack(const Stack& st) {
delete[] pitems;
size = st.size;
top = st.top;
pitems = new Item[size];
for (int i = 0; i < size; ++i) pitems[i] = st.pitems[i];
}
Stack::~Stack() { delete[] pitems; }
bool Stack::isempty() const { return top == 0; }
bool Stack::isfull() const { return top == MAX; }
bool Stack::push(const Item& item) {
if (top < MAX) {
pitems[top++] = item;
return true;
} else
return false;
}
bool Stack::pop(Item& item) {
if (top > 0) {
item = pitems[--top];
return true;
} else
return false;
}
Stack& Stack::operator=(const Stack& st) {
if (this == &st) return *this;
delete[] pitems;
size = st.size;
top = st.top;
pitems = new Item[size];
for (int i = 0; i < size; ++i) pitems[i] = st.pitems[i];
return *this;
}
std::ostream& operator<<(std::ostream& os, const Stack& st) {
for (int i = 0; i < st.top; i++) {
os << st.pitems[i] << std::endl;
}
return os;
}
main.cpp:
// stacker.cpp -- testing the Stack class
#include // or ctype.h
#include
#include "stack.h"
int main() {
using namespace std;
Stack st; // create an empty stack
char ch;
unsigned long po;
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
while (cin >> ch && toupper(ch) != 'Q') {
while (cin.get() != '\n') continue;
if (!isalpha(ch)) {
cout << '\a';
continue;
}
switch (ch) {
case 'A':
case 'a':
cout << "Enter a PO number to add: ";
cin >> po;
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p':
if (st.isempty())
cout << "stack already empty\n";
else {
st.pop(po);
cout << "PO #" << po << " popped\n";
}
break;
}
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
}
Stack st2;
st2 = st;
cout << "stack2 = stack is:\n" << st2;
cout << "Bye\n";
return 0;
}
根据实际情况可知,每小时到达的客户数目越多,则平均等候时间越长,若要求平均等候时间为1分钟(即平均等候时间不超过1分钟时的临界情况)对应的每小时到达客户数,则我们可以让程序从每小时客户数从1开始计算(不小于100小时)其对应的平均排队时间,直到平均等待时间刚好超过1分钟的时候停止,此时对应的客户数(或者对应客户数-1)即为答案。
queue.h(未修改):
// queue.h -- interface for a queue
#ifndef QUEUE_H_
#define QUEUE_H_
// This queue will contain Customer items
class Customer {
private:
long arrive; // arrival 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:
// class scope definitions
// Node is a nested structure definition local to this class
struct Node {
Item item;
struct Node* next;
};
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 end
bool dequeue(Item& item); // remove item from front
};
#endif
queue.cpp(未修改):
// queue.cpp -- Queue and Customer methods
#include "queue.h"
#include // (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->next; // reset pointer to next item
delete temp; // delete former front
}
}
bool Queue::isempty() const { return items == 0; }
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 pointers
add->next = NULL; // or nullptr;
items++;
if (front == NULL) // if queue is empty,
front = add; // place item at front
else
rear->next = add; // else place at rear
rear = add; // have rear point to new node
return true;
}
// Place front item into item variable and remove from queue
bool Queue::dequeue(Item& item) {
if (front == NULL) return false;
item = front->item; // set item to first item in queue
items--;
Node* temp = front; // save location of first item
front = front->next; // reset front to next item
delete temp; // delete former first item
if (items == 0) rear = NULL;
return true;
}
// customer method
// when is the time at which the customer arrives
// the arrival time is set to when and the processing
// time set to a random value in the range 1 - 3
void Customer::set(long when) {
processtime = std::rand() % 3 + 1;
arrive = when;
}
main.cpp:
// bank.cpp -- using the Queue interface
// compile with queue.cpp
#include // for rand() and srand()
#include // for time()
#include
#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
double perhour = 1; // number of customers per hour starts from 1
double min_per_cust; // average time between arrivals
min_per_cust = MIN_PER_HR / perhour;
Item temp; // new customer data
long turnaways = 0; // turned away by full queue
long customers = 0; // joined the queue
long served = 0; // served during the simulation
long sum_line = 0; // cumulative line length
int wait_time = 0; // time until autoteller is free
long line_wait = 0; // cumulative time in line
double average_time = 0; // average time
while (perhour++ && average_time <= 1) {
while (!line.isempty()) {
line.dequeue(temp);
}
min_per_cust = MIN_PER_HR / perhour;
for (int cycle = 0; cycle < cyclelimit; cycle++) {
if (newcustomer(min_per_cust)) {
if (line.isfull())
turnaways++;
else {
customers++;
temp.set(cycle);
line.enqueue(temp);
}
}
if (wait_time <= 0 && !line.isempty()) {
line.dequeue(temp);
wait_time = temp.ptime();
line_wait += cycle - temp.when();
served++;
}
if (wait_time > 0) wait_time--;
sum_line += line.queuecount();
}
if (customers > 0) {
average_time = (double)line_wait / served;
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: " << average_time << " minutes\n";
} else
cout << "No customers!\n";
}
cout << "When there comes " << perhour
<< " people per hour, the average wait time will be about 1 minute.\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) { return (std::rand() * x / RAND_MAX < 1); }
实验过程中,队列最大数为10,模拟小时数为100,结果如下:
Case Study: Bank of Heather Automatic Teller
Enter maximum size of queue: 10
Enter the number of simulation hours: 100
customers accepted: 217
customers served: 217
turnaways: 0
average queue size: 0.00
average wait time: 0.06 minutes
customers accepted: 522
customers served: 522
turnaways: 0
average queue size: 0.01
average wait time: 0.07 minutes
customers accepted: 941
customers served: 941
turnaways: 0
average queue size: 0.01
average wait time: 0.09 minutes
customers accepted: 1465
customers served: 1465
turnaways: 0
average queue size: 0.02
average wait time: 0.10 minutes
customers accepted: 2078
customers served: 2078
turnaways: 0
average queue size: 0.04
average wait time: 0.12 minutes
customers accepted: 2821
customers served: 2821
turnaways: 0
average queue size: 0.07
average wait time: 0.15 minutes
customers accepted: 3640
customers served: 3640
turnaways: 0
average queue size: 0.10
average wait time: 0.17 minutes
customers accepted: 4525
customers served: 4525
turnaways: 0
average queue size: 0.14
average wait time: 0.19 minutes
customers accepted: 5534
customers served: 5534
turnaways: 0
average queue size: 0.20
average wait time: 0.21 minutes
customers accepted: 6617
customers served: 6617
turnaways: 0
average queue size: 0.26
average wait time: 0.24 minutes
customers accepted: 7780
customers served: 7780
turnaways: 0
average queue size: 0.35
average wait time: 0.27 minutes
customers accepted: 9094
customers served: 9094
turnaways: 0
average queue size: 0.47
average wait time: 0.31 minutes
customers accepted: 10427
customers served: 10427
turnaways: 0
average queue size: 0.60
average wait time: 0.34 minutes
customers accepted: 11989
customers served: 11989
turnaways: 0
average queue size: 0.82
average wait time: 0.41 minutes
customers accepted: 13588
customers served: 13588
turnaways: 0
average queue size: 1.02
average wait time: 0.45 minutes
customers accepted: 15277
customers served: 15277
turnaways: 0
average queue size: 1.25
average wait time: 0.49 minutes
customers accepted: 17118
customers served: 17116
turnaways: 0
average queue size: 1.55
average wait time: 0.54 minutes
customers accepted: 19000
customers served: 18998
turnaways: 0
average queue size: 1.90
average wait time: 0.60 minutes
customers accepted: 21012
customers served: 21009
turnaways: 0
average queue size: 2.39
average wait time: 0.68 minutes
customers accepted: 23139
customers served: 23136
turnaways: 0
average queue size: 2.94
average wait time: 0.76 minutes
customers accepted: 25374
customers served: 25368
turnaways: 0
average queue size: 3.59
average wait time: 0.85 minutes
customers accepted: 27661
customers served: 27653
turnaways: 0
average queue size: 4.36
average wait time: 0.95 minutes
customers accepted: 30018
customers served: 30010
turnaways: 1
average queue size: 5.32
average wait time: 1.06 minutes
When there comes 25.00 people per hour, the average wait time will be about 1 minute.
Done!
queue.h(未修改):
// queue.h -- interface for a queue
#ifndef QUEUE_H_
#define QUEUE_H_
// This queue will contain Customer items
class Customer {
private:
long arrive; // arrival 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:
// class scope definitions
// Node is a nested structure definition local to this class
struct Node {
Item item;
struct Node* next;
};
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 end
bool dequeue(Item& item); // remove item from front
};
#endif
queue.cpp(未修改):
// queue.cpp -- Queue and Customer methods
#include "queue.h"
#include // (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->next; // reset pointer to next item
delete temp; // delete former front
}
}
bool Queue::isempty() const { return items == 0; }
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 pointers
add->next = NULL; // or nullptr;
items++;
if (front == NULL) // if queue is empty,
front = add; // place item at front
else
rear->next = add; // else place at rear
rear = add; // have rear point to new node
return true;
}
// Place front item into item variable and remove from queue
bool Queue::dequeue(Item& item) {
if (front == NULL) return false;
item = front->item; // set item to first item in queue
items--;
Node* temp = front; // save location of first item
front = front->next; // reset front to next item
delete temp; // delete former first item
if (items == 0) rear = NULL;
return true;
}
// customer method
// when is the time at which the customer arrives
// the arrival time is set to when and the processing
// time set to a random value in the range 1 - 3
void Customer::set(long when) {
processtime = std::rand() % 3 + 1;
arrive = when;
}
main.cpp:
// bank.cpp -- using the Queue interface
// compile with queue.cpp
#include // for rand() and srand()
#include // for time()
#include
#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
double perhour = 1; // number of customers per hour starts from 1
double min_per_cust; // average time between arrivals
min_per_cust = MIN_PER_HR / perhour;
Item temp; // new customer data
long turnaways = 0; // turned away by full queue
long customers = 0; // joined the queue
long served = 0; // served during the simulation
long sum_line = 0; // cumulative line length
int line1_size = 0; // number of people in line1
int line2_size = 0; // number of people in line2
int wait_time1 = 0; // time until autoteller is free in line1
int wait_time2 = 0; // time until autoteller is free in line2
long line_wait = 0; // cumulative time in line
double average_time = 0; // average time
while (perhour++ && average_time <= 1) {
while (!line1.isempty()) {
line1.dequeue(temp);
}
while (!line2.isempty()) {
line2.dequeue(temp);
}
min_per_cust = MIN_PER_HR / perhour;
for (int cycle = 0; cycle < cyclelimit; cycle++) {
if (newcustomer(min_per_cust)) {
if (line1.isfull() && line2.isfull())
turnaways++;
else if (line1_size < line2_size) {
customers++;
temp.set(cycle);
line1.enqueue(temp);
line1_size++;
} else {
customers++;
temp.set(cycle);
line2.enqueue(temp);
line2_size++;
}
}
if (wait_time1 <= 0 && !line1.isempty()) {
line1.dequeue(temp);
line1_size--;
wait_time1 = temp.ptime();
line_wait += cycle - temp.when();
served++;
}
if (wait_time2 <= 0 && !line2.isempty()) {
line2.dequeue(temp);
line2_size--;
wait_time2 = temp.ptime();
line_wait += cycle - temp.when();
served++;
}
if (wait_time1 > 0) wait_time1--;
if (wait_time2 > 0) wait_time2--;
sum_line += line1.queuecount() + line2.queuecount();
}
if (customers > 0) {
average_time = (double)line_wait / served;
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: " << average_time << " minutes\n";
} else
cout << "No customers!\n";
}
cout << "When there comes " << perhour
<< " people per hour, the average wait time will be about 1 minute.\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) { return (std::rand() * x / RAND_MAX < 1); }
实验过程中,队列最大数为10,模拟小时数为100,结果如下:
Case Study: Bank of Heather Automatic Teller
Enter maximum size of queue: 10
Enter the number of simulation hours: 100
customers accepted: 212
customers served: 212
turnaways: 0
average queue size: 0.00
average wait time: 0.03 minutes
customers accepted: 520
customers served: 520
turnaways: 0
average queue size: 0.00
average wait time: 0.06 minutes
customers accepted: 917
customers served: 917
turnaways: 0
average queue size: 0.01
average wait time: 0.06 minutes
customers accepted: 1372
customers served: 1372
turnaways: 0
average queue size: 0.02
average wait time: 0.07 minutes
customers accepted: 1987
customers served: 1987
turnaways: 0
average queue size: 0.03
average wait time: 0.10 minutes
customers accepted: 2715
customers served: 2715
turnaways: 0
average queue size: 0.05
average wait time: 0.11 minutes
customers accepted: 3471
customers served: 3471
turnaways: 0
average queue size: 0.07
average wait time: 0.12 minutes
customers accepted: 4367
customers served: 4367
turnaways: 0
average queue size: 0.09
average wait time: 0.13 minutes
customers accepted: 5368
customers served: 5368
turnaways: 0
average queue size: 0.13
average wait time: 0.14 minutes
customers accepted: 6454
customers served: 6454
turnaways: 0
average queue size: 0.17
average wait time: 0.16 minutes
customers accepted: 7639
customers served: 7639
turnaways: 0
average queue size: 0.22
average wait time: 0.17 minutes
customers accepted: 8909
customers served: 8909
turnaways: 0
average queue size: 0.27
average wait time: 0.18 minutes
customers accepted: 10292
customers served: 10292
turnaways: 0
average queue size: 0.33
average wait time: 0.19 minutes
customers accepted: 11830
customers served: 11830
turnaways: 0
average queue size: 0.41
average wait time: 0.21 minutes
customers accepted: 13347
customers served: 13347
turnaways: 0
average queue size: 0.48
average wait time: 0.21 minutes
customers accepted: 15033
customers served: 15033
turnaways: 0
average queue size: 0.57
average wait time: 0.23 minutes
customers accepted: 16837
customers served: 16836
turnaways: 0
average queue size: 0.67
average wait time: 0.24 minutes
customers accepted: 18717
customers served: 18716
turnaways: 0
average queue size: 0.79
average wait time: 0.25 minutes
customers accepted: 20775
customers served: 20774
turnaways: 0
average queue size: 0.91
average wait time: 0.26 minutes
customers accepted: 22874
customers served: 22873
turnaways: 0
average queue size: 1.05
average wait time: 0.28 minutes
customers accepted: 25038
customers served: 25037
turnaways: 0
average queue size: 1.20
average wait time: 0.29 minutes
customers accepted: 27395
customers served: 27394
turnaways: 0
average queue size: 1.37
average wait time: 0.30 minutes
customers accepted: 29826
customers served: 29825
turnaways: 0
average queue size: 1.54
average wait time: 0.31 minutes
customers accepted: 32313
customers served: 32312
turnaways: 0
average queue size: 1.73
average wait time: 0.32 minutes
customers accepted: 34782
customers served: 34781
turnaways: 0
average queue size: 1.90
average wait time: 0.33 minutes
customers accepted: 37513
customers served: 37511
turnaways: 0
average queue size: 2.12
average wait time: 0.34 minutes
customers accepted: 40250
customers served: 40248
turnaways: 0
average queue size: 2.33
average wait time: 0.35 minutes
customers accepted: 43151
customers served: 43149
turnaways: 0
average queue size: 2.56
average wait time: 0.36 minutes
customers accepted: 46116
customers served: 46114
turnaways: 0
average queue size: 2.80
average wait time: 0.36 minutes
customers accepted: 49234
customers served: 49232
turnaways: 0
average queue size: 3.07
average wait time: 0.37 minutes
customers accepted: 52400
customers served: 52398
turnaways: 0
average queue size: 3.35
average wait time: 0.38 minutes
customers accepted: 55651
customers served: 55648
turnaways: 0
average queue size: 3.65
average wait time: 0.39 minutes
customers accepted: 59012
customers served: 59008
turnaways: 0
average queue size: 3.97
average wait time: 0.40 minutes
customers accepted: 62468
customers served: 62464
turnaways: 0
average queue size: 4.29
average wait time: 0.41 minutes
customers accepted: 66015
customers served: 66010
turnaways: 0
average queue size: 4.62
average wait time: 0.42 minutes
customers accepted: 69696
customers served: 69691
turnaways: 0
average queue size: 4.97
average wait time: 0.43 minutes
customers accepted: 73509
customers served: 73503
turnaways: 0
average queue size: 5.38
average wait time: 0.44 minutes
customers accepted: 77483
customers served: 77476
turnaways: 0
average queue size: 5.81
average wait time: 0.45 minutes
customers accepted: 81552
customers served: 81544
turnaways: 0
average queue size: 6.24
average wait time: 0.46 minutes
customers accepted: 85676
customers served: 85668
turnaways: 0
average queue size: 6.70
average wait time: 0.47 minutes
customers accepted: 89893
customers served: 89885
turnaways: 0
average queue size: 7.18
average wait time: 0.48 minutes
customers accepted: 94185
customers served: 94177
turnaways: 0
average queue size: 7.68
average wait time: 0.49 minutes
customers accepted: 98572
customers served: 98564
turnaways: 0
average queue size: 8.22
average wait time: 0.50 minutes
customers accepted: 103067
customers served: 103058
turnaways: 0
average queue size: 8.78
average wait time: 0.51 minutes
customers accepted: 107697
customers served: 107688
turnaways: 0
average queue size: 9.38
average wait time: 0.52 minutes
customers accepted: 112391
customers served: 112382
turnaways: 0
average queue size: 9.98
average wait time: 0.53 minutes
customers accepted: 117190
customers served: 117181
turnaways: 0
average queue size: 10.67
average wait time: 0.55 minutes
customers accepted: 122085
customers served: 122075
turnaways: 0
average queue size: 11.43
average wait time: 0.56 minutes
customers accepted: 127075
customers served: 127065
turnaways: 0
average queue size: 12.17
average wait time: 0.57 minutes
customers accepted: 132223
customers served: 132212
turnaways: 0
average queue size: 13.06
average wait time: 0.59 minutes
customers accepted: 137410
customers served: 137398
turnaways: 0
average queue size: 14.04
average wait time: 0.61 minutes
customers accepted: 142710
customers served: 142697
turnaways: 0
average queue size: 15.11
average wait time: 0.63 minutes
customers accepted: 148126
customers served: 148112
turnaways: 0
average queue size: 16.21
average wait time: 0.66 minutes
customers accepted: 153631
customers served: 153617
turnaways: 0
average queue size: 17.51
average wait time: 0.68 minutes
customers accepted: 159249
customers served: 159234
turnaways: 0
average queue size: 19.50
average wait time: 0.73 minutes
customers accepted: 164952
customers served: 164936
turnaways: 0
average queue size: 22.05
average wait time: 0.80 minutes
customers accepted: 170746
customers served: 170720
turnaways: 0
average queue size: 24.75
average wait time: 0.87 minutes
customers accepted: 176635
customers served: 176603
turnaways: 11
average queue size: 29.79
average wait time: 1.01 minutes
When there comes 60.00 people per hour, the average wait time will be about 1 minute.
Done