《C++編程思想》 第十五章 模板和包容器類 (原書代碼+習題+解答)

一.相關代碼

1.

 

/*STACKT.h*/
#ifndef STACKT_H_
#define STACKT_H_
template<class T> class stacktIter;

template<class T>
class stackt
{
	enum{ ssize = 100 };
	T stack[ssize];
	int top;
public:
	stackt() : top(0)
	{
		stack[top] = 0;
	}
	void push(const T& i)
	{
		if(top < ssize)
		{
			stack[top++] = i;
		}
	}
	T pop()
	{
		return stack[top > 0 ? --top : top];
	}
	friend class stacktIter<T>;
};

template<class T>
class stacktIter
{
	stackt<T>& S;
	int index;
public:
	stacktIter(stackt<T>& is) : S(is), index(0) {}
	T& operator++() 
	{
		if(index < S.top - 1)
		{
			index++;
		}
		return S.stack[index];
	}
	T& operator++(int)
	{
		int returnval = S.stack[index];
		if(index < S.top - 1)
		{
			index++;
		}
		return returnval;
	}
};
#endif

 

/*STACKT.cpp*/
#include <assert.h>
#include <iostream.h>
#include "stackt.h"

int fibonacci(int N)
{
	const sz = 100;
	assert(N < sz);
	static F[sz];
	F[0] = F[1] = 1;
	for(int i = 0; i < sz; ++i)
	{
		if(F[i] == 0)
		{
			break;
		}
	}
	while(i <= N)
	{
		F[i] = F[i-1] + F[i-2];
		i++;
	}
	return F[N];
}

int main()
{
	stackt<int> is;
	for(int i = 0; i < 20; ++i)
	{
		is.push(fibonacci(i));
	}
	stacktIter<int> it(is);
	for(int j = 0; j < 20; ++j)
	{
		cout << it++ << endl;
	}
	for (int k = 0; k < 20; ++k)
	{
		cout << is.pop() << endl;
	}
	
	return 0;
}


2.

 

 

/*TSTASH.h*/
#ifndef TSTASH_H_
#define TSTASH_H_
#include <stdlib.h>
#include "E:\VC++\7_31_2\allege.h"

enum owns{ no = 0, yes = 1, Default};

template<class Type, int sz> class tstashIter;

template<class Type, int chunksize = 20>
class tstash
{
	int quantity;
	int next;
	owns own;//own標誌指明瞭包容器是否以缺省方式擁有它所包容的對象
	void inflate(int increase = chunksize);
protected:
	Type** storage;
public:
	tstash(owns owns = yes);
	~tstash();
	int Owns() const
	{
		return own;
	}
	void Owns(owns newOwns)
	{
		own = newOwns;
	}
	int add(Type* element);
	int remove(int index, owns d = Default);
	Type* operator[](int index);
	int count() const
	{
		return next;
	}
	friend class tstashIter<Type, chunksize>;
};

template<class Type, int sz = 20> 
class tstashIter
{
	tstash<Type, sz>& ts;
	int index;
public:
	tstashIter(tstash<Type, sz>& TS) : ts(TS), index(0) {}
	tstashIter(const tstashIter& rv) : ts(rv.ts), index(rv.index) {}
	void forward(int amount)
	{
		index += amount;
		if(index >= ts.next)
		{
			index = ts.next - 1;
		}
	}
	void backward(int amount)
	{
		index -= amount;
		if(index < 0)
		{
			index = 0;
		}
	}
	int operator++()
	{
		if(++index >= ts.next)
		{
			return 0;
		}
		return 1;
	}
	int operator++(int)
	{
		return operator++();
	}
	int operator--()
	{
		if(--index < 0)
		{
			return 0;
		}
		return 1;
	}
	int operator--(int)
	{
		return operator--();
	}
	operator int()
	{
		return index >= 0 && index < ts.next;
	}
	Type* operator->()
	{
		Type* t = ts.storage[index];
		if(t)
		{
			return t;
		}
		allege(0, "tstashIter::operator->return 0");
		return 0;
	}
	int remove(owns d = Default)
	{
		return ts.remove(index, d);
	}
};

template<class Type, int sz>
tstash<Type, sz>::tstash(owns Owns) : own(Owns)
{
	quantity = 0;
	storage = 0;
	next = 0;
}
template<class Type, int sz>
tstash<Type, sz>::~tstash()
{
	if(!storage)
	{
		return;
	}
	if(own == yes)
	{
		for(int i = 0; i < count(); i++)
		{
		//	delete storage[i];
		}
	}
	free(storage);
}

template<class Type, int sz>
int tstash<Type, sz>::add(Type* element)
{
	if(next >= quantity)
	{
		inflate();
	}
	storage[next++] = element;
	return(next - 1);
}

template<class Type, int sz>
int tstash<Type, sz>::remove(int index, owns d)
{
	if(index >= next || index < 0)
	{
		return 0;
	}
	switch(d)
	{
	case Default:
		if(own != yes)
		{
			break;
		}
	case yes:
		delete storage[index];
	case no:
		storage[index] = 0;
	}
	return 1;
}

template<class Type, int sz>
Type* tstash<Type, sz>::operator[](int index)
{
	assert(index >= 0 && index < next);
	return storage[index];
}

template<class Type, int sz>
void tstash<Type, sz>::inflate(int increase)
{
	void* v = realloc(storage, (quantity+increase)*sizeof(Type*));
	allegemem(v);
	storage = (Type**)v;
	quantity += increase;
}

#endif

 

/*創建和檢測兩個不同的 tstash對象,一個屬於新類Int並在它的析構函數和構
造函數中給出報告,而另一個含有屬於第 12章的String類的對象*/
/*TSTEST.cpp*/
#include <fstream.h>
#include "E:\VC++\7_31_2\allege.h"
#include "tstash.h"
#include "E:\VC++\8_4_1\strings.h"

const bufsize = 80;
ofstream out("tstash.out");

class Int
{
	int i;
public:
	Int(int I = 0) :i(I)
	{
		out << ">" << i << endl;
	}
	~Int()
	{
		out << "~" << i << endl;
	}
	operator int() const
	{
		return i;
	}
	friend ostream&
		operator<<(ostream& os, const Int& x)
	{
		return os << x.i ;
	}
};

int main()
{
	tstash<Int> intStash;
	for(int i = 0; i < 30; ++i)
	{
		intStash.add(new Int(i));
	}
	tstashIter<Int> Intit(intStash);
	Intit.forward(5);
	for(int j = 0; j < 20; ++j, Intit++)
	{
		Intit.remove();
	}
	for(int k = 0; k < intStash.count(); ++k)
	{
		if(intStash[k])
		{
			out << *intStash[k] << endl;
		}
	}

	ifstream file("tstash.cpp");
	allegefile(file);
	char buf[bufsize];

	tstash<String> stringStash;
	while(file.getline(buf, bufsize))
	{
		stringStash.add(makeString(buf));
	}
	for(int u = 0; u < stringStash.count(); ++u)
	{
		if(stringStash[u])
		{
			out << *stringStash[u] << endl;
		}
	}
	tstashIter<String> it(stringStash);
	j = 25;
	it.forward(j);
	while(it)
	{
		out << j++ << ": " << it->str() << endl;
		it++;
	}

	return 0;
}


3.

 

 

#ifndef TSTACK_H_
#define TSTACK_H_

template<class T> class tstackIterator;

template<class T>
class tstack
{
	struct link
	{
		T* data;
		link* next;
		link(T* Data, link* Next)
		{
			data = Data;
			next = Next;
		}
	}*head;
	int owns;
public:
	tstack(int Owns = 1) : head(0), owns(Owns) {}
	~tstack();
	void push(T* Data)
	{
		head = new link(Data, head);
	}
	T* peek() const
	{
		return head->data;
	}
	T* pop();
	int Owns() const
	{
		return owns;
	}
	void Owns(int newownership)
	{
		owns = newownership;
	}
	friend class tstackIterator<T>;
};

template<class T>
T* tstack<T>::pop()
{
	if(head == 0)
	{
		return 0;
	}
	T* result = head->data;
	link* oldHead = head;
	head = head->next;
	delete oldHead;
	return result;
}

template<class T>
tstack<T>::~tstack()
{
	link* cursor = head;
	while(head)
	{
		cursor = cursor->next;
		if(owns)
		{
			delete head->data;
		}
		delete head;
		head = cursor;
	}
}

template<class T>
class tstackIterator
{
	tstack<T>::link* p;
public:
	tstackIterator(const tstack<T>& t1) 
		: p(t1.head) {}
	tstackIterator(const tstackIterator& t1) 
		: p(t1.p) {}
	int operator++()
	{
		if(p->next)
		{
			p = p->next;
		}
		else
		{
			p = 0;
		}
		return int(p);
	}
	int operator++(int)
	{
		return operator++();
	}
	T* operator->() const
	{
		if(!p)
		{
			return 0;
		}
		return p->data;
	}
	T* current() const
	{
		if(!p)
		{
			return 0;
		}
		return p->data;
	}
	operator int() const
		//operator int()指出,是否我們已處在表的尾部和是否允許在條件語句中使用該循環子
	{
		return p ? 1 : 0 ;
	}
};

#endif

 

/*TSTKTST.cpp*/
#include "E:\VC++\8_4_1\strings.h"
#include "E:\VC++\7_31_2\allege.h"
#include "tstack.h"
#include <fstream.h>

int main()
{
	ifstream file("tstktst.cpp");
	allegefile(file);
	const bufsize = 100;
	char buf[bufsize];
	tstack<String> textlines;
	while(file.getline(buf, bufsize))
	{
		textlines.push(String::make(buf));
	}
	int i = 0;
	tstackIterator<String> it(textlines);
	tstackIterator<String>* it2 = 0;
	while(it)
	{
		cout << *it.current() << endl;
		it++;
		if(++i == 10)
		{
			it2 = new tstackIterator<String>(it);
		}
	}
	cout << *(it2->current()) << endl;
	delete it2;

	return 0;
}


4.

 

 

/*SSTRING.h*/
#ifndef SSTRING_H_
#define SSTRING_H_
#include <string.h>
#include <iostream.h>

template<int bsz = 0>
class SString
{
	char buf[bsz + 1];
	char* s;
public:
	SString(const char* S = "") : s(buf)
	{
		if(!bsz)
		{
			s = new char[strlen(S) + 1];
			strcpy(s, S);
		}
		else
		{
			buf[bsz] = 0;
			strncpy(s, S, bsz);
		}
	}
	SString(const SString& rv) : s(buf)
	{
		if(!bsz)
		{
			s = new char[strlen(rv.s) + 1];
			strcpy(s, rv.s);
		}
		else
		{
			buf[bsz] = 0;
			strncpy(s, rv.s, bsz);
		}
	}
	SString& operator=(const SString& rv)
	{
		if(&rv == this)
		{
			return *this;
		}
		if(!bsz)
		{
			delete s;
			s = new char[strlen(rv.s) + 1];
		}
		strcpy(s, rv.s);
		return *this;
	}
	~SString()
	{
		if(!bsz)
		{
			delete []s;
		}
	}
	int operator==(const SString& rv) const
	{
		return !stricmp(s, rv.s);
		//字符串的比較運算符
	}
	int operator!=(const SString& rv) const
	{
		return stricmp(s, rv.s);
	}
	int operator>(const SString& rv) const
	{
		return stricmp(s, rv.s) > 0;
	}
	int operator<(const SString& rv) const
	{
		return stricmp(s, rv.s) < 0;
	}
	char* str() const
	{
		return s;
	}
	friend ostream&
		operator<<(ostream& os,
		           const SString<bsz>& S)
	{
		return os << S.s;
	}
};

typedef SString<> Hstring;
//通過使用typedef Hstring,我們可以得到一個普通的基於堆的字符串(使用typedef而不是
//使用繼承是因爲繼承需要重新創建構造函數和重載符 =)。
#endif

 

 

5.

 

/*INTEGER.cpp*/
#ifndef INREGER_H_
#define INTEGER_H_
#include <iostream.h>

class integer
{
	int i;
public:
	integer(int ii = 0) : i(ii) {}
	operator int() const
	{
		return i;
	}
	const integer& operator++()
	{
		i++;
		return *this;
	}
	const integer operator++(int)
	{
		integer returnval(i);
		i++;
		return returnval;
	}
	integer& operator+=(const integer& x)
	{
		i += x.i;
		return *this;
	}
	friend ostream&
		operator<<(ostream& os, const integer& x)
	{
		return os << x.i;
	}
};

#endif

 

 

 

 

 

6.

 

/*“無窮”向量
下面的向量類僅僅擁有指針。它從不需要調整大小:我們可以簡單地對任何位置進行索引,
這些位置可魔術般地變化,而無需提前通知向量類。 operator[]能返回一個指針的引用,所以可
以出現在=的左邊(它可以是一個左值,也可以是一個右值)。向量類僅僅與指針打交道,所以
它工作的對象沒有類型限制,對於類型的行爲沒有事先假定的必要。*/
/*VECTOR.cpp*/
#ifndef VECTOR_H_
#define VECTOR_H_
#include <stdlib.h>
#include "E:\VC++\7_31_2\allege.h"

template<class T>
class vector
{
	T** pos;
	int pos_sz;
	T** neg;
	int neg_sz;
	int owns;
	enum
	{
		chunk = 20,
		esz = sizeof(T*),
	};
	void expand(T**& array, int& size, int index);
public:
	vector(int Owns = 1);
	~vector();
	T*& operator[](int index);
	int Owns() const
	{
		return owns;
	}
	void Owns(int newOwns)
	{
		owns = newOwns;
	}
};

template<class T>
vector<T>::vector(int Owns)
: pos(0), pos_sz(0),
  neg(0), neg_sz(0),
  owns(Owns){}

template<class T>
vector<T>::~vector()
{
	if(owns)
	{
		for(int i = 0; i < pos_sz; ++i)
		{
			delete pos[i];
		}
	}
	free(pos);
	if(owns)
	{
		for(int j = 0; j < neg_sz; ++j)
		{
			delete neg[j];
		}
	}
	free(neg);
}

template<class T>
T*& vector<T>::operator[](int index)
{
	if(index < 0)
	{
		index *= -1;
		if(index >= neg_sz)
		{
			expand(neg, neg_sz, index);
		}
		return neg[index];
	}
	else
	{
		if(index >= pos_sz)
		{
			expand(pos, pos_sz, index);
		}
		return pos[index];
	}
}

template<class T> void
vector<T>::expand(T**& array, int& size,
				  int index)
				  //expand()採用的參數是引用T**&而不是一個指針
{
	const newsize = index +chunk;
	const increment = newsize - size;
	void* v = realloc(array, newsize * esz);
	allegemem(v);
	array = (T**)v;
	memset(&array[size], 0, increment * esz);
	size = index + chunk;
}
#endif;

 

/*VECTOR.cpp*/
#include <fstream.h>
#include "E:\VC++\7_31_2\allege.h"
#include "vector.h"
#include "E:\VC++\8_7_4\sstring.h"
typedef SString<40> String;

int main()
{
	ifstream source("vector.cpp");
	allegefile(source);
	const bsz = 255;
	char buf[bsz];
	vector<String> words;
	int i = 0;
	while(source.getline(buf, bsz))
	{
		char* s = strtok(buf, "\t");
		//標準C函數strtok(),它取字符緩衝區的起始地址(第一個參數)和尋找定界符(第二個參數)
		while(s)
		{
			words[i++] = new String(s);
			s = strtok(0, "\t");
		}
		words[i++] = new String("\n");
	}
	for(int j = 0; words[j]; ++j)
	{
		cout << *words[j] << ' ';
	}
}

 

 

 

 

 

7.

 

/*SET.cpp*/
#ifndef SET_H_
#define SET_H_
#include "E:\VC++\8_7_6\vector.h"
#include <assert.h>

template<class Type>
class set
{
	vector<Type> elem;
	int max;
	int lastindex;
	int within(const Type& e)
	{
		for(lastindex = 0; lastindex < max; ++lastindex)
		{
			if(elem[lastindex]->operator == (e))
			{
				return lastindex;
			}
		}
		return -1;
	}
	void operator=(set&);
	set(set&);
public:
	set() : max(0), lastindex(0) {}
	void add(const Type&);
	int contains(const Type&);
	int index(const Type& e);
	Type& operator[] (int index)
	{
		assert(index >= 0 && index < max);
		return *elem[index];
	}
	int length() const
		//length()告訴我們集合中有多少個元素
	{
		return max;
	}
};

template<class Type> void
set<Type>::add(const Type& e)
//add()在檢測確定一個新元素不在集合後,將其追加入集合中
{
	if(!contains(e))
	{
		elem[max] = new Type(e);
		max++;
	}
}

template<class Type> int
set<Type>::contains(const Type& e)
//contains()告訴我們對象是否已存在於集合之中
{
	return within(e) != -1;
}

template<class Type> int
set<Type>::index(const Type& e)
//index()告訴我們對象在集合之中的位置
{
	if(elem[lastindex]->operator != (e))
	{
		int ind = within(e);
		assert(ind != -1);
	}
	return lastindex;
}

#endif

 

/*SETTEST.cpp*/
#include <fstream.h>
#include "set.h"
#include "E:\VC++\7_31_2\allege.h"
#include "E:\VC++\8_7_4\sstring.h"

const char* delimiters = 
" \t;()\''<>:{}[]+-=&*#.,/\\"
"0123456789";

typedef SString<40> String;

int main(int argc, char* argv[])
{
	allege(argc == 2, "need file argument");
	ifstream in(argv[1]);
	allegefile(in);
	ofstream out("settest.out");
	set<String> concordance;
	const sz = 255;
	char buf[sz];
	while(in.getline(buf, sz))
	{
		char* s = strtok(buf, delimiters);//定界符
		while(s)
		{
			concordance.add(s);
			s = strtok(0, delimiters);
		}
	}
	for(int i = 0; i < concordance.length(); ++i)
	{
		out << concordance[i] << endl;
	}

	return 0;
}


8.

 

 

/*ASSOC.h*/
#ifndef ASSOC_H_
#define ASSOC_H_
#include "E:\VC++\8_7_7\set.h"
#include <assert.h>

template<class In, class Out>
class assoc_array
{
	set<In> inVal;
	vector<Out> outVal;
	int max;
	void operator=(assoc_array&);
	assoc_array(assoc_array&);
public:
	assoc_array() : max(0) {}
	Out& operator[] (const In&);
	int length() const 
	{
		return max;
	}
	In& in_value(int i)
	{
		assert(i >= 0 && i < max);
		return inVal[i];
	}
	Out& out_value(int i)
	{
		assert(i >= 0 && i < max);
		return *outVal[i];
	}
};

template<class In, class Out> Out&
assoc_array<In,Out>::operator[](const In& in)
{
	if(!inVal.contains(in))
	{
		inVal.add(in);
		outVal[max] = new Out;
		max++;
	}
	int x = inVal.index(in);
	return *outVal[inVal.index(in)];
}

#endif

 

/*ASSOC.cpp*/
#include "assoc.h"
#include "E:\VC++\8_7_4\sstring.h"
#include "E:\VC++\8_7_5\integer.h"
#include "E:\VC++\7_31_2\allege.h"
#include <fstream.h>
#include <ctype.h>

int main()
{
	const char* delimiters =
		"\t;()\''<>;{}[]+-=&*#.,/\\";
	assoc_array<SString<80>, integer> strcount;
	ifstream source("assoc.cpp");
	allegefile(source);
	ofstream out("assoc.out");
	allegefile(out);
	const bsz = 255;
	char buf[bsz];
	while(source.getline(buf, bsz))
	{
		char* s = strtok(buf, delimiters);
		while(s)
		{
			strcount[s]++;
			s = strtok(0, delimiters);
		}
	}
	for(int i = 0; i < strcount.length(); ++i)
	{
		out << strcount.in_value(i) << " : "
			<< strcount.out_value(i) << endl;
	}
	assoc_array<SString<>, integer> shoplist;
	ifstream list("shoplist.txt");
	allegefile(list);
	ofstream olist("shoplist.out");
	allegefile(olist);
	while(list.getline(buf, bsz))
	{
		int i = strlen(buf) - 1;
		while(isspace(buf[i]))
		{
			i--;
		}
		while(!isspace(buf[i]))
		{
			i--;
		}
		int count = atoi(&buf[i+1]);
		while(isspace(buf[i]))
		{
			i--;
		}
		buf[i+1] = 0;
		i = 0;
		while(isspace(buf[i]))
		{
			i++;
		}
		shoplist[&buf[i]] += count;
	}
	
	for(int j = 0; j < shoplist.length(); ++j)
	{
		olist << shoplist.in_value(j) << " : "
			<< shoplist.out_value(j) << endl;
	}

	return 0;
}


9.

 

 

/*SORTED.h*/
#ifndef SORTED_H_
#define SORTED_H_
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "E:\VC++\8_7_2\tstash.h"
#include "E:\VC++\8_7_7\set.h"

template<class T>
class sorted : public tstash<T>
{
	void bubblesort();
public:
	int add(T* element)
	{
		tstash<T>::add(element);
		bubblesort();
		return 0;
	}
};

template<class T>
void sorted<T>::bubblesort()
{
	for(int i = count(); i > 0; --i)
	{
		for(int j = 1; j > i; ++j)
		{
			if(*storage[j - 1] > *storage[j])
			{
				T* t = storage[j - 1];
				storage[j - 1] = storage[j];
				storage[j] = t;
			}
		}
	}
}

template<class T>
class sortedSet : public set<T>
{
	sorted<T> Sorted;
public:
	void add(T& e)
	{
		if(contains(e))
		{
			return;
		}
		set<T>::add(e);
		Sorted.add(new T(e));
	}
	T& operator[] (int index)
	{
		assert(index >= 0 && index < length());
		assert(Sorted[index]);
		return *Sorted[index];
	}
	int length()
	{
		return Sorted.count();
	}
};

template<int upper_bound>
class urand
{
	int map[upper_bound];
	int recycle;
public:
	urand(int Recycle = 0);
	int operator()();
};

template<int upper_bound>
urand<upper_bound>::urand(int Recycle)
: recycle(Recycle)
{
	memset(map, 0, upper_bound * sizeof(int));
	time_t t;
	srand((unsigned)time(&t));
}

template<int upper_bound>
int urand<upper_bound>::operator()()
{
	if(!memchr(map, 0, upper_bound))
	{
		if(recycle)
		{
			memset(map, 0, sizeof(map) * sizeof(int));
		}
		else
		{
			return -1;
		}
	}
	int newval;
	while(map[newval = rand() % upper_bound]);
	map[newval]++;
	return newval;
}

#endif

 

/*SORTED.cpp*/
#include "sorted.h"
#include "E:\VC++\8_7_5\integer.h"
#include "E:\VC++\8_7_4\sstring.h"
typedef SString<40> String;

char* words[] = 
{
	"is", "running", "big", "dog", "a",
};
const wordsz = sizeof words / sizeof *words;

int main()
{
	sorted<String> ss;
	for(int i = 0; i < wordsz; ++i)
	{
		ss.add(new String(words[i]));
	}
	for(int j = 0; j < ss.count(); ++j)
	{
		cout << ss[j]->str() << endl;
	}
	sorted<integer> is;
	urand<47> rand1;
	for(int k = 0; k < 15; ++k)
	{
		is.add(new integer(rand1()));
	}
	for(int l = 0; l < is.count(); ++l)
	{
		cout << *is[l] << endl;
	}

	return 0;
}

 

 

 

10.

 

/*NOBLOAT.h*/
#ifndef NOBLOAT_H_
#define NOBLOAT_H_
#include "E:\VC++\8_4_3\stackl1.h"

template<class T>
class nbstack : public stack
{
public:
	void push(T* str)
	{
		stack::push(str);
	}
	T* peek() const
	{
		return (T*)stack::peek();
	}
	T* pop()
	{
		return (T*)stack::pop();
	}
	~nbstack();
};

template<class T>
nbstack<T>::~nbstack()
{
	T* top = pop();
	while(top)
	{
		delete top;
		top = pop();
	}
}
#endif

 


11.

 

 

 

/*GETMEM.h*/
#ifndef GETMEM_H_
#define GETMEM_H_
#include <stdlib.h>
#include <string.h>
#include "E:\VC++\7_31_2\allege.h"

template<class T>
void getmem(T*& oldmem, int elems)
{
	typedef int cntr;
	const int csz = sizeof(cntr);
	const int Tsz = sizeof(T);
	if(elems == 0)
	{
		free(&(((cntr*)oldmem)[-1]));
		return;
	}
	T* p = oldmem;
	cntr oldcount = 0;
	if(p)
	{
		(cntr*)p--;
		oldcount = *(cntr*)p;
	}
	T* m = (T*)realloc(p, elems*Tsz + csz);
	allegemem(m);
	*((cntr*)m) = elems;
	const cntr increment = elems - oldcount;
	if(increment > 0)
	{
		long startadr = (long)&(m[oldcount]);
		startadr += csz;
		memset((void*)startadr, 0, increment*Tsz);
	}
	oldmem = (T*)&(((cntr*)m)[1]);
}

template<class T>
inline void freemem(T * m)
{
	getmem(m, 0);
}

#endif

 

</pre><pre name="code" class="cpp">/*GETMEM.cpp*/
#include "getmem.h"
#include <iostream.h>
int main()
{
	int* p = 0;
	getmem(p, 10);
	for(int i = 0; i < 10; ++i)
	{
		cout << p[i] << ' ';
		p[i] = i;
	}
	cout << '\n';
	getmem(p, 20);
	for(int j = 0; j < 20; ++j)
	{
		cout << p[j] << ' ';
		p[j] = j;
	}
	cout << '\n';
	getmem(p, 25);
	for(int k = 0; k ,25; ++k)
	{
		cout << p[k] << ' ';
	}
	freemem(p);
	cout << '\n';

	float* f = 0;
	getmem(f, 3);
	for(int u = 0; u < 3 ;++u)
	{
		cout << f[u] << ' ';
		f[u] = u + 3.14159;
	}
	cout << '\n';
	getmem(f, 6);
	for(int v = 0; v < 6; ++v)
	{
		cout << f[v] << ' ';
	}
	freemem(f);

	return 0;
}


12.

 

 

/*ISTACK.cpp*/
#include <iostream.h>
#include <assert.h>

class istack
{
	enum{ ssize = 100 };
	int stack[ssize];
	int top;
public:
	istack() : top(0)
	{
		stack[top] = 0;
	}
	void push(int i)
	{
		if(top < ssize)
		{
			stack[top++] = i;
		}
	}
	int pop()
	{
		return stack[top > 0 ? --top : top];
	}
	friend class istackIter;
};

class istackIter
{
	istack& S;
	int index;
public:
	istackIter(istack& is) : S(is), index(0) {}
	int operator++() 
	{
		if(index < S.top - 1)
		{
			index++;
		}
		return S.stack[index];
	}
	int operator++(int)
	{
		int returnval = S.stack[index];
		if(index < S.top - 1)
		{
			index++;
		}
		return returnval;
	}
};

int fibonacci(int N)
{
	const sz = 100;
	assert(N < sz);
	static F[sz];
	F[0] = F[1] = 1;
	for(int i = 0; i < sz; ++i)
	{
		if(F[i] == 0)
		{
			break;
		}
	}
	while(i <= N)
	{
		F[i] = F[i-1] + F[i-2];
		i++;
	}
	return F[N];
}

int main()
{
	istack is;
	for(int i = 0; i < 20; ++i)
	{
		is.push(fibonacci(i));
	}
	istackIter it(is);
	for(int j = 0; j < 20; ++j)
	{
		cout << it++ << endl;
	}
	for (int k = 0; k < 20; ++k)
	{
		cout << is.pop() << endl;
	}
	
	return 0;
}

 

 

 

13.

 

/*模板語法*/
/*STEMP.cpp*/
#include <iostream.h>
#include <assert.h>

template<class T>
class array
{
	enum{ size = 100 };
	T A[size];
public:
	T& operator[](int index)
	{
		assert(index >= 0 && index < size);
		return A[index];
	}
};

int main()
{
	array<int> ia;
	array<float> fa;
	for(int i = 0; i < 20; ++i)
	{
		ia[i] = i * i;
		fa[i] = float(i) * 1.414;
	}
	for(int j = 0; j < 20; ++j)
	{
		cout << j << ": " << ia[j]
			 << ", " << fa[j] << endl;
	}
	
	return 0;
}

 


14.

 

 

 

/*說明非內聯成員函數的定義*/
/*STEMP2.cpp*/
#include <iostream.h>
#include <assert.h>

template<class T>
class array
{
	enum{ size = 100 };
	T A[size];
public:
	T& operator[](int index);
};

template<class T>
T& array<T>::operator[](int index)
{
	assert(index >= 0 && index < size);
	return A[index];
}

int main()
{
	array<float> fa;
	fa[0] = 1.414;
	
	return 0;
}


15.

 

 

/*模板中的常量
模板參數並不侷限於有類定義的類型,可以使用編譯器內置類型。這些參數值在模板特定
實例時變成編譯期間常量。我們甚至可以對這些參數使用缺省值*/
/*MBLOCK.cpp*/
/*類holder和mblock極爲相似,但是在 holder中有一個指向mblock的指針,而不是含有
mblock類型的嵌入式對象。該指針並不在 holder的構造函數中初始化,其初始化過程被安排在
第一次訪問的時候。 如果我們正在創建大量的對象,卻又不立即全部訪問它們,可以用這種
技術,以節省存儲空間。*/
#include <assert.h>
#include <iostream.h>

template<class T, int size = 100>
class mblock
{
	T array[size];
public:
	T& operator[](int index)
	{
		assert(index >= 0 && index < size);
		return array[index];
	}
};

class number
{
	float f;
public:
	number(float F = 0.0f) : f(F) {}
	number& operator=(const number& n)
	{
		f = n.f;
		return *this;
	}
	operator float() const
	{
		return f;
	}
	friend ostream&
		operator<<(ostream& os, const number& x)
	{
		return os << x.f;
	}
};

template<class T, int sz = 20>
class holder
{
	mblock<T, sz>* np;
public:
	holder() : np(0) {}
	number& operator[](int i)
	{
		assert(i >= 0 && i < sz);
		if(!np)
		{
			np = new mblock<T, sz>;
		}
		return np->operator[](i);
	}
};

int main()
{
	holder<number, 20> H;
	for(int i = 0; i < 20; ++i) 
	{
		H[i] = i;
	}
	for(int j = 0; j < 20; ++j)
	{
		cout << H[j] << endl;
	}

	return 0;
}

 

 

 

 

 

16.

 

/*垃圾回收模擬*/
/*RECYCLE.cpp*/
#include <fstream.h>
#include <stdlib.h>
#include <time.h>
#include "E:\VC++\8_7_3\tstack.h"
ofstream out("recycle.out");

enum type{ Aluminum, Paper, Glass };

class trash
{
	float Weight;
public:
	trash(float Wt) : Weight(Wt) {}
	virtual type trashType() const = 0;
	virtual const char* name() const = 0;
	virtual float value() const = 0;
	float weight() const 
	{
		return Weight;
	}
	virtual ~trash() {}
};

class aluminum : public trash
{
	static float val;
public:
	aluminum(float Wt) : trash(Wt) {}
	type trashType() const 
	{
		return Aluminum;
	}
	virtual const char* name() const
	{
		return "aluminum";
	}
	float value() const
	{
		return val;
	}
	static void value(int newval)
	{
		val = newval;
	}
};

float aluminum::val = 1.67;

class paper : public trash
{
	static float val;
public:
	paper(float Wt) : trash(Wt) {}
	type trashType() const
	{
		return Paper;
	}
	virtual const char* name() const
	{
		return "paper";
	}
	float value() const
	{
		return val;
	}
	static void value(int newval)
	{
		val = newval;
	}
};

float paper::val = 0.10;

class glass : public trash
{
	static float val;
public:
	glass(float Wt) : trash(Wt) {}
	type trashType() const 
	{
		return Glass;
	}
	virtual const char* name() const
	{
		return "glass";
	}
	float value() const
	{
		return val;
	}
	static void value(int newval)
	{
		val = newval;
	}
};

float glass::val = 0.23;

void SumValue(const tstack<trash>& bin, ostream& os)
{
	tstackIterator<trash> tally(bin);
	float val = 0;
	while(tally)
	{
		val += tally->weight() * tally->value();
		os << "weight of" << tally->name()
			<< " = " << tally->weight() << endl;
		tally++;
	}
	os << "Total value = " << val << endl;
}

int main()
{
	time_t t;
	srand((unsigned)time(&t));

	tstack<trash> bin;
	for(int i = 0; i < 30; ++i)
	{
		switch(rand() % 3)
		{
		case 0:
			bin.push(new aluminum(rand() % 100));
			break;
		case 1:
			bin.push(new paper(rand() % 100));
			break;
		case 2:
			bin.push(new glass(rand() % 100));
			break;
		}
	}
	tstack<trash> glassbin(0);
	tstack<trash> paperbin(0);
	tstack<trash> ALbin(0);
	tstackIterator<trash> sorter(bin);
	while(sorter)
	{
		switch(sorter->trashType())
		{
        case Aluminum:
			ALbin.push(sorter.current());
			break;
		case Paper:
			paperbin.push(sorter.current());
			break;
		case Glass:
			glassbin.push(sorter.current());
			break;
		}
		sorter++;
	}
	SumValue(ALbin, out);
	SumValue(paperbin, out);
	SumValue(glassbin, out);
	SumValue(bin, out);

	return 0;
}

 

 

 

 

 

 

17.

 

/*APPLIST.cpp*/
#include "E:\VC++\8_7_3\tstack.h"
#include <iostream.h>

template<class T, class R>
void applist(tstack<T>& t1, R(T::*f)())
{
	tstackIterator<T> it(t1);
	while(it)
	{
		(it.current()->*f)();
		it++;
	}
}

template<class T, class R, class A>
void applist(tstack<T>& t1, R(T::*f)(A), A a)
{
	tstackIterator<T> it(t1);
	while(it)
	{
		(it.current()->*f)(a);
		it++;
	}
}

template<class T , class R, class A1, class A2>
void applist(tstack<T>& t1, R(T::*f)(A1, A2),
			 A1 a1, A2 a2)
{
	tstackIterator<T> it(t1);
	while(it)
	{
		(it.current()->*f)(a1, a2);
		it++;
	}
}

class gromit
{
	int arf;
public:
	gromit(int Arf = 1) : arf(Arf+1) {}
	void speak(int)
	{
		for(int i = 0; i < arf; ++i)
		{
			cout << "arf!";
		}
		cout << endl;
	}
	char eat(float)
	{
		cout << "chomp!" << endl;
		return 'z';
	}
	int sleep(char, double)
	{
		cout << "zzz..." << endl;
		return 0;
	}
	void sit(void) {}
};


int main()
{
	tstack<gromit> dogs;
	for(int i = 0; i < 5; ++i)
	{
		dogs.push(new gromit(i));
	}
	applist(dogs, &gromit::speak, 1);
	applist(dogs, &gromit::eat, 2.0f);
	applist(dogs, &gromit::sleep, 'z', 3.0);
	applist(dogs, &gromit::sit);
	//dogs.applist(&gromit::sit);
	
	return 0;
}

 

 

 

 

 

18.

 

/*GENERATE.cpp*/
#include "E:\VC++\8_7_9\sorted.h"
#include "E:\VC++\8_7_5\integer.h"
template class sorted<integer>;

int main()
{
	sorted<integer> is;
	urand<47> rand1;
	for(int k = 0; k < 15; ++k)
	{
		is.add(new integer(rand1()));
	}
	for(int l = 0; l < is.count(); ++l)
	{
		cout << *is[l] << endl;
	}

	return 0;
}

 

 

 

 

 

19.

 

/*SPECIAL.cpp*/
#include "E:\VC++\8_7_9\sorted.h"
#include <iostream.h>

class sorted<char> : public tstash<char>
{
	void bubblesort();
public:
	int add(char* element)
	{
		tstash<char>::add(element);
		bubblesort();
		return 0;
	}
};


void sorted<char>::bubblesort()
{
	for(int i = count(); i > 0;--i)
	{
		for(int j = 1; j < i; ++j)
		{
			if(strcmp(storage[j], storage[j-1]) < 0)
			{
				char* t = storage[j-1];
				storage[j-1] = storage[j];
				storage[j] = t;
			}
		}
	}
}

char* words[] = 
{
	"is", "running", "big", "dog", "a",
};

const wsz = sizeof words/sizeof *words;

void main()
{
	sorted<char> sc;
	for(int k = 0; k < wsz; ++k)
	{
		sc.add(words[k]);
	}
	for(int l = 0; l < sc.count(); ++l)
	{
		cout << sc[l] << endl;
	}
}

 

 

 

 

 

 

二.習題+解答

1. 修改第1 4章練習一的結果,以便使用 tstack 和 tstackIterator替代 shape指針數組。增加針對類層次的析構函數以便在 tstack超出範圍時觀察shape對象被析構。
2. 修改第1 4章例子SSHAPE2.CPP以使用tstack替代數組。
3. 修改RECYCLE.CPP以使用tstash替代tstack。
4. 改變SETTEST.CPP以使用sortedSet替代set。
5. 爲 tstash 類複製A P P L I S T. C P P的功能。
6. 將T S TA C K . H拷貝到新的頭文件中,並增加 A P P L I S T. C P P中的函數模板作爲 t s t a c k的成
員函數模板。本練習要求我們的編譯器支持成員函數模板。
7. (高級)修改t s t a c k類以促進增加所有權的區分粒度。爲每一個鏈接增加標誌以表明它
是否擁有其指向的對象,並在 a d d ( )函數和析構函數中支持這一標誌信息。增加用於讀取和改
變每一鏈接所有權的成員函數,並在新的上下文環境中確定 a d d ( )標誌的含義。
8. (高級)修改t s t a c k類,使每一個入口包含引用計數信息(不是它們所包容的對象)並且
增加用於支持引用計數行爲的成員函數。
9. (高級)改變S O RT E D . C P P中u r a n d的底層實現以提高其空間效率( S O RT E D . C P P後面段
落所描述的) 而非時間效率。
10. (高級)將G E T M E M . H中的typedef cntr從整型改成長整型,並且修改代碼以消除失去
精度的警示信息,這是一個指針算術問題。
11. (高級)設計一個測試程序,用於比較創建在堆上和創建在棧上的 S S t r i n g的執行速度。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章