essential C++

本文通过多个实例展示了C++编程中的各种技巧,包括使用标准库组件如vector,设计泛型算法,实现类和继承,以及利用迭代器等。此外还探讨了面向对象编程的概念。

1.5节中有对vector的简单介绍,所以就写了一个程序,用于表达书上运用vector的思想:

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
using namespace std;

//备注:这里用到rand当然不好,因为rand并不是一个真正的随机数。
void getNum(vector< vector<int> > &ivvec, int &firstNum, int &secondNum, int &thirdNum)
{
	int		randomSeq = 0;		//随机的序列
	int		randomBegin = 0;	//随机序列中随机的第一个元素的索引
	randomSeq = rand() % 6;
	randomBegin = rand() % 6;

	firstNum = ivvec[randomSeq][randomBegin];
	secondNum = ivvec[randomSeq][randomBegin + 1];
	thirdNum = ivvec[randomSeq][randomBegin + 2];
}
int main(void)
{
	int		arrFib[8] = {1, 1, 2, 3, 5, 8, 13, 21};
	vector<int>		iFibVec(arrFib, arrFib + 8);
	int		arrLuc[8] = {1, 3, 4, 7, 11, 18, 29, 47};
	vector<int>		iLucVec(arrLuc, arrLuc + 8);
	int		arrPel[8] = {1, 2, 5, 12, 29, 70, 169, 408};
	vector<int>		iPelVec(arrPel, arrPel + 8);
	int		arrTri[8] = {1, 3, 6, 10, 15, 21, 28, 36};
	vector<int>		iTriVec(arrTri, arrTri + 8);
	int		arrSqu[8] = {1, 4, 9, 16, 25, 36, 49, 64};
	vector<int>		iSquVec(arrSqu, arrSqu + 8);
	int		arrPen[8] = {1, 5, 12, 22, 35, 51, 70, 92};
	vector<int>		iPenVec(arrPen, arrPen + 8);

	vector< vector<int> > ivvec;
	ivvec.push_back(iFibVec);
	ivvec.push_back(iLucVec);
	ivvec.push_back(iPelVec);
	ivvec.push_back(iTriVec);
	ivvec.push_back(iSquVec);
	ivvec.push_back(iPenVec);

	//从ivvec中提取三个随机的数
	bool		bTry = true;		//用户想再次尝试
	const int	maxTries = 5;		//最多尝试次数
	int			numTries = 0;		//用户尝试的次数
	int			numRight = 0;		//用户正确的次数

	while (bTry)
	{
		int		firstNum = 0;
		int		secondNum = 0;
		int		thirdNum = 0;
		getNum(ivvec, firstNum, secondNum, thirdNum);
		cout << "the first number is: " << firstNum << "\nand the second number is: " << secondNum << endl;
		cout << "please enter the third number: ";
		int		userNum = 0;
		cin >> userNum;
		string userSelect;

		if (userNum == thirdNum)
		{
			numRight++;
			numTries++;
			cout << "you are right.do you want to try another numbers?(N/n to break, another continue)" << endl;
			cin >> userSelect;
		}
		else
		{
			if (numTries > maxTries)
			{
				cout << "sorry, you have tried max times." << endl;
				break;
			}
			numTries++;
			cout <<"you are wrong. do you wang to try another numbers?(N/n to break, another continue)" << endl;
			cin >> userSelect;
		}
		if ((userSelect == "n") || (userSelect == "N"))
		{
			break;
		}
	}

	cout << "the rate success is: " << (numRight * 1.0 / numTries) * 100 << "%" << endl;

	return 0;
}
在第二章中讲述如何编写函数,举了Fibonacci函数的例子:
#include <iostream>
using namespace std;

bool fibon_elem(int, int &);

int main(void)
{
	int pos;
	cout << "please enter a position:";
	cin >> pos;

	int elem;
	if (fibon_elem(pos, elem))
	{
		cout << "element #" << pos<< " is " << elem << endl;
	}
	else
	{
		cout << "sorry. could not calculate element#" << pos << endl;
	}

	return 0;
}

bool fibon_elem(int pos, int &elem)
{
	if ((pos <= 0) || (pos > 1024))
	{
		elem = 0;
		return false;
	}

	elem = 1;
	int n_2 = 1;
	int n_1 = 1;

	for (int ix = 3; ix <= pos; ix++)
	{
		elem = n_1 + n_2;
		n_2 = n_1;
		n_1 = elem;
	}

	return true;
}
调用一个函数:
#include <iostream>
#include <vector>
using namespace std;

void display(vector<int> ivec);
void swap(int &val1, int &val2);
void bubble_sort(vector<int> &ivec);

int main(void)
{
	int ia[8] = {8, 34, 3, 13, 1, 21, 5, 2};
	vector<int> ivec(ia, ia + 8);

	cout << "vector before sort" << endl;
	display(ivec);

	bubble_sort(ivec);

	cout << "vector after sort:" << endl;
	display(ivec);

	return 0;
}

void display(vector<int> ivec)
{
	for (int ix = 0; ix < ivec.size(); ix++)
	{
		cout << ivec[ix] << " ";
	}
	cout << endl;
}

void swap(int &val1, int &val2)
{
	int temp;
	temp = val1;
	val1 = val2;
	val2 = temp;
}

void bubble_sort(vector<int> &ivec)
{
	for (int ix = 0; ix < ivec.size(); ix++)
	{
		for (int jx = ix + 1; jx < ivec.size(); jx++)
		{
			if (ivec[ix] > ivec[jx])
			{
				swap(ivec[ix], ivec[jx]);
			}
		}
	}
}
关于如何提供默认参数值:
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

void swap(int &val1, int &val2, ofstream *ofil = 0);
template<typename T>
void bubble_sort(vector<int> &ivec, T *ofil = 0);
void display(vector<int> &ivec, ostream &os = cout);
int main(void)
{
	int ia[8] = {8, 7, 6, 5, 4, 3, 2, 1};
	vector<int> ivec(ia, ia + 8);

	cout << "before sort:" << endl;
	display(ivec);

	bubble_sort<ostream>(ivec, &cout);
	cout << "after sort:" << endl;
	display(ivec, cout);

	return 0;
}

void display(vector<int> &ivec, ostream &os)
{
	for (int ix = 0; ix < ivec.size(); ix++)
	{
		os << ivec[ix] << " ";
	}

	os << endl;
}

void swap(int &val1, int &val2, ofstream *ofil)
{
	int temp;
	temp = val1;
	val1 = val2;
	val2 = temp;

	if (ofil != 0)
	{
		(*ofil) << "swap " << val1 << " and " << val2 << endl;
	}
}

template<typename T>
void bubble_sort(vector<int> &ivec, T *ofil /* = 0 */)
{
	for (int ix = 0; ix < ivec.size(); ix++)
	{
		for (int jx = ix + 1; jx < ivec.size(); jx++)
		{
			if (ivec[ix] > ivec[jx])
			{
				if (ofil != 0)
				{
					(*ofil) << "about to call swap! ix: " << ix
						<< " jx: " << jx << "\tswapping :" << ivec[ix] << " with " << ivec[jx] << endl;
				}
				swap(ivec[ix], ivec[jx]);
			}
		}
	}
}
使用局部静态对象:
#include <iostream>
#include <vector>
using namespace std;

vector< int > fibon_seq(int size);
int main(void)
{
	vector< int > ivec;
	ivec = fibon_seq(10);
	ivec = fibon_seq(5);
	for (int ix = 0; ix < ivec.size(); ix++)
	{
		cout << ivec[ix] << " ";
	}

	cout << endl;
	
	return 0;
}

vector< int > fibon_seq(int size)
{
	static vector< int > elems; 
	for (int ix = elems.size(); ix < size; ix++)
	{
		if ((ix == 0) || (ix == 1))
		{
			elems.push_back(1);
		}
		else
		{
			elems.push_back(elems[ix - 1] + elems[ix - 2]);
		}
	}

	return elems;
}
函数指针的作用,增加灵活性:
#include <iostream>
#include <vector>
#include <string>
using namespace std;

void fun1(int iValue)
{
	cout << iValue << endl;
}

void fun2(float fValue)
{
	cout << fValue << endl;
}

void fun3(string sValue)
{
	cout << sValue << endl;
}

template<typename funType>
void fun(void (*subfun)(funType), funType val)
{
	(*subfun)(val);
}

int main(void)
{
	fun<int>(fun1, 12);
	fun<float>(fun2, 12.3);
	fun<string>(fun3, "hello world");

	return 0;
}

第三章介绍设计泛型算法的时候,自己就先设计了一下,运行了还可以,当然,用到了函数指针的思想:

#include <iostream>
#include <vector>
using namespace std;

template<typename T>
bool lessThan(T val, T maxValue)
{
	return (val < maxValue);
}

template<typename IteratorType, typename T>
vector< T > less_than_10(IteratorType first, IteratorType last, bool (*fun)(T,T ), T maxValue)
{
	vector< T > ivec;
	for ( ; first != last; first++ )
	{
		if (fun(*first, maxValue))
		{
			ivec.push_back(*first);
		}
	}

	return ivec;
}

int main(void)
{
	vector< int > ivec;
	vector< int > ivecres;
	for ( int i = 0; i < 20; i++)
	{
		ivec.push_back(i);
	}
	ivecres = less_than_10<vector<int>::iterator, int>(ivec.begin(), ivec.end(), lessThan, 10);
	for (int i = 0; i < ivecres.size(); i++)
	{
		cout << ivecres[i] << " ";
	}

	return 0;
}
然而,书本上提供了一种仿函数和配接器的能力,来完成这个泛型的算法:

当然,书上的方法更好:

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;

template<typename InputIterator, typename OutputIterator,
		typename ElemType, typename Comp>
OutputIterator
filter(InputIterator first, InputIterator last,
	   OutputIterator at, const ElemType val, Comp pred)
{
	while ((first = find_if(first, last, bind2nd(pred, val))) != last)
	{
		cout << "found value: " << *first << endl;

		*at++ = *first++;
	}

	return at;
}

int main(void)
{
	vector<int> ivec;
	for (int i = 0; i < 20; i++)
	{
		ivec.push_back(i);
	}

	vector<int> ivec2;
	filter(ivec.begin(), ivec.end(), back_inserter(ivec2), 10, less<int>());

	for (int i = 0; i < ivec2.size(); i++)
	{
		cout << ivec2[i] << " ";
	}

	cout << endl;

	return 0;
}
书上讲到输入输出流的时候,我就写了一个例子:
#include <iostream>
#include <iterator>
#include <string>
using namespace std;

int main(void)
{
	copy(istream_iterator<string>(cin), istream_iterator<string>(), ostream_iterator<string>(cout, " "));

	return 0;
}
我只能说,这个例子太美了。


第四章中如何实现一个class,第一个例子就是stack,编写如下:

stack.h

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

class Stack{
public:
	bool	push(const string);
	bool	pop(string &elem);
	bool	peek(string &elem);

	bool	empty();
	bool	full();

	bool	find(string elem);
	int		count(string elem);

	int		size(){
		return _stack.size();
	}
private:
	vector<string> _stack;
};
stack.cpp
#include "Stack.h"

inline bool Stack::empty()
{
	return _stack.empty();
}

inline bool Stack::full()
{
	return _stack.size() == _stack.max_size();
}

bool Stack::push(const string elem)
{
	if (full())
	{
		return false;
	}

	_stack.push_back(elem);

	return true;
}

bool Stack::pop(string &elem)
{
	if (empty())
	{
		return false;
	}

	elem = _stack.back();
	_stack.pop_back();

	return true;
}

bool Stack::peek(string &elem)
{
	if (empty())
	{
		return false;
	}

	elem = _stack.back();

	return true;
}

bool Stack::find(string elem)
{
	return ::find(_stack.begin(), _stack.end(), elem) != _stack.end();
}

int Stack::count(string elem)
{
	return ::count(_stack.begin(), _stack.end(), elem);
}
在进行类的设计的时候,有一点要注意就是:析构函数,赋值操作符重载,复制构造函数三者同存同亡,是个好的设计理念。

第四章里面设计了一个类,但是我怎么都是弄混了,于是自己写了这个类,当然和书上的不同,但是运行的结果是一样的:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Triangular{
public:
	Triangular( int length = 1, int beg_pos = 1)
	{
		_length = length;
		_beg_pos = beg_pos;
		for (int i = beg_pos; i < beg_pos + length; i++)
		{
			sivec.push_back(i * (i + 1) / 2);
		}
	}

	int beg_pos() const
	{
		return _beg_pos;
	}
	int length() const
	{
		return _length;
	}
	void show() const 
	{
		for (int i = 0; i < sivec.size(); i++)
		{
			cout << sivec[i] << " ";
		}
	}
	int sum() const
	{
		int sum = 0;
		for (int i = 0; i < sivec.size(); i++)
		{
			sum += sivec[i];
		}

		return sum;
	}
private:
	int		_length;
	int		_beg_pos;

	vector<int>	sivec;
};

ostream& operator<<(ostream &os, Triangular &rhs)
{
	os << "( " << rhs.beg_pos() << " , " << rhs.length() << " ) ";
	rhs.show();

	return os;
}

int main(void)
{
	Triangular tr(4);
	cout << tr << "--sum of elements:" << tr.sum() << endl;

	Triangular tr2(4, 3);
	cout << tr2 << "--sum of elements:" << tr2.sum() << endl;

	Triangular tr3(4, 8);
	cout << tr3 << "--sum of elements:" << tr3.sum() << endl;

	return 0;
}

在第四章的中间部分,有一个问题提出是如何设计iterator class,于是自己照着书上的方法写了一下,发现可以运行,就粘贴上来了。当然,代码的构架方面和书上的意义,只是编写方式不同而已:

triangular_iterator.h:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Triangular_iterator{
public:
	Triangular_iterator(int index) : _index(index - 1){}
	bool operator==(const Triangular_iterator&) const;
	bool operator!=(const Triangular_iterator&) const;
	int operator*() const;
	Triangular_iterator& operator++();
	Triangular_iterator operator++(int);
private:
	void check_integrity() const;
	int _index;
};

class Triangular{
	friend Triangular_iterator;
public:
	Triangular( int length = 1, int beg_pos = 1)
	{
		_length = length;
		_beg_pos = beg_pos;
		_elems.clear();		
		//这里进行了一次折中的运算。因为iterator要求_elems必须为static,
		//但是static的性质导致_elems的值每次都在原基础上增加,所以进行clear操作
		for (int i = beg_pos; i < beg_pos + length; i++)
		{
			_elems.push_back(i * (i + 1) / 2);
		}
	}

	typedef Triangular_iterator iterator;

	Triangular_iterator begin() 
	{
		return Triangular_iterator(1);		//这里进行了特殊的修改,为了符合我自己编写代码的习惯,符合_elems为static并且每次都变的情况。
	}

	Triangular_iterator end() 
	{
		return Triangular_iterator(1 + _length);
	}

	int beg_pos() const
	{
		return _beg_pos;
	}
	int length() const
	{
		return _length;
	}
	static void show() 
	{
		for (int i = 0; i < _elems.size(); i++)
		{
			cout << _elems[i] << " ";
		}
	}
	static int sum()
	{
		int sum = 0;
		for (int i = 0; i < _elems.size(); i++)
		{
			sum += _elems[i];
		}

		return sum;
	}
	static void gen_elements(int index)
	{
		for (int i = _elems.size(); i < index; i++)
		{
			_elems.push_back(i * (i + 1) / 2);
		}
	}

private:
	int		_length;
	int		_beg_pos;

	static vector<int>	_elems;
};
vector<int> Triangular::_elems;

ostream& operator<<(ostream &os, Triangular &rhs)
{
	os << "( " << rhs.beg_pos() << " , " << rhs.length() << " ) ";
	rhs.show();

	return os;
}

inline bool Triangular_iterator::operator==(const Triangular_iterator &rhs) const
{
	return _index == rhs._index;
}

inline bool Triangular_iterator::operator!=(const Triangular_iterator &rhs) const
{
	return !(*this == rhs);
}

inline int Triangular_iterator::operator*() const
{
	check_integrity();
	return Triangular::_elems[_index];
}

inline void Triangular_iterator::check_integrity() const
{
	if (_index >= Triangular::_elems.size())
	{
		Triangular::gen_elements(_index + 1);
	}
}

inline Triangular_iterator& Triangular_iterator::operator++()
{
	++_index;
	check_integrity();
	return *this;
}

inline Triangular_iterator Triangular_iterator::operator++(int)
{
	Triangular_iterator tmp = *this;
	++_index;
	check_integrity();
	return tmp;
}
main.cpp:
#include "Triangular_iterator.h"

int main(void)
{
	Triangular tr(32);
	cout << tr << "--sum of elements:" << tr.sum() << endl;

	Triangular tr2(4, 3);
	cout << tr2 << "--sum of elements:" << tr2.sum() << endl;

	Triangular tr3(4, 8);
	cout << tr3 << "--sum of elements:" << tr3.sum() << endl;

	Triangular tr4(20, 12);
	Triangular::iterator it = tr4.begin();
	Triangular::iterator end_it = tr4.end();
	cout << "triangular series of " << tr4.length() << " elements\n";
	cout << tr4 << endl;
	while (it != end_it)
	{
		cout << *it << " ";
		++it;
	}

	cout << endl;

	return 0;
}
关于仿函数:
#include <iostream>
#include <vector>
using namespace std;

class LessThan{
public:
	LessThan( int val ) : _val(val){}
	int comp_val() const {return _val;}
	void comp_val( int nval ){ _val = nval;}

	bool operator()( int value ) const
	{
		return value < _val;
	}
private:
	int _val;
};

int count_less_than( const vector<int> &vec, int comp )
{
	LessThan lt(comp);

	int count = 0;
	for ( int ix = 0; ix < vec.size(); ix++ )
	{
		if ( lt( vec[ix] ) )
		{
			++count;
		}
	}

	return count;
}

int main(void)
{
	vector< int > ivec;
	for ( int i = 0; i < 20; i++ )
	{
		ivec.push_back(i);
	}

	cout << count_less_than( ivec, 10 ) << endl;

	return 0;
}


第五章面向对象编程风格中,刚开头举了一个图书馆的例子,代码如下:

#include <iostream>
#include <string>

using namespace std;

class LibMat{
public:
	LibMat()
	{
		cout << "LibMat::Libmat() default constructor!\n";
	}
	virtual ~LibMat()
	{
		cout << "LibMat::~LibMat() default destructor!\n";
	}
	virtual void print() const
	{
		cout << "LibMat::print() -- I am a LibMat object!\n";
	}
};

class Book : public LibMat{
public:
	Book(const string &title, const string &author)
		:_title(title), _author(author)
	{
		cout << "Book::Book( " << _title << " , "
			<< _author << " ) constructor\n";
	}
	virtual ~Book()
	{
		cout << "Book::~Book() destructor!\n";
	}
	virtual void print() const
	{
		cout << "Book::print() -- I am a Book object!\n"
			<< "My title is: " << _title << "\n"
			<< "My author is: " << _author << endl;
	}
	const string &title() const
	{
		return _title;
	}
	const string &author() const
	{
		return _author;
	}
protected:
	string _title;
	string _author;
};

class AudioBook : public Book{
public:
	AudioBook( const string &title,
		const string &author, const string &narrator)
		:Book(title, author),
		_narrator(narrator)
	{
		cout << "audiobook:audiobook( " << _title
			<< " , " << _author
			<< " ," << _narrator
			<< " ) constructor\n";
	}
	~AudioBook()
	{
		cout << "audiobook::~audiobook() destructor!\n";
	}
	virtual void print() const
	{
		cout << "AudioBook::print() -- I am an AudioBook object!\n"
			<< "My title is: " << _title << "\n"
			<< "My author is: " << _author << "\n"
			<< "My narrator is: " << _narrator << endl;
	}
	const string &narrator() const
	{
		return _narrator;
	}
protected:
	string _narrator;
};

void print(const LibMat &mat)
{
	cout << "in global print(): about to print mat.print()\n";

	mat.print();
}

int main(void)
{
	AudioBook ab("随遇而安","孟非", "good");
	print(ab);

	return 0;
}

在进行类的继承和多态的问题上,书上讲了一个非常好的例子:

num_sequence.h:

#include <iostream>
using namespace std;

class num_sequence{
public:
	virtual ~num_sequence(){}

	virtual int			elem(int pos) const = 0;
	virtual const char*	what_am_i() const  = 0;
	static int			max_elems()
	{
		return _max_elems;
	}
	virtual ostream&	print(ostream &os = cout) const = 0;
protected:
	virtual void		gen_elems(int pos) const = 0;
	bool				check_integrity(int pos, int size) const;

	const static int	_max_elems = 1024;
};

bool num_sequence::check_integrity(int pos, int size) const
{
	if (pos <= 0 || pos > _max_elems)
	{
		cerr << "!! invalid position: " << pos
			<< " cannot honor request\n";
		return false;
	}

	if (pos > size)
		gen_elems(pos);

	return true;
}

ostream& operator<<(ostream &os, const num_sequence &ns)
{
	return ns.print(os);
}
Fibonacci.h:
#include "num_sequence.h"
#include <iostream>
#include <vector>
using namespace std;

class Fibonacci : public num_sequence{
public:
	Fibonacci(int len = 1, int beg_pos = 1)
		:_length(len), _beg_pos(beg_pos){}
	virtual int			elem(int pos) const;
	virtual const char*	what_am_i() const { return "Fibonacci";}
	virtual ostream&	print(ostream &os = cout) const;
	int					length() const{return _length;}
	int					beg_pos() const {return _beg_pos;}
protected:
	virtual void		gen_elems(int pos) const;
	int					_length;
	int					_beg_pos;
	static vector<int>	_elems;
};
vector<int> Fibonacci::_elems;

int Fibonacci::elem(int pos) const
{
	if (!check_integrity(pos, _elems.size()))
	{
		return 0;
	}

	if (pos > _elems.size())
		Fibonacci::gen_elems(pos);

	return _elems[pos - 1];
}

void Fibonacci::gen_elems(int pos) const
{
	if (_elems.empty())
	{
		_elems.push_back(1);
		_elems.push_back(1);
	}

	if (_elems.size() <= pos)
	{
		int ix = _elems.size();
		int n_2 = _elems[ix - 2];
		int n_1 = _elems[ix - 1];

		for (; ix <= pos; ++ix)
		{
			int elem = n_2 + n_1;
			_elems.push_back(elem);
			n_2 = n_1;
			n_1 = elem;
		}
	}
}

ostream& Fibonacci::print(ostream &os) const
{
	int elem_pos = _beg_pos - 1;		//之所以要减1,是因为索引是从0开始的
	int end_pos = elem_pos + _length;	

	if (end_pos > _elems.size())
		Fibonacci::gen_elems(end_pos);

	while (elem_pos < end_pos)
	{
		os << _elems[elem_pos++] << " ";
	}

	return os;
}
main.cpp:
#include <iostream>
#include "Fibonacci.h"
using namespace std;

int main(void)
{
	Fibonacci fib;

	cout << fib << endl;

	Fibonacci fib2(4);
	cout << fib2 << endl;

	Fibonacci fib3(8, 12);
	cout << fib3 << endl;

	return 0;
}


第六章的模板和第七章的异常不看了。还好吧,一步步来,不急。

接下去就慢慢的工作,然后看完《C++ Primer》,《the C++ programming language》和《C和指针》。

今年下半年不求什么,只要把这四本书看完就可以了。

顺便看50本的额外小说,加油。

工作就好好工作。



转载于:https://my.oschina.net/voler/blog/151762

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值