12
12
#ifndef COW_H_
#define COW_H_
3
4
class Cow
private:
char name[20];
char * hobby;
double weight;
10 public:
11
Cow();
12
13
14
~Cow();
15
16
17 };
18
19 #endif
cow.cpp
1
#include <iostream>
#include "cow.h"
3
4
Cow::Cow()
name[0] = '\0';
hobby = NULL;
weight = 0;
10
11 Cow::Cow (const char * nm, const char * ho, double wt)
12 {
13
strcpy(name,nm);
14
15
strcpy(hobby,ho);
16
weight = wt;
17 }
18
19 Cow::Cow (const Cow & c)
20 {
21
strcpy(name,c.name);
22
23
strcpy(hobby,c.hobby);
24
weight = c.weight;
25 }
26
27 Cow::~Cow()
28 {
29
delete [] hobby;
30 }
31
32 Cow & Cow::operator=(const Cow & c)
33 {
34
35
return *this;
36
delete [] hobby;
37
strcpy(name,c.name);
38
39
strcpy(hobby,c.hobby);
40
weight = c.weight;
41
return *this;
42 }
43
44 void Cow::ShowCow() const
45 {
46
47
if (hobby == NULL)
48
49
else
50
51
52 }
cp12ex1.cpp
1
#include <iostream>
#include "cow.h"
3
4
int main()
7
8
Cow name2;
10
11
12
name1.ShowCow();
13
name2.ShowCow();
14
name3.ShowCow();
15
16
17
18
name2.ShowCow();
19
20
21
22
23
24
name1.ShowCow();
25
name2.ShowCow();
26
name3.ShowCow();
27
28
cin.get();
29
cin.get();
30
return 0;
31 }
Fran says:
August 22, 2012 at 10:35 am
Cow & Cow::operator=(const Cow & c)
{
if (this == &c) // object assigned to itself
return *this;
delete [] hobby;
strcpy(name,c.name);
2. Enhance the String class declaration (that is, upgrade string1.h to string2.h) by
doing the following:
a. Overload the + operator to allow you to join two strings into one.
b. Provide a stringlow() member function that converts all alphabetic characters in
a string to lowercase. (Dont forget the cctype family of character functions.)
c. Provide a stringup() member function that converts all alphabetic characters in a
string to uppercase.
d. Provide a member function that takes a char argument and returns the number of
times the character appears in the string.
test your work in the following program:
// 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++)
{
10
11
12
13 public:
14
15
16
17
18
~String(); // destructor
19
20
void stringlow();
21
void stringup();
22
23
24
25
26
27
28
29
30
31
32
33
34
friend ostream & operator<<(ostream & os, const String & st);
35
36
// static function
37
38 };
39 #endif
string2.cpp
1
#include <cctype>
using std::cin;
using std::cout;
int String::num_strings = 0;
// static method
int String::HowMany()
10
11
return num_strings;
12
13
// class methods
14
15
16
17
18
19
20
21
22
23
len = 4;
24
25
26
num_strings++;
27
28
29
30
31
32
33
34
35
36
37
--num_strings; // required
38
39
40
41
void String::stringlow()
42
43
44
strcpy(temp,str);
45
46
47
temp[i] = tolower(temp[i]);
48
strcpy(str,temp);
49
delete [] temp;
50
51
52
53
void String::stringup()
54
55
56
strcpy(temp,str);
57
58
59
temp[i] = toupper(temp[i]);
60
strcpy(str,temp);
61
delete [] temp;
62
63
64
65
66
67
int chnum = 0;
68
69
70
if (str[i] == ch)
71
chnum++;
72
73
74
return chnum;
75
76
77
78
79
80
81
82
83
String temp;
84
85
86
strcpy(temp.str,str);
87
strcat(temp.str,st.str);
88
89
90
return temp;
}
91
92
93
94
String temp;
95
96
97
strcpy(temp.str,st2);
98
strcat(temp.str,st.str);
99
100
return temp;
101 }
102 String & String::operator=(const String & st)
103 {
104
if (this == &st)
105
return *this;
106
delete [] str;
107
len = st.len;
108
109
std::strcpy(str, st.str);
110
return *this;
111 }
112 // assign a C string to a String
delete [] str;
116
len = std::strlen(s);
117
118
std::strcpy(str, s);
119
return *this;
120 }
121 // read-write char access for non-const String
122 char & String::operator[](int i)
123 {
124
return str[i];
125 }
126 // read-only char access for const String
127 const char & String::operator[](int i) const
128 {
129
return str[i];
130 }
131 // overloaded operator friends
132 bool operator<(const String &st1, const String &st2)
133 {
134
135 }
136 bool operator>(const String &st1, const String &st2)
137 {
138
139 }
140 bool operator==(const String &st1, const String &st2)
141 {
142
143 }
144 // simple String output
145 ostream & operator<<(ostream & os, const String & st)
146 {
147
os << st.str;
148
return os;
149 }
150 // quick and dirty String input
151 istream & operator>>(istream & is, String & st)
152 {
153
char temp[String::CINLIM];
154
is.get(temp, String::CINLIM);
155
if (is)
156
157
158
159
160 }
st = temp;
while (is && is.get() != '\n')
continue;
return is;
cp12ex2.cpp
1 #include <iostream>
2 using namespace std;
3 #include "string2.h"
4 int main()
5 {
6
8
9
String s3;
10
11
12
13
14
s2 = s2 + s1;
15
16
cout << "The string\n" << s2 << "\ncontains " << s2.has('A') << " 'A' characters in it.\n";
17
18
19
20
cout << "Enter the name of a primary color for mixing light: ";
21
String ans;
22
23
24
25
26
27
28
29
30
31
success = true;
32
break;
33
34
35
if (success)
36
break;
37
else
38
39
40
41
42
cin.get();
43
cin.get();
44
return 0;
45}
Saad says:
April 7, 2012 at 6:50 pm
The operator+ overloaded functions return objects that cease to exist upon termination of the
function, returned data will be garbled as the memory they point to has been cleared by the
destructor. Another solution is required.
Reply
Saad says:
April 7, 2012 at 7:02 pm
My bad it works, I was using a & operator+ overload in my implementation :P
Reply
Saad says:
April 7, 2012 at 7:06 pm
String String::operator+(const String & st)
{
String tmp;
tmp.len = len + st.len;
delete [] tmp.str; //Default constructor allocates enough room for null char, must clear that.
tmp.str = new char[tmp.len+1];
strcpy(tmp.str, str);
strcat(tmp.str, st.str);
return tmp;
}
String operator+(const char *st1, const String &st2)
{
String tmp;
tmp.len = strlen(st1) + st2.len + 1;
delete [] tmp.str; //Clear default constructor allocated memory.
tmp.str = new char[tmp.len];
strcpy(tmp.str, st1);
strcat(tmp.str, st2.str);
return tmp;
}
Reply
Fran says:
August 22, 2012 at 11:49 am
You define to operator+ functions, one as a method and the other as a friend. But this is
unnecessary becuase the friend function already deals with all posible combinations.
Reply
Fran says:
August 22, 2012 at 11:51 am
OTOH, why do you create a temporary char* in the stringlow() and stringup()
methods? You can deal directly with str without the need of dynamic memory
allocation.
Saad says:
April 7, 2012 at 6:50 pm
The operator+ overloaded functions return objects that cease to exist upon termination of the
function, returned data will be garbled as the memory they point to has been cleared by the
destructor. Another solution is required.
Reply
Saad says:
April 7, 2012 at 7:02 pm
My bad it works, I was using a & operator+ overload in my implementation :P
Reply
Saad says:
April 7, 2012 at 7:06 pm
String String::operator+(const String & st)
{
String tmp;
tmp.len = len + st.len;
delete [] tmp.str; //Default constructor allocates enough room for null char, must clear that.
tmp.str = new char[tmp.len+1];
strcpy(tmp.str, str);
strcat(tmp.str, st.str);
return tmp;
}
String operator+(const char *st1, const String &st2)
{
String tmp;
tmp.len = strlen(st1) + st2.len + 1;
delete [] tmp.str; //Clear default constructor allocated memory.
tmp.str = new char[tmp.len];
strcpy(tmp.str, st1);
strcat(tmp.str, st2.str);
return tmp;
}
Reply
Fran says:
August 22, 2012 at 11:49 am
You define to operator+ functions, one as a method and the other as a friend. But this is
unnecessary becuase the friend function already deals with all posible combinations.
Reply
Fran says:
August 22, 2012 at 11:51 am
OTOH, why do you create a temporary char* in the stringlow() and stringup()
methods? You can deal directly with str without the need of dynamic memory
allocation.
++++++++
3. Rewrite the Stock class, as described in Listings 10.7 and 10.8 in Chapter 10,
so that it
uses dynamically allocated memory directly instead of using string class objects
to hold
the stock names. Also, replace the show() member function with an overloaded
operator<<() definition. Test the new definition program in Listing 10.9.
stock2.h
1 #ifndef STOCK2_H_
2 #define STOCK2_H_
3 class Stock
4 {
5 private:
6
char * company;
int shares;
double share_val;
double total_val;
10
11 public:
12
13
14
15
16
~Stock();
17
18
19
20
21
friend std::ostream & operator<<(std::ostream & os, const Stock & s);
22 };
23 #endif
stock2.cpp
1
#include <iostream>
#include "stock2.h"
// constructors
std::strcpy(company,"no name");
shares = 0;
10
share_val = 0.0;
11
total_val = 0.0;
12 }
13 Stock::Stock(const char * co, int n, double pr)
14 {
15
16
std::strcpy(company,co);
17
if (n < 0)
18
19
20
21
shares = 0;
22
23
else
24
shares = n;
25
26
share_val = pr;
27
set_tot();
28 }
29
30 // copy constructor
31 Stock::Stock(const Stock &st)
32 {
33
34
std::strcpy(company,st.company);
35
shares = st.shares;
36
share_val = st.share_val;
37
total_val = st.total_val;
38
set_tot();
39 }
40
41 // assignment constructor
42 Stock & Stock::operator=(const Stock & st)
43 {
44
if (this == &st)
45
return *this;
46
delete [] company;
47
48
std::strcpy(company,st.company);
49
shares = st.shares;
50
share_val = st.share_val;
51
total_val = st.total_val;
52
set_tot();
53
return *this;
54 }
55
56 // class destructor
57 Stock::~Stock() // quiet class destructor
58 {
59
delete [] company;
60 }
61 // other methods
62 void Stock::buy(int num, double price)
63 {
64
if (num < 0)
65
66
67
68
69
else
70
71
shares += num;
72
share_val = price;
73
set_tot();
74
75 }
76 void Stock::sell(int num, double price)
77 {
78
using std::cerr;
79
if (num < 0)
80
81
82
83
84
85
86
cerr << "You can't sell more than you have! "
87
88
89
else
90
91
shares -= num;
92
share_val = price;
93
set_tot();
94
95 }
96 void Stock::update(double price)
97 {
98
share_val = price;
99
set_tot();
100 }
101
102 const Stock & Stock::topval(const Stock & s) const
103 {
104
105
106
107
108 }
109
110 std::ostream & operator<<(std::ostream & os, const Stock & s)
111 {
112
113
114
115
116
return os;
117 }
cp12ex3.cpp
1 #include <iostream>
2 #include "stock2.h"
3 const int STKS = 4;
4 int main()
5{
6
using std::cout;
using std::ios_base;
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
int st;
std::cin.get();
0
std::cin.get();
2
1
return 0;
2}
2
Just curious, why did you write a copy constructor you have double calls to std::cin.get()
Reply
Fran says:
August 22, 2012 at 12:54 pm
Thats because when you manage memory dynamically with classes you need to
use one of those to do deep copying and not simply copying the same address from
one object to another. (in this specific program I think its not necessary, neither is
necessary the overloaded assignment operator but just for precaucion, its a good
practice) The cin.get() its because in windows console applications, when the
program finishes it automatically closes the window, you cannot see anything at all.
This way the window remains open until the user press any key and the program
terminates (he really needed only one cin.get() in this case, the two are redundant).
BTW, he has one error in cout << top. As top is a Stock *, it will display its address,
it won't call operator<<(). For it to call the function he needs to put cout << *top, as
it's expecting an object, not a pointer.
+++++++++++
4. Consider the following variation of the Stack class defined in Listing 10.10:
// 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 = 10); // creates stack with n elements
Stack(const Stack & st);
~Stack();
10
11
12
13 public:
14
15
16
~Stack();
17
18
19
20
21
22
23
24 };
25
26 #endif
d_stack.cpp
1
#include "d_stack.h"
size = n;
top = 0;
8
9
10 {
11
size = st.size;
12
top = st.top;
13
14
15
pitems[i] = st.pitems[i];
16 }
17
18 bool Stack::isempty() const
19 {
20
return top == 0;
21 }
22 bool Stack::isfull() const
23 {
24
25 }
26 bool Stack::push(const Item & item)
27 {
28
29
30
pitems[top++] = item;
31
return true;
32
33
else
34
return false;
35 }
36 bool Stack::pop(Item & item)
37 {
38
if (top > 0)
39
40
item = pitems[--top];
41
return true;
42
43
else
44
return false;
45 }
46
47 Stack::~Stack()
48 {
49
delete [] pitems;
50 }
51
52 Stack & Stack::operator=(const Stack & st)
53 {
54
if (this == &st)
55
return *this;
56
delete [] pitems;
57
size = st.size;
58
top = st.top;
59
60
61
pitems[i] = st.pitems[i];
62
return *this;
63 }
cp12ex4.cpp
1 #include <iostream>
2 #include <cctype> // or ctype.h
3 #include "d_stack.h"
4
5 using namespace std;
6 void stackprocessing(Stack &);
7
8 int main()
9 {
10
11
12
13
14
15
16
st2 = st1;
17
18
19
20
21
22
23
stackprocessing(st3);
}
else
cout << "\n\nFirst stack is empty, exitting...";
24
25
26
27
cin.get();
28
cin.get();
29
return 0;
30 }
31
32 void stackprocessing(Stack & st)
33 {
34
char ch;
35
36
37
38
39
40
41
continue;
42
if (!isalpha(ch))
43
44
45
continue;
46
47
switch(ch)
48
49
case 'A':
50
51
52
if (st.isfull())
53
54
55
56
st.push(po);
break;
57
case 'P':
58
else
60
61
st.pop(po);
62
63
64
break;
65
66
67
68
}
}
5. The Bank of Heather has performed a study showing that ATM customers
wont wait
more than one minute in line. Using the simulation from Listing 12.10, find a
value for
number of customers per hour that leads to an average wait time of one minute.
(Use at
least a 100-hour trial period.)
My answer:
queue.h
1
#ifndef QUEUE_H_
#define QUEUE_H_
class Customer
private:
public:
10
11
12
13
14 };
15
16 typedef Customer Item;
17
18 class Queue
19 {
20 private:
21
22
23
24
25
26
27
28
29
30
31
32
33 public:
34
35
~Queue();
36
37
38
39
40
41 };
42 #endif
queue.cpp
1 #include "queue.h"
items = 0;
7 }
8 Queue::~Queue()
9 {
10
Node * temp;
11
12
13
14
15
16
17 }
18 bool Queue::isempty() const
19 {
20
return items == 0;
21 }
22 bool Queue::isfull() const
23 {
24
25 }
26 int Queue::queuecount() const
27 {
28
return items;
29 }
30 // Add item to queue
31 bool Queue::enqueue(const Item & item)
32 {
33
if (isfull())
34
return false;
35
36
if (add == NULL)
37
38
39
add->next = NULL;
40
items++;
41
42
43
else
44
45
46
return true;
47 }
48 // Place front item into item variable and remove from queue
49 bool Queue::dequeue(Item & item)
50 {
51
if (front == NULL)
52
return false;
53
54
items--;
55
56
57
58
if (items == 0)
59
rear = NULL;
60
return true;
61 }
62 // customer method
63 // when is the time at which the customer arrives
64 // the arrival time is set to when and the processing
65 // time set to a random value in the range 1 - 3
processtime = std::rand() % 3 + 1;
69
arrive = when;
70 }
cp12ex5.cpp
1 #include <iostream>
2 #include <cstdlib> // for rand() and srand()
3 #include <ctime> // for time()
4 #include "queue.h"
5
6 const int MIN_PER_HR = 60;
7 bool newcustomer(double x); // is there a new customer?
8
9 int main()
10 {
11
using std::cin;
12
using std::cout;
13
using std::endl;
14
using std::ios_base;
15
// setting things up
16
17
18
19
int qs;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
double averagewait = 0;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// since values for processing times are random it will take a while, on
average 5-10 min of running this program, be patient
// sometimes it finds value very fast, again, because it's random
do
{
// reset all values for a new simulation loop
Item temp;
turnaways = 0; // turned away by full queue
customers = 0; // joined the queue
served = 0; // served during the simulation
sum_line = 0; // cumulative line length
wait_time = 0; // time until autoteller is free
line_wait = 0; // cumulative time in line
52
53
54
55
56
57
58
59
60
61
if (line.isfull())
62
turnaways++;
63
else
64
65
customers++;
66
67
68
69
70
71
72
73
74
75
served++;
76
77
if (wait_time > 0)
78
wait_time--;
79
sum_line += line.queuecount();
80
81
82
83
84
85
86
87
88
89
90
91
92
93 #######################" << endl; // Success!!
94
95
cout << " customers served: " << served << endl;
96
97
98
cout.precision(2);
99
cout.setf(ios_base::fixed, ios_base::floatfield);
10
0
cout.setf(ios_base::showpoint);
10
1
10
2
10
3
10
4
10
5
10
6
10
7 }
6. The Bank of Heather would like to know what would happen if it added a
second ATM.
Modify the simulation in this chapter so that it has two queues. Assume that a
customer
will join the first queue if it has fewer people in it than the second queue and that
the
customer will join the second queue otherwise. Again, find a value for number of
customers
per hour that leads to an average wait time of one minute. (Note: This is a
nonlinear
problem in that doubling the number of ATMs doesnt double the number of
customers who can be handled per hour with a one-minute wait maximum.)
My answer:
queue.h
1
#ifndef QUEUE_H_
#define QUEUE_H_
class Customer
private:
public:
10
11
12
13
14 };
15
16 typedef Customer Item;
17
18 class Queue
19 {
20 private:
21
22
23
24
25
26
27
28
29
30
31
32
33 public:
34
35
~Queue();
36
37
38
39
40
41 };
42 #endif
queue.cpp
1 #include "queue.h"
2 #include <cstdlib> // (or stdlib.h) for rand()
3 Queue::Queue(int qs) : qsize(qs)
4 {
5
items = 0;
7 }
8 Queue::~Queue()
9 {
10
Node * temp;
11
12
13
14
15
16
17 }
18 bool Queue::isempty() const
19 {
20
return items == 0;
21 }
22 bool Queue::isfull() const
23 {
24
25 }
26 int Queue::queuecount() const
27 {
28
return items;
29 }
30 // Add item to queue
31 bool Queue::enqueue(const Item & item)
32 {
33
34
if (isfull())
return false;
35
36
if (add == NULL)
37
38
39
add->next = NULL;
40
items++;
41
42
43
else
44
45
46
return true;
47 }
48 // Place front item into item variable and remove from queue
49 bool Queue::dequeue(Item & item)
50 {
51
if (front == NULL)
52
return false;
53
54
items--;
55
56
57
58
if (items == 0)
59
rear = NULL;
60
return true;
61 }
62 // customer method
63 // when is the time at which the customer arrives
64 // the arrival time is set to when and the processing
65 // time set to a random value in the range 1 - 3
66 void Customer::set(long when)
67 {
68
processtime = std::rand() % 3 + 1;
69
arrive = when;
70 }
cp12ex6.cpp
1 #include <iostream>
2 #include <cstdlib> // for rand() and srand()
3 #include <ctime> // for time()
4 #include "queue.h"
5
6 const int MIN_PER_HR = 60;
7 bool newcustomer(double x); // is there a new customer?
8
9 int main()
10 {
11
using std::cin;
12
using std::cout;
13
using std::endl;
14
using std::ios_base;
15
// setting things up
16
17
18
19
int qs;
20
21
22
Queue line2(qs);
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int wait_time2 = 0;
38
39
double averagewait = 0;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// since values for processing times are random it will take a while, on
average 5-10 min of running this program, be patient
// sometimes it finds value very fast, again, because it's random
do
{
// reset all values for a new simulation loop
Item temp;
turnaways = 0; // turned away by full queue
customers = 0; // joined the queue
served = 0; // served during the simulation
sum_line = 0; // cumulative line length
wait_time1 = 0; // time until autoteller is free
wait_time2 = 0;
line_wait = 0; // cumulative time in line
55
56
perhour = std::rand() % 120 + 1; // 120 ppl max per hour for 2 lines with
1 min of waiting (average),
57
// higher numbers produce more randomness and longer time to find the
average
58
59
60
61
62
63
64
65
66
67
68
69
70
customers++;
71
72
73
74
75
else
76
77
78
79
80
}
}
if (wait_time1 <= 0 && !line1.isempty()) // for line 1
{
81
82
83
84
85
86
served++;
}
if (wait_time1 > 0)
87
wait_time1--;
88
sum_line += line1.queuecount();
89
90
91
92
93
94
95
96
97
98
99
10
served++;
}
if (wait_time2 > 0)
wait_time2--;
sum_line += line2.queuecount();
0
10
1
10
2
10
3
if (averagewait > 0.999 && averagewait < 1.03) // value between 0.999
10
and 1.03 will be considered 1 min
4
break;
10
5
}while (perhour > 0);
10
6
10
7
10
8
// reporting results
if (customers > 0)
{
11
0
cout << " customers served: " << served << endl;
11
1
cout.precision(2);
11
2
cout.setf(ios_base::fixed, ios_base::floatfield);
11
3
cout.setf(ios_base::showpoint);
cout << (double) sum_line / cyclelimit << endl;
11
4
11
5
11
6
11
7
11
8
11
9
cin.get();
cin.get();
12
0
12
1
12
2
12
3
12
4
return 0;
12
}
5
// x = average time, in minutes, between customers
12
6 // return value is true if customer shows up this minute
12 bool newcustomer(double x)
7
{
12
return (std::rand() * x / RAND_MAX < 1);
8
}
12
9
13
0
13
1
13
2
13
3