C++Primer Plus第6版第12章编程练习

第一题

对于下面类声明

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

给这个类提供实现,并编写一个使用所有成员函数的小程序

cow.h头文件

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#ifndef _COW_
#define _COW_

class Cow
{
	char name[20];
	char* hobby;
	double weight;
public:
	Cow()
	{
		name[0] = '\0';
		hobby = nullptr;
		weight = 0.0;
	}
	Cow(const char* nm, const char* ho, double wt)
	{
		strncpy(name, nm,20 - 1);
		name[20 - 1] = '\0';
		hobby = new char[strlen(ho) + 1];
		weight = wt;
		strcpy(hobby, ho);
	}
	Cow(const Cow& c)
	{
		strcpy(name, c.name);
		hobby = new char[strlen(c.hobby) + 1];
		weight = c.weight;
		strcpy(hobby, c.hobby);
	}
	~Cow()
	{
		delete[]hobby;
	}
	Cow& operator=(const Cow& c)
	{
		if (this == &c)
			return *this;

		delete[]hobby;			//可用于nullptr
		strcpy(name, c.name);
		if (c.hobby != nullptr)
		{
			hobby = new char[strlen(c.hobby) + 1];
			strcpy(hobby, c.hobby);
		}
		else
			hobby = nullptr;
		weight = c.weight;

		return*this;
	}

	void ShowCow()const
	{
		if (hobby == nullptr)
		{
			std::cout << "name:" << name << std::endl
					  << "hobby: " << "nullptr" << std::endl
					  << "weight: " << weight << std::endl;
			return;
		}

		std::cout << "name:" << name << std::endl
				  << "hobby: " << hobby << std::endl
				  << "weight: " << weight << std::endl;
	}
};
#endif

main.cpp

#define _CRT_SECURE_NO_WARNINGS  //vs里添加这个宏不然编译器认为strcpy不安全 记住头文件里函数的定义为内联函数
#include"cow.h"
int main()
{
	using std::cout;
	using std::endl;
	Cow c("lesson","hello",2.1);
	Cow d;

	cout << "c:\n";
	c.ShowCow();
	cout << "d:\n";
	d.ShowCow();

	d = c;
	cout << "d:\n";
	d.ShowCow();

	cout << "e:\n";
	Cow e;
	e.ShowCow();
	cout << "e:\n";
	e = Cow("order","hello",2.1);			//先调用复制函数 在调用赋值函数
	e.ShowCow();

	cout << "p:\n";
	Cow* p = nullptr;
	p = new Cow(e);
	p->ShowCow();
	delete p;

	return 0;
}

运行结果

 

第二题

通过完成下面的工作来改进String类声明(即将String1.h升级为String2.h)

a.对+运算符进行重载,使之可将两个字符串合并成1个。

b.提供一个stringlow()成员函数,将字符串所有的字母字符转换为小写(别忘了cctype系列字符函数)。

c.提供String()成员函数,将字符串中所有字母转换成大写。

d.提供一个这样的成员函数,它接受一个char参数,返回该字符在字符串中出现的次数。

略:

String2.h头文件

#ifndef STRING1_H_
#define STRING1_H_
#include<iostream>
using std::ostream;
using std::istream;

class String
{
private:
	char* str;							
	int len;							
	static int num_strings;				//对象数
	static const int CINLIM = 80;		//CIN输入限制
public:
	//构造函数和其他方法
	String(const char* s);				//构造 函数
	String();							//默认构造函数
	String(const String&);				//复制构造函数
	~String();
	int length()const { return len; }
	void stringlow();
	void stringup();
	int has(char);
	String& operator=(const String&);
	String& operator=(const char*);
	String& operator+(const String&);
	char& operator[](int i);
	const char& operator[](int i)const;
	friend bool operator<(const String& st, const String& st2);
	friend bool operator>(const String& st, const String& st2);
	friend bool operator==(const String& st, const String& st2);
	friend ostream& operator<<(ostream& os, const String& st);
	friend istream& operator>>(istream& is, String& st);
	friend String operator+(const char* str, const String& st2);
	//static function
	static int How_Many();

};
#endif

String.cpp

#define _CRT_SECURE_NO_WARNINGS 21

#include"string2.h"
#include<cstring>
#include<cctype>
using std::cin;
using std::cout;

int String::num_strings = 0;

int String::How_Many()
{
	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 = 4;
	str = new char[1];
	str[0] = '\0';
	num_strings++;
}

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

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

String& String::operator=(const String& st)
{
	if (this == &st)
		return *this;
	delete[]str;
	len = st.len;
	str = new char[len + 1];
	std::strcpy(str, st.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;
}

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

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

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

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.str < st1.str;
}

bool operator==(const String& st1, const String& st2)
{
	return (std::strcmp(st1.str, st2.str) == 0);
}

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

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

String operator+(const char* str, const String& st2)
{
	String temp;
	temp.len = strlen(str) + strlen(st2.str);
	temp.str = new char[temp.len + 1];
	strcpy(temp.str, str);
	strcat(temp.str, st2.str);

	return temp;
}

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

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

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

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

运行结果:

第3题

新编写程序清单10.7和程序清单10.8描述的Stock类,使之使用动态内存分配,而不是string类对象来存储股票名称。另外,使用重载的operator<<()定义代替show()成员函数。再使用程序清单10.9测试新的定义程序。

stock.h

#ifndef STOCK20_H_
#define STOCK20_H_
#include<string>
#include<iostream>

using std::ostream;
using std::istream;

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* str, 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);
	const Stock& topval(const Stock& s)const;
	friend ostream& operator<<(ostream& fout, const Stock& stocks);
};
#endif

 stock.cpp

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include"stock.h"

Stock::Stock()
{
	company = nullptr;
	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 set to 0.\n";
		shares = 0;
	}
	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)
{
	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();
}

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

ostream& operator<<(ostream& fout, const Stock& stocks)
{
	fout << "Company: " << stocks.company
		 << "shares: " << stocks.shares << '\n';
	fout << " share Price: $" << stocks.share_val;
	fout << " Total Worth: $" << stocks.total_val << '\n';

	return fout;
}

 stock_main.cpp

#include<iostream>
#include"stock.h"

const int STKS = 4;
int main()
{
	Stock stocks[STKS] =
	{
		Stock("NanoSmart",12,20.0),
		Stock("Boffo objects",200,2.0),
		Stock("Monolithic oblisks",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];
	const Stock* top = &stocks[0];
	for (st = 1; st < STKS; st++)
		top = &top->topval(stocks[st]);
	std::cout << "\nMost valuable holding:\n";
	std::cout << *top;
	return 0;
}

运行结果

第4题

请看下面程序清单10.10定义的Stack类的变量

正如私有成员表明的,这个类使用动态分配的数组来保存栈项。请重新编写方法,以适应这种新的表示法,并编写一个程序来演示所有的方法,包括复制构造函数和赋值运算符。

stack.h

#ifndef STACK_
#define _STACK_

typedef unsigned long Item;

class Stack
{
private:
	enum{MAX = 10};
	Item* pitems;
	int size;
	int top;
public:
	Stack(int n = MAX);
	Stack(const Stack& st);
	~Stack() { delete[]pitems; }
	bool isempty()const;
	bool isfull()const;
	bool push(const Item& item);
	bool pop(Item& item);
	Stack& operator=(const Stack& st);
};
#endif

 stack.cpp

#include"stack.h"
#include<iostream>
Stack::Stack(int n)
{
	pitems = new Item[n];
	size = top = 0;
}

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

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

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

bool Stack::push(const Item& item)
{
	if (isfull())
	{
		std::cout << "full\n";
		return false;
	}

	pitems[top++] = item;
	size += 1;
	return true;
}

bool Stack::pop(Item& item)
{
	if (isempty())
	{
		std::cout << "empty\n";
		return false;
	}

	item = pitems[--top];
	size -= 1;
	return true;
}

Stack& Stack::operator=(const Stack& st)
{
	for (int i = 0; i < st.size; i++)
	{
		pitems[i] = st.pitems[i];
	}
	
	size = st.size;
	top = st.top;
	return *this;
}

stack_main.cpp

#include<iostream>
#include"stack.h"

using std::cout;
using std::endl;
using std::cin;

int main()
{
	Stack stacks;
	Item number = 0;

	cout << "Enter a number:\n";
	
	while (cin >> number)
	{
		if (stacks.push(number))
			cout << "Successful onboarding\n";
	}

	Stack stack1 = stacks;						//复制构造函数
	if (stacks.pop(number))
		cout << "stacks: " << number << endl;

	if (stack1.pop(number))
		cout << "stacks1: " << number << endl;

	Stack stack2;
	stack2 = stack1;							//赋值

	stack2.pop(number);
	cout << "stacks2: " << number << endl;		//这里的number的值是上一个值

	return 0;
}

运行结果

 第5题

这里的意思是要你把书里的程序自己测试 我的客户数是19和18

第6题

Heather银行想知道,如果再开启一台ATM,情况将如何。请对模拟就行修改,以包含两个队列。假设当第一台ATM的排队人数少于第二台ATM时,客户将排在第一队,否则排在第二队。然后再找出要使平均等候时间为1分钟,每小时到达的客户数应为多少(注意,这是一个非线性问题,即将ATM数量加倍,并不能保证每小时处理客户数量也翻倍,并确保客户等候时间少于1分钟)?

queue.h

#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; }
	int ptime()const { return processtime; }
};

typedef Customer Item;

class Queue
{
private:
	//类作用域定义 节点是此类的本地嵌套结构定义
	struct Node { Item item; struct Node* next; };
	enum { Q_SIZE = 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 = Q_SIZE);
	~Queue();
	bool isempty()const;
	bool isfull()const;
	int queuecount()const;
	bool enqueue(const Item& item);	//将项目添加到末尾
	bool dequeue(Item& item);		//从前面删除项目


};
#endif

queue.cpp

#include"queue.h"
#include<cstdlib>
//队列方法
Queue::Queue(int qs) : qsize(qs)
{
	front = rear = nullptr;
	items = 0;
}

Queue::~Queue()
{
	Node* temp;
	while (front != nullptr)
	{
		temp = front;
		front = front->next;
		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 (isfull())
		return false;

	Node* add = new Node;			//创建节点
	add->item = item;
	add->next = nullptr;
	items++;
	if (front == nullptr)
		front = add;
	else
		rear->next = add;

	rear = add;
	return true;
}

bool Queue::dequeue(Item& item)
{
	if (front == nullptr)
		return false;

	item = front->item;
	items--;
	Node* temp = front;
	front = front->next;
	delete temp;

	if (items == 0)
		rear = nullptr;

	return true;
}

void Customer::set(long when)
{
	processtime = std::rand() % 3 + 1; //处理客户的时候 0-3之间的值
	arrive = when;					   //客户到达的时间
}

queue_main.cpp

#include<iostream>
#include<cstdlib>
#include<ctime>
#include"queue.h"
const int MIN_PER_HR = 60;

bool newcustomer(double x);

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	using std::ios_base;
	//setting things up
	std::srand(std::time(0));

	cout << "Case Study: Bank of Heather Automatic Teller\n";
	cout << "Enter maximum size of queue: ";					//输入队列的最大大小
	int qs;
	cin >> qs;

	Queue line1(qs);											//第一队
	Queue line2(qs);											//第二队

	cout << "Enter the number of simulation hours: ";			//输入模拟小时数
	int hours;
	cin >> hours;
	//模拟将每分钟运行 1 个周期
	long cyclelimit = MIN_PER_HR * hours;

	cout << "Enter the average number of customers per hour: ";	//输入每小时的平均客户数
	double perhour;												//每小时平均 # 到达次数
	cin >> perhour;												
	double min_per_cust;										//到达之间的平均时间
	min_per_cust = MIN_PER_HR / perhour;						//几分钟到达一个人

	Item temp;													//新客户数据
	//第一队
	long turnaways1 = 0;										//被满队列拒之门外
	long customers1 = 0;										//加入队列
	long served = 0;											//在模拟期间服务
	long sum_line1 = 0;											//累积线长度
	int wait_time1 = 0;
	long line_wait1 = 0;										//累计排队时间

	//第二队
	long wait_time2 = 0;

	for (int cycle = 0; cycle < cyclelimit; cycle++)
	{
		if (newcustomer(min_per_cust))
		{
			if (line1.queuecount() < line2.queuecount())
			{
				if (line1.isfull())									//检查是否已满
					turnaways1++;
				else
				{
					customers1++;									
					temp.set(cycle);								//周期 = 到达时间
					line1.enqueue(temp);
				}
			}
			else
			{
				if (line2.isfull())
					turnaways1++;
				else
				{
					customers1++;
					temp.set(cycle);
					line2.enqueue(temp);
				}

			}
		}

		if (wait_time1 <= 0 && !line1.isempty())
		{
			line1.dequeue(temp);								//参加下一位客户
			wait_time1 = temp.ptime();							//wait_time分钟 得到客户处理的时间
			line_wait1 += cycle - temp.when();					//累计排队时间
			served++;											//模拟期间服务的次数
		}

		if (wait_time2 <= 0 && !line2.isempty())
		{
			line2.dequeue(temp);
			wait_time2 = temp.ptime();
			line_wait1 += cycle - temp.when();
			served++;
		}

		if (wait_time1 > 0)
			wait_time1--;										//wait_time==0表示客户已经处理完成

		if (wait_time2 > 0)
			wait_time2--;

		sum_line1 += line1.queuecount();
		sum_line1 += line2.queuecount();
	}
	if (customers1 > 0)
	{
		cout << "customers accepted1: " << customers1 << endl;
		cout << " customers served1: " << served << endl;
		cout << " turnaways1: " << turnaways1 << endl;
		cout << "average queue size1: ";
		cout.precision(2);
		cout.setf(ios_base::fixed, ios_base::floatfield);
		cout << (double)sum_line1 / cyclelimit << endl;
		cout << " average wait time1: "
			<< (double)line_wait1 / served << " minutes\n";
	}
	else
		cout << "No customers!\n";

	cout << "Done!\n";

	return 0;
}
//x = 客户之间的平均时间(以分钟为单位),如果客户显示分钟,则返回值为 true
bool newcustomer(double x)
{
	return (std::rand() * x / RAND_MAX < 1);		//0到x之间 每隔x次,这个值就会小于1 理解:小于1的话就为到来一个人
}

运行结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值