C + + premier plus (Sixth Edition) Chapter 12 class and dynamic memory allocation programming practice answers

1. For the following class declarations:

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
};

Provide an implementation for this class and write an applet that uses all functions.
There is no difficulty in writing the class method implementation according to the class declaration. Then write the test function. When writing the test function, you encounter a problem. The main function defines a string object, which cannot match the type of the constructor. Modify it into a string array to solve it. The code is as follows:

// cow.h -- definition of Cow class
#ifndef COW_H_
#define COW_H_
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
};
#endif
// cow.cpp -- methods for Cow class
#include <iostream>
#include <cstring>
#include "cow.h"

Cow::Cow()
{
    name[0] = '\0';
    hobby = NULL;
    weight = 0.0;
}

Cow::Cow(const char * nm, const char * ho, double wt)
{
    strcpy(name, nm);
    hobby = new char [strlen(ho) + 1];
    strcpy(hobby, ho);
    weight = wt;
}

Cow::Cow(const Cow & c)
{
    strcpy(name, c.name);
    hobby = new char [strlen(c.hobby) + 1];
    strcpy(hobby, c.hobby);
    weight = c.weight;
}

Cow::~Cow()
{
    delete [] hobby;
}

Cow & Cow::operator=(const Cow & c)
{
    strcpy(name, c.name);
    hobby = new char [strlen(c.hobby) + 1];
    strcpy(hobby, c.hobby);
    weight = c.weight;
    return *this;
}

void Cow::ShowCow() const
{
    std::cout << "Name: " << name << ", hobby: " << hobby << ", weight = " << weight << '\n';
}
// ex1.cpp -- test Cow class
// compile with cow.cpp
#include <iostream>
#include <cstring>
#include "cow.h"


int main()
{
	using std::cout;
	using std::cin;
	using std::endl;
	int num;
	char tname[20];
	double wt;
	char tho[20];
	cout << "Enter the number of student: ";
	cin >> num;
	cin.get();
	Cow cows[num];
	int i;
	for(i = 0; i < num; i++)
	{
		cout << "Student #" << i + 1 << ":\n";
		cout << "Enter student's name<empty line to quit>: ";
		cin.getline(tname, 20);
		if(strcmp(tname, "") == 0)
			break;
		cout << "Enter the hobby of this student: ";
		cin.getline(tho,20);
		cout << "Enter this student's weight: ";
		cin >> wt;
		cin.get();
		cows[i] = Cow(tname,tho,wt);
	}
	int total = i;
	cout << "Student list:\n";
	for (i = 0; i < total; i++)
		cows[i].ShowCow();
	Cow last;
	last = cows[total - 1];
	cout << "Last student is \n"; 
	last. ShowCow();
	return 0;
}

The operation results are as follows:

2. Improve the String class declaration by completing the following work (i.e. upgrading String1.h to String2.h)

a. Overload the + operator so that it can combine two strings into one.
b. A Stringlow() member function is provided to convert all alphabetic characters of a string to lowercase (don't forget the cctype series character functions).
c. Provides a Stringup() member function to convert all alphabetic characters in a string to uppercase.
d. Provide a member function that accepts a char parameter and returns the number of times the character appears in the string.
Use the following procedure to test your work:

// 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;
	cin >> s3;
	s2 = "My name is " + s3;
	cout << s2 << ".\n";
	s2 = s2 + s1;
	s2.Stringup();
	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();
		for(int i = 0; i < 3; i++)
		{
			if (ans == rgb[i])
			{
				cout << "That's right!\n";
				success = true;
				break;
			}
		}
		if(success)
			break;
		else
			cout << "Try again!\n";
	}
	cout << "Bye\n";
	return 0;
}

The implementation method of this problem class is not difficult.
However, there are many problems when writing the + operator. The addition operator is planned to be implemented through a friend operator overload and a member function operator overload. Unknown problems are encountered in the writing process, so the friend overload operator + is directly used; When writing the conversion case function, the start code is wrong, only toupper(str[i]), so str[i] will not be modified, which needs to be modified with the return value of the function; Count the number of characters. Use an if statement. The code of this example has no problem when running. When debugging, the destructor delete str [] is called many times. The author has not found the reason for this for the time being, and will modify it later. if the cause is caused by the strcat() function, change the function code to use the for loop to assign values to temp [] in turn; Another approach is to use strcpy_s(temp,int size;const char *) function. The first function is the starting point of the assignment string, the second is the length of the copied string, and the third is the copied string. The sample code is as follows:

// String2.h -- definiton of String class
// version2.0
#ifndef STRING2_H_
#define STRING2_H_
#include <iostream>
using std::istream;
using std::ostream;
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);
        String();
        String(const String &);
        ~String();
        int length() const { return len; }
        void Stringlow();
        void Stringup();
        int has(char ch);
    // overloaded operator methods
        String & operator=(const String &);
        String & operator=(const char *);
        // String & operator+(const String &);
        char & operator[](int i);
        const char & operator[](int i) const;
    // overloaded operator friends
        friend String 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 bool operator==(const String & st1, const String & st2);
        friend istream & operator>>(istream & is, String & st);
        friend ostream & operator<<(ostream & os, const String & st);
    // static function
        static int HowMany();
};
#endif
// String2.cpp -- methods for String class
#include <cstring>
#include <cctype>
#include "String2.h"


int String::num_strings = 0;
// constructors and other methods
String::String()
{
    len = 0;
    str = new char[len + 1];
    *str = '\0';
    num_strings++;
}

String::String(const char * s)
{
    len = strlen(s);
    str = new char[len + 1];
    strcpy(str, s);
    num_strings++;
}

String::String(const String & s)
{
    len = s.len;
    str = new char[len + 1];
    strcpy(str, s.str);
    num_strings++;
}

String::~String()
{
    --num_strings;
    delete [] str;
}

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

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

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

String & String::operator=(const String & s) 
{
    if(this == &s)
        return *this;
    len = s.len;
    delete [] str;
    str = new char[len + 1];
    strcpy(str, s.str);
    return *this;
}

String & String::operator=(const char * s) 
{
    len = strlen(s);
    delete [] str;
    str = new char[len + 1];
    strcpy(str, s);
    return * this;
}
// String & String::operator+(const String & s)
// {
//     String temp = *this;
//     delete [] str;
//     len += s.len;
//     str = new char[len + 1];
//     str = strcat(temp.str, s.str);
//     return *this;
// }
char & String::operator[](int i)
{
    return str[i];
}

const char & String::operator[](int i) const
{
    return str[i];
}

// overloaded operator friends

String  operator+(const String & st1, const String & st2)
{
    char * temp = new char[st1.len + st2.len + 1];
    // temp = strcat(st1.str,st2.str);
    int i;
    for(i = 0; i < st1.len; i++)
        temp[i] = st1.str[i];
    for(; i < st1.len + st2.len + 1; i++)
    {
        temp[i] = st2.str[i - st1.len];
    }
    temp[st1.len + st2.len + 1] = '\0';
    return String(temp);
}

bool operator<(const String & st1, const String & st2)
{
    return (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 (strcmp(st1.str, st2.str) == 0);
}

istream & operator>>(istream & is, String & st)
{
    char temp[String::CINLIM];
    is.get(temp,String::CINLIM);
    if(is)
        st = temp;
    while(is && is.get() != '\n')
        continue;
    return is;
}

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

int String::HowMany()
{
    return num_strings;
}

The operation results are as follows:

3. Newly write the Stock class described in listing 10.7 and listing 10.8 to use dynamically allocated memory instead of string class objects to store Stock names. In addition, the overloaded operator < < () definition replaces the show() member function. Then use program listing 10.9 to test the new definition program.

There are few changes to modify the dynamically allocated memory in this problem. After modifying the private member, modify the constructor, default constructor, destructor and the code that returns the company value function. After modifying, the company's dynamic memory allocation is realized. Because this problem does not use the copy constructor, it is not necessary to write the deep copy constructor, The overloaded operator < < () function needs to return os. The code of this problem is as follows:

// stock20.h -- augment version
// verson 20
#ifndef STOCK20_H_
#define STOCK20_H_
#include <iostream>

class Stock
{
    char * company;
    long shares;
    double share_val;
    double total_val;
    void set_tot(){ total_val = shares * share_val; }

    public:
        Stock();
        Stock(const char * str, long n = 0.0, double pr = 0.0);
        ~Stock();
        void buy(long num, double price);
        void sell(long num, double price);
        void update(double price);
        void show()const;
        const Stock & topval(const Stock & s) const;
        const char * getcompany() const{return company;}
        long getshares() const{return shares;}
        double getshares_val() const {return share_val;}
        double gettotal_val() const {return total_val;}
        friend std::ostream & operator<<(std::ostream & os, const Stock & s);
};
#endif
// stock20.cpp --augment version
// version 20
#include<cstring>
#include"stock20.h"

// constructors
Stock::Stock()
{
    company = new char[1];
    company[0] = '\0';
    shares = 0;
    share_val = 0.0;
    total_val = 0.0;
}

Stock::Stock(const char * str, long n, double pr)
{
    company = new char[strlen(str) + 1];
    strcpy(company, str);
    if(n < 0)
    {
        std::cout << "Number of shares can't be negative; "
                  << company << " shares will be set to 0.\n";
    }
    else
        shares = n;
    share_val = pr;
    set_tot();
}

Stock::~Stock()
{
    delete [] company;
}

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)
{
    if(num < 0)
    {
        std::cout << "Number of shares sold can't be negative. "
                  << "Transaction is aborted.\n";
    }
    else if(num > shares)
    {
        std::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;
}

void Stock::show()const
{
    using std::cout;
    using std::ios_base;
    // set format to #.###
    ios_base::fmtflags orig =
        cout.setf(ios_base::fixed, ios_base::floatfield);
    std::streamsize prec = cout.precision(3);

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

    // restore orignal format

    cout.setf(orig,ios_base::floatfield);
    cout.precision(prec);
}

const Stock & Stock::topval(const Stock & s) const
{
    return s.total_val > total_val ? s : *this;
}

std::ostream & operator<<(std::ostream & os, const Stock & s)
{
    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: " << s.getcompany()
        << "Shares: " << s.shares << '\n';
    os << "   Share Price: $" << s.share_val;
    // set format to #.##
    os.precision(2);
    os << "   Total Worth: $" << s.total_val << '\n';

    // restore orignal format

    os.setf(orig,ios_base::floatfield);
    os.precision(prec);
    return os;
}
// usestock10_9.cpp -- using the Stock class
// compile with stock20.cpp
#include<iostream>
#include"stock20.h"

const int STKS = 4;

int main()
{
// create an array of initialized objects
    Stock stocks[STKS] = 
    {
        Stock("NanaSmart", 12, 20.0),
        Stock("Boffo Objects", 200, 2.0),
        Stock("Monolithic Obelisks", 130, 3.25),
        Stock("Fleep Enterprises", 60, 6.5)
    };

    std::cout << "Stock holding:\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 points to the most valuable holding
    std::cout << "\nMost valuable holding:\n";
    std::cout << * top;
    return 0;
}

The operation results are as follows:

4. See the variables of the Stack class defined in listing 10.10 below:

// stack.h -- class defination for the stack ADT
#ifndef STACK_H_
#define STACK_H_

typedef unsigned long Item;

class Stack
{
    private:
        enum {MAX = 10};
        Item * pitems;
        int top;            // index for top stack item
        int size;           // number of elements
    public:
        Stack(int n = MAX);
        Stack(const Stack & st);
        ~Stack();
        bool isempty() const;
        bool isfull() const;
        // push() return false if stack is full, ture otherwise
        bool push(const Item & item);
        // pop() return false if stack is empty, true otherwise
        bool pop(Item & item);
        Stack & operator=(const Stack & st);
};
#endif

As private members indicate, this class uses dynamically allocated arrays to hold stack items. Please rewrite the method to adapt to this new representation, and write a program to demonstrate all methods, including copy constructors and assignment operators.
This topic uses dynamically allocated arrays to save stack items. The core is to write the functions of copy constructors and assignment operators. When writing, I copy the elements in the dynamic array into the object and use the for loop to complete the procedures of pressing and popping the stack. What I wrote is different from that in the book and can be run. I personally feel that it is better in the book, The main function uses a function that looks for the maximum value to call the copy constructor, and st2=st1 to use the assignment operator. The code is as follows:

// stack.h -- class defination for the stack ADT
#ifndef STACK_H_
#define STACK_H_

typedef unsigned long Item;

class Stack
{
    private:
        enum {MAX = 10};
        Item * pitems;
        int top;            // index for top stack item
        int size;           // number of elements
    public:
        Stack(int n = MAX);
        Stack(const Stack & st);
        ~Stack();
        bool isempty() const;
        bool isfull() const;
        // push() return false if stack is full, ture otherwise
        bool push(const Item & item);
        // pop() return false if stack is empty, true otherwise
        bool pop(Item & item);
        Stack & operator=(const Stack & st);
};
#endif
// stack.cpp -- methods for Stack class
#include "stack.h"

Stack::Stack(int n)
{
    size = n;
    pitems = new Item[n];
    top = 0;
}

Stack::Stack(const Stack & st)
{
    size = st.size;
    pitems = new Item[st.size];
    
    for(top = 0; top < st.top; top++)
        pitems[top] = st.pitems[top];
    top = st.top;
}

Stack::~Stack()
{
    size = 0;
    delete [] pitems;
}

bool Stack::isempty() const
{
    return top == 0;
}

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

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

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

Stack & Stack::operator=(const Stack & st)
{
    if(this == &st)
        return *this;
    size = st.size;
    pitems = new Item[st.size];
    for(top = 0; top < st.top; top++)
        pitems[top] = st.pitems[top];
    top = st.top;
    return *this;
}
// stacker10_12.cpp -- testing the Stack class
#include <iostream>
#include <cctype>
#include "stack.h"

Item findmax(Stack st);	// using Stack(const Stack & st) to get copy od st
int main()
{
    using namespace std;
	Item num;
    Stack st1(6);
	Stack st2;
	int count = 0;
	cout << "Enter a seires of number, I'll show them and find the maximum.\n";
	cout << "Enter q to quit\n";
	while(!st1.isfull())
	{
		cout << "Value #" << count + 1 << ": ";
		cin >> num;
		if(!cin)
			break;
		st1.push(num);
		count++;
	}
    cout << "The list of you input number:\n";
	st2 = st1;		// using Stack & operator=(const Stack & st)
	while (!st2.isempty())
	{
		st2.pop(num);
		cout << num << '\t';
	}
	cout << endl;
	Item max = findmax(st1);
	cout << "The maximun of these numbers is " << max << endl;
	cout << "Pop st1:\n";
	while (!st1.isempty())
	{
		st1.pop(num);
		cout << num << '\t';
	}
	cout << endl;
	cout << "Done\n";
    return 0;
}

Item findmax(Stack st)
{
	Item max,temp;
	st.pop(max);
	while(!st.isempty())
	{
		st.pop(temp);
		max = max > temp ? max : temp;
	}
	return max;
}

The operation results are as follows:

5. Research conducted by Heather bank shows that ATM customers do not want to queue for no more than 1 minute. Using the simulation in program listing 12.10, find out the average waiting time is 1 minute, and what should be the number of customers arriving per hour (the test time should not be less than 100 hours)?

The main modification of this problem is the program of the main function. Because the comparison needs to calculate the results of a cycle and obtain the data before comparison, the dowile cycle is selected. The key of this problem is that the variables to be changed in the cycle should be placed in the cycle. At the beginning, the author did not convert a few people per hour into a few minutes per hour cycle into the cycle body, Cause the program cannot jump out of the loop and solve it after adding. The code is as follows:

// queue.h -- definition of Queue class
#ifndef QUEUE_H_
#define QUEUE_H_

class Customer
{
private:
    long arrive;
    int processtime;
public:

    Customer(){ arrive = processtime = 0;}

    void set(long when);
    long When() const {return arrive;}
    long Ptime() const {return processtime;}
};


typedef Customer Item;

class Queue
{
private:
    struct Node
    {
        Item item;
        struct Node * next;     // Node * next
    };
    enum{Q_SZIE = 10};
    // 
    Node * front;
    Node * rear;
    int items;
    const int qsize;
    Queue(const Queue & q):qsize(0){}
    Queue & operator=(const Queue & q){return * this;}
public:
    Queue(int qs = Queue::Q_SZIE);         // why need to point to Queue class Q_SIZE
    ~Queue();
    bool isempty() const;
    bool isfull() const;
    int queuecount() const;
    bool enqueue(const Item & item);
    bool dequeue(Item & item);
};
#endif
// queue.cpp - methods for Queue class

#include "queue.h"
#include <cstdlib>

Queue::Queue(int q):qsize(q)
{
    items = 0;
    front = rear = nullptr;
}
Queue::~Queue()
{
    while(!isempty())
    {
        Node * temp;
        temp = front;
        front = front->next;
        items--;
        delete temp;
    }
}

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

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

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

bool Queue::enqueue(const Item & item)
{
    if(items < qsize)
    {
        Node * add = new Node;
        add->item = item;
        if(isempty())
        {
            front = rear =add;
        }
        else
        {
            rear->next = add;
            rear = add;
        }
        rear->next = nullptr;
        items++;
        return true;
    }
    return false;
}

bool Queue::dequeue(Item & item)
{
    if(items > 0)
    {
        Node * temp;
        item = front->item;
        temp = front;
        front = front->next;
        delete temp;
        items--;
        return true;
    }
    return false;
}

void Customer::set(long when)
{
    arrive = when;
    processtime = rand() % 3 + 1;
}
// 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;

	std::srand(std::time(0));
	cout << "Case Study: Bank of Heather Automatic Teller\n";
	// cout << "Enter the maximum size of queue: ";
	// int qs;
	// cin >> qs;
	// Queue line (qs);

	cout << "Enter the number of simulation hours: ";
	int hours;
	cin >> hours;
	long cyclelimit = hours * MIN_PER_HR;
	
	// cout << "Enter the average number of customers per hour: ";
	// double perhour;
	// cin >> perhour;
	double perhour = 1;
	int qs = int(4*perhour);
	Queue line (qs);
	

	Item temp;                 // new customer data
    long turnaways = 0;        // turn away by full queue
    long customers = 0;        // joined the queue
    long served = 0;           // served during the simulation
    long sum_line = 0;         // cmulative line length
    long wait_time = 0;        // time untile autoteller is free
    long line_wait = 0;        // cumulative time in line
	do
	{
		int qs = int(4*perhour);
		double min_per_cust = MIN_PER_HR / perhour;		// is necessary at while body
		Queue line (qs);
    	turnaways = 0;        // turn away by full queue
    	customers = 0;        // joined the queue
    	served = 0;           // served during the simulation
    	sum_line = 0;         // cmulative line length
    	wait_time = 0;        // time untile autoteller is free
    	line_wait = 0;        // cumulative time in line
		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();
		}
		cout << "Perhour = " << perhour << ":\n";
		// 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 << " avergae wait time: "
				<< (double) line_wait / served << "minutes\n";
    	}
    	else
		{
			cout << "No customerr!\n";
		}
		perhour+=1;
		line.~Queue();
	}while((double) line_wait / served < 1);
	
// 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 << " avergae wait time: "
             << (double) line_wait / served << "minutes\n";
    }
    else
        cout << "No customerr!\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);
}

Since this problem started from receiving 1 person per hour, the results are relatively long. The first three and last three operation results are intercepted as follows:


It can be seen that it should be 18.

6. Heather bank would like to know what would happen if an ATM were opened in. Modify the simulation to include two queues. Suppose that when the number of people queuing in front of the first ATM is less than that of the second ATM, customers will be in the first queue, otherwise they will be in the second queue. Then find out how many customers should arrive per hour if the average waiting time is 1 minute (note that this is a nonlinear problem, that is, doubling the number of ATMs does not guarantee doubling the number of customers processed per hour, and ensure that the waiting time of customers is less than 1 minute)

This question is similar to the previous one. In different cases, two ATMs are used, so the class interface and implementation file remain unchanged. What needs to be modified is the main function. Two ATMs need two queues, marked as line1 and line2 respectively; Then modify the program when customers come, and leave when both queues are full; Otherwise, enter the queue. Compare the number of people in the two queues. line1 is less, and enter line1 or line2. Next, judge the program of the queue. Since there are two queues, there are two waiting times, which are recorded as waittime1 and waittime2 respectively; Conduct departure operation and time reduction operation respectively. The code is as follows:

// queue.h -- definition of Queue class
#ifndef QUEUE_H_
#define QUEUE_H_

class Customer
{
private:
    long arrive;
    int processtime;
public:

    Customer(){ arrive = processtime = 0;}

    void set(long when);
    long When() const {return arrive;}
    long Ptime() const {return processtime;}
};


typedef Customer Item;

class Queue
{
private:
    struct Node
    {
        Item item;
        struct Node * next;     // Node * next
    };
    enum{Q_SZIE = 10};
    // 
    Node * front;
    Node * rear;
    int items;
    const int qsize;
    Queue(const Queue & q):qsize(0){}
    Queue & operator=(const Queue & q){return * this;}
public:
    Queue(int qs = Queue::Q_SZIE);         // why need to point to Queue class Q_SIZE
    ~Queue();
    bool isempty() const;
    bool isfull() const;
    int queuecount() const;
    bool enqueue(const Item & item);
    bool dequeue(Item & item);
};

#endif
// queue.cpp - methods for Queue class

#include "queue.h"
#include <cstdlib>

Queue::Queue(int q):qsize(q)
{
    items = 0;
    front = rear = nullptr;
}
Queue::~Queue()
{
    while(!isempty())
    {
        Node * temp;
        temp = front;
        front = front->next;
        items--;
        delete temp;
    }
}

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

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

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

bool Queue::enqueue(const Item & item)
{
    if(items < qsize)
    {
        Node * add = new Node;
        add->item = item;
        if(isempty())
        {
            front = rear =add;
        }
        else
        {
            rear->next = add;
            rear = add;
        }
        rear->next = nullptr;
        items++;
        return true;
    }
    return false;
}

bool Queue::dequeue(Item & item)
{
    if(items > 0)
    {
        Node * temp;
        item = front->item;
        temp = front;
        front = front->next;
        delete temp;
        items--;
        return true;
    }
    return false;
}

void Customer::set(long when)
{
    arrive = when;
    processtime = rand() % 3 + 1;
}
// 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;

	std::srand(std::time(0));
	cout << "Case Study: Bank of Heather Automatic Teller\n";

	cout << "Enter the number of simulation hours: ";
	int hours;
	cin >> hours;
	long cyclelimit = hours * MIN_PER_HR;
	
	double perhour = 20;	//20 must be enough
	int qs = int(4*perhour);
	

	Item temp;                 // new customer data
    long turnaways = 0;        // turn away by full queue
    long customers = 0;        // joined the queue
    long served = 0;           // served during the simulation
    // long sum_line = 0;         // cmulative line length
    long wait_time1 = 0;       // time untile autoteller1 is free
	long wait_time2 = 0;	   // time untile autoteller2 is free
    long line_wait = 0;        // cumulative time in line
	do
	{
		int qs = int(4*perhour);
		double min_per_cust = MIN_PER_HR / perhour;		// is necessary at while body
		Queue line1 (qs),line2(qs);
    	turnaways = 0;        // turn away by full queue
    	customers = 0;        // joined the queue
    	served = 0;           // served during the simulation
    	// sum_line = 0;         // cmulative line length
    	wait_time1 = 0;
		wait_time2 = 0;        // time untile autoteller is free
    	line_wait = 0;        // cumulative time in line
		for(int cycle = 0; cycle < cyclelimit; cycle++)
		{
			if(newcustomer(min_per_cust))
			{
				if(line1.isfull()&&line2.isfull())	// line1 full && line2 full
					turnaways++;
				else
				{
					customers++;
					temp.set(cycle);
					if(line1.queuecount()<line2.queuecount())
						line1.enqueue(temp);
					else
						line2.enqueue(temp);
				}
			}

			if(wait_time1 <= 0 && !line1.isempty())
			{
				line1.dequeue(temp);
				wait_time1 = temp.Ptime();
				line_wait += cycle - temp.When(); 
				served++;
			}
			if(wait_time2 <= 0 && !line2.isempty())
			{
				line2.dequeue(temp);
				wait_time2 = temp.Ptime();
				line_wait += cycle - temp.When(); 
				served++;
			}
			if(wait_time1 > 0)
			{
				wait_time1--;
			}
			if(wait_time2 > 0)
			{
				wait_time2--;
			}
		}
		cout << "Perhour = " << perhour << ":\n";
	// reporting results
    	if(customers > 0)
    	{
        	cout << "customers accepted: " << customers << endl;
        	cout << "  customers served: " << served << endl;
        	cout << "         turnaways: " << turnaways << endl;
			cout << " avergae wait time: "
				<< (double) line_wait / served << "minutes\n";
    	}
    	else
		{
			cout << "No customerr!\n";
		}
		perhour+=1;
	}while((double) line_wait / served < 1);
	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);
}

Since the time of 20 people must be less than 1 minute, the operation starts from 20, and the operation results are as follows (results of the first four groups and the last four groups):


It can be seen from the results that the two ATM s can receive 50 people, and the waiting time for no one is less than 1min, which is nearly three times higher than the result of question 5. Therefore, this is not a linear problem.

Added by toolmania1 on Sun, 02 Jan 2022 16:44:01 +0200