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