目录

本章小结

程序清单

string类

16.1 str1.cpp                16.2 strfile.cpp            16.3 hangman.cpp          16.4 str2.cpp

智能指针模板类

16.5 smrtptrs.cpp         16.6 fowl.cpp

标准模板库

16.7 vect1.cpp             16.8 vect2.cpp              16.9 vect3.cpp

泛型编程

16.10 copyit.cpp          16.11 inserts.cpp          16.12 list.cpp               16.13 setops.cpp          16.14 multimap.cpp

函数对象

16.15 functor.cpp         16.16 funadap.cpp

算法

16.17 strgst1.cpp         16.18 listrmv.cpp           16.19 usealgo.cpp

其他库

16.20 valvect.cpp           16.21 vslice.cpp             16.22 ilist.cpp


本章小结

       C++提供了一组功能强大的库,这些库提供了很多常见编程问题的解决方案以及简化其他问题的工具。 string类为将字符串作为对象来处理提供了种方便的方法。string类提供了自动内存管理功能以及众多处理字符串的方法和函数。例如,这些方法和函数让您能够合并字符串、将一个字符串插入到另一个字符串中、反转字符串、在字符串中搜索字符或子字符串以及执行输入和输出操作。

       诸如auto_ptr以及C++11新增的shared_ptr和unique_ptr等智能指针模板使得管理由new分配的内存更容易。如果使用这些智能指针(而不是常规指针)来保存new返回的地址,则不必在以后使用删除运算符。智能指针对象过期时,其析构函数将自动调用delete运算符。

       STL是一个容器类模板、迭代器类模板、函数对象模板和算法函数模板的集合,它们的设计是一致的,都是基于泛型编程原则的。算法通过使用模板,从而独立于所存储的对象的类型:通过使用迭代器接口,从而独立于容器的类型。迭代器是广义指针。

       STL使用术语“概念”来描述一组要求。例如,正向迭代器的概念包含这样的要求,即正向迭代器能够被解除引用,以便读写,同时能够被递增。概念真正的实现方式被称为概念的“模型”。例如,正向迭代 概念可以是常规指针或导航链表的对象。基于其他概念的概念叫作“改进”。例如,双向迭代器是正向迭代器概念的改进。

       诸如vector和set等容器类是容器概念(如容器、序列和关联容器)的模型。STL定义了多种容器类模板:vector、deque、list、set、multiset、map、multimap 和 bitset;还定义了适配器类模板 queue、priority_queue 和stack;这些类让底层容器类能够提供适配器类模板名称所建议的特性接口。因此,stack虽然在默认情况下是基于vector的,但仍只允许在找顶进行插入和删除。C++11新增了 forward_list、unordered_set、 unordered_multiset、 unordered_map 和 unordered_multimap。

       有些算法被表示为容器类方法,但大量算法都被表示为通用的、非成员函数,这处通过将迭代器作为容器和算法之间的接口得以实现的。这种方法的一个优点是:只需一个诸如for_each()或copy()这样的函数,向不必为每种容器提供一个版木;另一个优点是:STL算法可用于非STL容器,如常规数组、string 对象、array对象以及您设计的秉承STL迭代器和容器规则的任何类。

       容器和算法都是山其提供或需要的迭代器类型表征的。应当检査容器是否具备支持算法要求的迭代器概念。例如,for_each( )算法使用一个输入迭代器,所有的STL容器类类型都满足其最低要求:而sort() 则要求随机访问迭代器,并非所有的容器类都支持这种迭代器。如果容器类不能满足特定算法的要求,则可能提供一个专用的方法。例如,list类包含一个基于双向迭代器的sort()方法,因此它可以使用该方法, 是通用函数。

       STL还提供了函数对象(函数符),函数对象是重载了()运算符(即定义了 operator(X)方法)的类。 可以使用函数表示法来调用这种类的对象,同时可以携带额外的信息。自适应函数符有typedef语句,这种语句标识了函数符的参数类型和返回类型。这些信息可供其他组件(如函数适配器)使用。

       通过表示常用的容器类型,并提供各种使用高效算法实现的常用操作(全部是通用的方式实现的),STL提供了一个非常好的可重用代码源。可以直接使用STL工具来解决编程问题,也可以把它们作为基本部件,来构建所需的解决方案。

       模板类complex和valarray支持复数和数组的数值运算。

程序清单

string类

16.1 str1.cpp

构造字符串

// str1.cpp -- introducing the string class
#include <iostream>
#include <string>
// using string constructors

int main()
{
	using namespace std;
	string one("Lottery Winner!");	//	ctor #1
	cout << one << endl;	//	overloaded <<
	string two(20, '$');
	cout << two << endl;
	string three(one);	//	ctor #3
	cout << three << endl;
	one += " Oops !";	//	overloaded +=
	cout << one << endl;
	two = "Sorry! That was ";
	three[0] = 'P';
	string four;	//	ctor #4
	four = two + three;	// overloaded + =,
	cout << four << endl;
	char alls[] = "All is well that ends well";
	string five(alls, 20);	// ctor #5
	cout << five << "!\n";
	string six(alls + 6, alls + 10);	// ctor #6
	cout << six << ", ";
	string seven(&five[6], &five[10]); // ctor #6 again
	cout << seven << "...\n";
	string eight(four, 7, 16);// ctor #7
	cout << eight << " in motion!" << endl;
	return 0;
}

16.2 strfile.cpp

string类输入

// strfile.cpp -- read strings from a file
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

int main()
{
	using namespace std;
	ifstream fin; fin.open("tobuy.txt");
	if (fin.is_open() == false)
	{
		cerr << "Can't open file. Bye.\n";
		exit(EXIT_FAILURE);
	}
	string item;
	int count = 0;
	getline(fin, item, ':');
	while (fin) // while input is good
	{
		++count;
		cout << count << ": " << item << endl;
		getline(fin, item, ':');
	}
	cout << "Done\n";
	fin.close();
	return 0;
}

16.3 hangman.cpp

使用字符串

//hangman.cpp -- some string methods
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <cctype>

using namespace std;

const int NUM = 26;
const string wordlist[NUM] = { "apiary","beetle","cereal","danger","ensign","florid","garage",
"			health","insult","jackal","keeper","loaner","manage","nonce","onset","plaid","quilt",
			"remote","stolid","train","useful","valid","whence","xenon","yearn","zippy" };

int main()
{
	srand(time(0));
	char play;
	cout << "Will you play a word game ? <y/n>";
	cin >> play;
	play = tolower(play);
	while (play == 'y')
	{
		string target = wordlist[rand() % NUM];
		int length = target.length();
		string attempt(length, '-');
		string badchars;
		int guesses = 6;
		cout << "Guess my secret word. It has " << length << " letters, and you guess\n"
			<< "one letter at a time. You get " << guesses << " wrong guesses.\n";
		cout << "Your word: " << attempt << endl;
		while (guesses > 0 && attempt != target)
		{
			char letter;
			cout << "Guess a letter: ";
			cin >> letter;
			if (badchars.find(letter) != string::npos || attempt.find(letter) != string::npos)
			{
				cout << "You already guessed that. Try again.\n";
				continue;
			}
			int loc = target.find(letter);
			if (loc == string::npos)
			{
				cout << "Oh, bad guess!\n";
				--guesses;
				badchars += letter; // add to string
			}
			else
			{
				cout << "Good guessJ\n";
				attempt[loc] = letter;
				// check if letter appears again
				loc = target.find(letter, loc + 1);
				while (loc != string::npos)
				{
					attempt[loc] = letter;
					loc = target.find(letter, loc + 1);
				}
			}
			cout << "Your word: " << attempt << endl;
			if (attempt != target)
			{
				if (badchars.length() > 0)
					cout << "Bad choices: " << badchars << endl;
				cout << guesses << " bad guesses left\n";
			}
		}
		if (guesses > 0)
			cout << "That's right!\n";
		else
			cout << "Sorry, the word is " << target << ".\n";
		cout << "Will you play another? <y/n> ";
		cin >> play;
		play = tolower(play);
	}
	cout << "Bye\n";
	return 0;
}

16.4 str2.cpp

string的其他功能

//str2.cpp -- capacity() and reserve()
#include <iostream>
#include <string>

int main()
{
	using namespace std;

	string empty;
	string small = "bit";
	string larger = "Elephants are a girl's best friend";
	cout << "Sizes:\n";
	cout << "\tempty: " << empty.size() << endl;
	cout << "\tsmall: " << small.size() << endl;
	cout << "\tlarger: " << larger.size() << endl;
	cout << "Capacities:\n";
	cout << "\tempty: " << empty.capacity() << endl;
	cout << "\tsmall: " << small.capacity() << endl;
	cout << "\tlarger: " << larger.capacity() << endl;
	empty.reserve(50);
	cout << "Capacity after empty.reserve(50): " << empty.capacity() << endl;
	return 0;
}

智能指针模板类

16.5 smrtptrs.cpp

使用智能指针

// smrtptrs.cpp -- usir.g three kinds of smart pointers
// requires support of C+*ll shared_ptr and unique_ptr
#include <iostream>
#include <string>
#include <memory>

class Report
{
private:
	std::string str;
public:
	Report(const std::string s) : str(s)
	{
		std::cout << "Object created!\n";
	}
	~Report() { std::cout << "Object deleted!\n"; }
	void comment() const { std::cout << str << "\n"; }
};

int main()
{
	{
		std::auto_ptr<Report> ps(new Report("using auto_ptr"));
		ps->comment();	// use -> to invoke a member function
	}
	{
		std::shared_ptr<Report> ps(new Report("using shared_ptr"));
		ps->comment();
	}
	{
		std::unique_ptr<Report> ps(new Report("using unique_j>tr"));
		ps->comment();
	}
	return 0;
}

16.6 fowl.cpp

注意事项

// fowl.cpp -- auto_ptr a poor choice
#include <iostream>
#include <string>
#include <memory>

int main()
{
	using namespace std;
	auto_ptr<string> films[5] =
	{
		auto_ptr<string>(new string("Fowl Balls")),
		auto_ptr<string>(new string("Duck Walks")),
		auto_ptr<string>(new string("Chicken Runs")),
		auto_ptr<string>(new string("Turkey Errors")),
		auto_ptr<string>(new string("Goose Eggs"))
	};
	auto_ptr<string> pwin;
	pwin = films[2];	// films[2] loses ownerships
	cout << "The nominees for best avian baseball film are\n";
	for (int i = 0; i < 5; i++)
		cout << *films[i] << endl;
	cout << "The winner is " << *pwin << "!\n";
	cin.get();
	return 0;
}

标准模板库

16.7 vect1.cpp

模板类 vector

// vect1.cpp -- introducing the vector template
#include <iostream>
#include <string>
#include <vector>

const int NUM = 5;

int main()
{
	using namespace std;

	vector<int> ratings(NUM);
	vector<string> titles(NUM);
	cout << "You will do exactly as told. You will enter\n" << NUM << " book titles and your ratings (0-10).\n";
	int i;
	for (i = 0; i < NUM; i++)
	{
		cout << "Enter title #" << i + 1 << ": ";
		getline(cin, titles[i]);
		cout << "Enter your rating (0-10): ";
		cin >> ratings[i];
		cin.get();
	}
	cout << "Thank you. You entered the following:\n"
		<< "Rating\tBook\n";
	for (i = 0; i < NUM; i++)
	{
		cout << ratings[i] << "\t" << titles[i] << endl;
	}
	return 0;
}

16.8 vect2.cpp

对矢量进行操作

// vect2.cpp -- methods and iterators
#include <iostream>
#include <string>
#include <vector>

struct Review
{
	std::string title;
	int rating;
};

bool FillReview(Review & rr);
void ShowReview(const Review & rr);

int main()
{
	using std::cout;
	using std::vector;
	vector<Review> books;
	Review temp;
	while (FillReview(temp))
		books.push_back(temp);
	int num = books.size();
	if (num > 0)
	{
		cout << "Thank you. You entered the following:\n" << "Rating\tBook\n";
		for (int i = 0; i < num; i++)
			ShowReview(books[i]);
		cout << "Reprising:\n" << "Rating\tBook\n";
		vector<Review>::iterator pr;
		for (pr = books.begin(); pr != books.end(); pr++)
			ShowReview(*pr);
		vector <Review> oldlist(books);	// copy constructor used
		if (num > 3)
		{
			// remove 2 items
			books.erase(books.begin() + 1, books.begin() + 3);
			cout << "After erasure: \n";
			for (pr = books.begin(); pr != books.end(); pr++)
				ShowReview(*pr);
			// insert 1 item
			books.insert(books.begin(), oldlist.begin() + 1, oldlist.begin() + 2);
			cout << "After insertion: \n";
			for (pr = books.begin(); pr != books.end(); pr++)
				ShowReview(*pr);
		}
		books.swap(oldlist);
		cout << "Swapping oldlist with books:\n";
		for (pr = books.begin(); pr != books.end(); pr++)
			ShowReview(*pr);
	}
	else
		cout << "Nothing entered, nothing gained.\n ";
	return 0;
}
bool FillReview(Review & rr)
{
	std::cout << "Enter book title (quit to quit): ";
	std::getline(std::cin, rr.title);
	if (rr.title == "quit")
		return false;
	std::cout << "Enter book rating: ";
	std::cin >> rr.rating;
	if (!std::cin)
		return false;
	// get rid of rest of input line
	while (std::cin.get() != '\n')
		continue;
	return true;
}

void ShowReview(const Review & rr)
{
	std::cout << rr.rating << "\t" << rr.title << std::endl;
}

16.9 vect3.cpp

其他操作

//vect3.cpp -- using STL functions
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

struct Review
{
	std::string title;
	int rating;
};

bool operator<(const Review & r1, const Review & r2);
bool worseThan(const Review r1, const Review & r2);
bool FillReview(Review & rr);
void ShowReview(const Review & rr);


int main()
{
	using namespace std;
	vector<Review> books;
	Review temp;
	while (FillReview(temp))
		books.push_back(temp);
	if (books.size() > 0)
	{
		cout << "Thank you. You entered the following "
			<< books.size() << " ratings:\n"
			<< "Rating\tBook\n";
		for_each(books.begin(), books.end(), ShowReview);

		sort(books.begin(), books.end());
		cout << "Sorted by title:\nRating\tBook\n";
		for_each(books.begin(), books.end(), ShowReview);

		sort(books.begin(), books.end(), worseThan);
		cout << "Sorted by rating:\nRating\tBook\n";
		for_each(books.begin(), books.end(), ShowReview);

		random_shuffle(books.begin(), books.end());
		cout << "After shuffling:\nRating\tBook\n";
		for_each(books.begin(), books.end(), ShowReview);
	}
	else
		cout << "No entries.";
	cout << "Bye.\n";
	return 0;
}

bool operator<(const Review & r1, const Review & r2)
{
	if (r1.title < r2.title) return true;
	else if (r1.title == r2.title && r1.rating < r2.rating)
		return true;
	else
		return false;
}

bool woraeThan(const Review & r1, const Review & r2)
{
	if (r1.rating < r2.rating)
		return true;
	else
		return false;
}

bool FillReview(Review & rr)
{
	std::cout << "Enter book title(quit to quit) : ";
	std::getline(std::cin, rr.title);
	if (rr.title == "quit")
		return false;
	std::cout << "Enter book rating: ";
	std::cin >> rr.rating;
	if (!std::cin)
		return false;
	// get rid of rest of input line
	while (std::cin.get() != '\n')
		continue;
	return true;
}

void ShowReview(const Review & rr)
{
	std::cout << rr.rating << "\t" << rr.title << std::endl;
}

泛型编程

16.10 copyit.cpp

// copyit.cpp -- copy() and iterators
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
	using namespace std;
	int casts[10] = { 6, 7, 2, 9 ,4 , 11, 8, 7, 10, 5 };
	vector<int> dice(10);
	// copy from array to vector
	copy(casts, casts + 10, dice.begin());
	cout << "Let the dice be cast!\n";
	// create an ostream iterator
	ostream_iterator<int, char> out_iter(cout, " ");
	// copy from vector to output
	copy(dice.begin(), dice.end(), out_iter);
	cout << endl;
	cout << "Implicit use of reverse iterator.\n";
	copy(dice.rbegin(), dice.rend(), out_iter);
	cout << endl;
	cout << "Explicit use of reverse iterator.\n";
	vector<int>::reverse_iterator ri;
	for (ri = dice.rbegin(); ri != dice.rend(); ++ri)
		cout << *ri << ' ';
	cout << endl;
	return 0;
}

16.11 inserts.cpp

// inserts.cpp -- copy!) and insert iterators
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <algorithm>

void output(const std::string & s) { std::cout << s << " "; }

int main()
{
	using namespace std;
	string s1[4] = { "fine", "fish", "fashion", "fate" };
	string s2[2] = { "busy", "bats" };
	string s3[2] = { "silly", "singers" };
	vector<string> words(4);
	copy(s1, s1 + 4, words.begin());
	for_each(words.begin(), words.end(), output);
	cout << endl;
	// construct anonymous back_insert_iterator object
	copy(s2, s2 + 2, back_insert_iterator<vector<string> >(words));
	for_each(words.begin(), words.end(), output);
	cout << endl;
	// construct anonymous insert_iterator object
	copy(s3, s3 + 2, insert_iterator<vector<string> >(words, words.begin()));
	for_each(words.begin(), words.end(), output);
	cout << endl;
	return 0;
}

16.12 list.cpp

//list.cpp -- using a list
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

void outint(int n) { std::cout << n << " "; }
int main()
{
	using namespace std;
	list<int> one(5, 2); // list of 5 2s
	int stuff[5] = { 1,2,4,8,6 };
	list<int> two;
	two.insert(two.begin(), stuff, stuff + 5);
	int more[6] = { 6, 4, 2, 4, 6, 5 };
	list<int> three(two);
	three.insert(three.end(), more, more + 6);
	cout << "List one: ";
	for_each(one.begin(), one.end(), outint);
	cout << endl << "List two: ";
	for_each(two.begin(), two.end(), outint);
	cout << endl << "List three: ";
	for_each(three.begin(), three.end(), outint);
	three.remove(2);
	cout << endl << "List three minus 2s: ";
	for_each(three.begin(), three.end(), outint);
	three.splice(three.begin(), one);
	cout << endl << "List three after splice: ";
	for_each(three.begin(), three.end(), outint);
	cout << endl << "List one: ";
	for_each(one.begin(), one.end(), outint);
	three.unique();
	cout << endl << "List three after unique: ";
	for_each(three.begin(), three.end(), outint);
	three.sort();
	three.unique();
	cout << endl << "List three after sort &• unique: ";
	for_each(three.begin(), three.end(), outint);
	two.sort();
	three.merge(two);
	cout << endl << "Sorted two merged into three: ";
	for_each(three.begin(), three.end(), outint);
	cout << endl;
	return 0;
}

16.13 setops.cpp

//setops.cpp -- some set operations
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <iterator>

int main()
{
	using namespace std;
	const int N = 6;
	string s1[N] = { "buffoon","thinkers","for","heavy","can","for" };
	string s2[N] = { "metal", "any", "food","elegant","deliver","for" };

	set<string> A(s1, s1 + N);
	set<string> B(s2, s2 + N);

	ostream_iterator<string, char> out(cout, " ");
	cout << "Set A";
	copy(A.begin(), A.end(), out);
	cout << endl;
	cout << "Set B: ";
	copy(B.begin(), B.end(), out);
	cout << endl;
	cout << "Union of A and B:\n";
	set_union(A.begin() , A.end(), B.begin(), B.end(), out);
	cout << endl;
	cout << "Intersection of A and B:\n";
	set_intersection(A.begin(), A.end(), B.begin(), B.end(), out);
	cout << endl;
	cout << "Difference of A and B:\n";
	set_difference(A.begin(), A.end(), B.begin(), B.end(), out);
	cout << endl;
	set<string> C; cout << "Set C:\n";
	set_union(A.begin(), A.end(), B.begin(), B.end(), insert_iterator<set<string> >(C, C.begin()));
	copy(C.begin(), C.end(), out);
	cout << endl;
	string s3("grungy");
	C.insert(s3);
	cout << "Set C after insertion:\n";
	copy(C.begin(), C.end(), out);
	cout << endl;
	cout << "Showing a range:\n";
	copy(C.lower_bound("ghost"), C.upper_bound("spook"), out);
	cout << endl;
	return 0;
}

16.14 multimap.cpp

//multmap.cpp -- use a multimap
#include <iostream>
#include <string>
#include <map>
#include <algorithm>

typedef int KeyType;
typedef std::pair<const KeyType, std::string> Pair;
typedef std::multimap<KeyType, std::string> MapCode;
int main()
{
	using namespace std; MapCode codes;
	codes.insert(Pair(415, "San Francisco"));
	codes.insert(Pair(510, "Oakland"));
	codes.insert(Pair(718, "Brooklyn"));
	codes.insert(Pair(718, "Staten Island"));
	codes.insert(Pair(415, "San Rafael"));
	codes.insert(Pair(510, "Berkeley"));

	cout << "Number of cities with area code 415: " << codes.count(415) << endl;
	cout << "Number of cities with area code 718: " << codes.count(718) << endl;
	cout << "Number of cities with area code 510: " << codes.count(510) << endl;
	cout << "Area Code City\n";
	MapCode::iterator it;
	for (it = codes.begin(); it != codes.end(); ++it)
		cout << " " << (*it).first << "	" << (*it).second << endl;
	pair<MapCode::iterator, MapCode::iterator> range = codes.equal_range(718);
	cout << "Cities with area code 718 :\n";
	for (it = range.first; it != range.second; ++it)
		cout << (*it).second << endl;
	return 0;
}

函数对象

16.15 functor.cpp

// functor.cpp using a functor
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

template <class T> // functor class defines operator0 ()

class TooBig {
private:
	T cutoff;
public:
	TooBig(const T & t) : cutoff(t) {}
	bool operator()(const T & v) { return v > cutoff; }
};

void outint(int n) { std::cout << n << " "; }

int main()
{
	using std::list;
	using std::cout;
	using std::endl;
	TooBig<int> f100(100); // limit = 100
	int vals[10] = { 50, 100, 90, 180, 60, 210, 415, 88, 188, 20l };
	list<int> yadayada(vals, vals + 10); // range constructor
	list<int> etcetera(vals, vals + 10);
	// C++11 can use the following instead
	//list<int> yadayada = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201} ;
	// list<int> etcetera {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
	cout << "Original lists:\n";
	for_each(yadayada.begin(), yadayada.end(), outint);
	cout << endl;
	for_each(etcetera.begin(), etcetera.end(), outint);
	cout << endl;
	yadayada.remove_if(f100);	// use a named function object
	etcetera.remove_if(TooBig<int> (200));	// construct a function object
	cout << "Trimmed lists:\n";
		for_each(yadayada.begin(), yadayada.end(), outint); cout << endl;
	for_each(etcetera.begin(), etcetera.end(), outint);
	cout << endl;
	return 0;
}

16.16 funadap.cpp

// funadap.cpp -- using function adapters
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>

void Show(double);
const int LIM = 6;

int main()
{
	using namespace std;
	double arr1[LIM] = {28, 29, 30, 35, 38, 59};
	double arr2[LIM] = {63, 65, 69, 75, 80, 99};
	vector<double> gr8(arr1, arr1 + LIM);
	vector<double> m8(arr2, arr2 + LIM);
	cout.setf(ios_base::fixed);
	cout.precision(1);
	cout << "gr8:\t";
	for_each(gr8.begin(), gr8.end(), Show);
	cout << endl;
	cout << "m8: \t";
	for_each(m8.begin(), m8.end(), Show);
	cout << endl;
	vector<double> sum(LIM);
	transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(), plus<double>());
	cout << "sum:\t";
	for_each(sum.begin(), sum.end(), Show);
	cout << endl;

	vector<double> prod(LIM);
	transform(gr8.begin(), gr8.end(), prod.begin(), bind1st(multiplies<double>(), 2.5));
	cout << "prod:\t";
	for_each(prod.begin(), prod.end(), Show);
	cout << endl;
	return 0;
}

void Show(double v)
{
	std::cout.width(6);
	std::cout << v << ' ';
}

算法

16.17 strgst1.cpp

// strgstl.cpp -- applying the STL to a string
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
	using namespace std;
	string letters;
	cout << "Enter the letter grouping (quit to quit): ";
	while (cin >> letters && letters != "quit")
	{
		cout << "Permutations of " << letters << endl;
		sort(letters.begin(), letters.end());
		cout << letters << endl;
		while (next_permutation(letters.begin(), letters.end()))
			cout << letters << endl;
		cout << "Enter next sequence (quit to quit): ";
	}
	cout << "Done.\n";
	return 0;
}

16.18 listrmv.cpp

// listrmv.cpp -- applying the STL to a string
#include <iostream>
#include <list>
#include <algorithm>
void Show(int); const int LIM = 10;
int main()
{
	using namespace std;
	int ar[LIM] = { 4, 5, 4, 2, 2, 3, 4, 8, 1, 4 };
	list<int> la(ar, ar + LIM);
	list<int> lb(la);
	cout << "Original list contents:\n\t";
	for_each(la.begin(), la.end(), Show);
	cout << endl;
	la.remove(4);
	cout << "After using the remove() method:\n";
	cout << "la:\t";
	for_each(la.begin(), la.end(), Show);
	cout << endl;
	list<int>::iterator last;
	last = remove(lb.begin(), lb.end(), 4);
	cout << "After using the remove() functionin";
	cout << "lb:\t";
	for_each(lb.begin(), lb.end(), Show); cout << endl;
	lb.erase(last, lb.end());
	cout << "After using the erase!) method:\n"; cout << "lbAt";
	for_each(lb.begin(), lb.end(), Show); cout << endl;
	return 0;
}

void Show(int v)
{
	std::cout << v << ' ';
}

16.19 usealgo.cpp

//usealgo.cpp -- using several STL elements
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
#include <cctype>

using namespace std;

char toLower(char ch) { return tolower(ch);}
string & ToLower(string & st);
void display(const string & s);

int main()
{
	vector<string> words;
	cout << "Enter words (enter quit to quit):\n";
	string input;
	while (cin >> input && input != "quit")
		words.push_back(input);
	cout << "You entered the following words:\n";
	for_each(words.begin(), words.end(), display);
	cout << endl;
	// place words in set, converting to lowercase
	set<string> wordset;
	transform(words.begin(), words.end(), insert_iterator<set<string> >(wordset, wordset.begin()), ToLower);
	cout << "\nAlphabetic list of words:\n";
	for_each(wordset.begin(), wordset.end(), display);
	cout << endl;
	// place word and frequency in map
	map<string, int> wordmap;
	set<string>::iterator si;
	for (si = wordset.begin(); si != wordset.end(); si++)
		wordmap[*si] = count(words.begin(), words.end(), *si);
	// display map contents
	cout << "\nWord frequency:\n";
	for (si = wordset.begin();
		si != wordset.end(); si++) cout << *si << ":" << wordmap[*si] << endl;
	return 0;
}

string & ToLower(string & st)
{
	transform(st.begin(), st.end(), st.begin(), toLower);
	return st;
}

void display(const string & s)
{
	cout << s << " ";
}

其他库

16.20 valvect.cpp

联合使用

// valvect.cpp -- comparing vector and valarray
#include <iostream>
#include <valarray>
#include <vector>
#include <algorithm>
int main()
{
	using namespace std;
	vector<double> data;
	double temp;
	cout << "Enter numbers (<=0 to quit):\n";
	while (cin >> temp && temp > 0)
		data.push_back(temp);
	sort(data.begin(), data.end());
	int size = data.size();
	valarray<double> numbers(size);
	int i;
	for (i = 0; i < size; i++)
		numbers[i] = data[i];
	valarray<double> sq_rts(size);
	sq_rts = sqrt(numbers);
	valarray<double> results(size);
	results = numbers + 2.0 * sq_rts;
	cout.setf(ios_base::fixed);
	cout.precision(4);
	for (i = 0; i < size; i++)
	{
		cout.width(8);
		cout << numbers[i] << ': ';
		cout.width(8);
		cout << results[i] << endl;
	}
	cout << "done\n";
	return 0;
}

16.21 vslice.cpp

使用valarray库

//vslice.cpp -- using valarray slices
#include <iostream>
#include <valarray>
#include <cstdlib>

const int SIZE = 12;
typedef std::valarray<int> vint; // simplify declarations
void show(const vint & v, int cols);

int main()
{
	using std::slice;	// from <valarray>
	using std::cout;
	vint valint(SIZE);	// think of as 4 rows of 3
	int i;
	for (i = 0; i < SIZE; ++i)
		valint[i] = std::rand() % 10;
	cout << "Original array:\n";
	show(valint, 3); // show in 3 columns
	vint vcol(valint[slice(1, 4, 3)]); // extract 2nd column
	cout << "Second column:\n";
	show(vcol, 1);// show in 1 column
	vint vrow(valint[slice(3, 3, 1)]);// extract 2nd row
	cout << "Second row:\n";
	show(vrow, 3);
	valint[slice(2, 4, 3)] = 10;// assign to 2nd column
	cout << "Set last column to 10:\n"; show(valint, 3);
	cout << "Set first column to sum of next two:\n";
	// + not defined for slices, so convert to valarray<int>
	valint[slice(0, 4, 3)] = vint(valint[slice(1, 4, 3)]) + vint(valint[slice(2, 4, 3)]);
	show(valint, 3);
	return 0;
}

void show(const vint & v, int cols)
{
	using std::cout;
	using std::endl;
	int lim = v.size();
	for (int i = 0; i < lim; ++i)
	{
		cout.width(3);
		cout << v[i];
		if (i % cols == cols - 1)
			cout << endl;
		else
			cout << ' ';
	}
	if (lim % cols != 0)
		cout << endl;
}

16.22 ilist.cpp

使用initializer_list

// ilist.cpp -- use initializer_list (C++11 feature)
#include <iostream>
#include <initializer_list>

double sum(std::initializer_list<double> il);
double average(const std::initializer_list<double> & ril);

int main()
{
	using std::cout;

	cout << "List l: sum = " << sum({ 2,3,4 }) << ", ave = " << average({ 2,3,4 }) << '\n';
	std::initializer_list<double> dl = { 1.1, 2.2, 3.3, 4.4, 5.5 };
	cout << "List 2: sum = " << sum(dl) << ", ave = " << average(dl)<< '\n';
	dl = { 16.0, 25.0, 36.0, 40.0, 64.0 };
	cout << "List 3: sum = " << sum(dl) << ", ave = " << average(dl) << '\n';
	return 0;
}

double sum(std::initializer_list<double> il)
{
	double tot = 0;
	for (auto p = il.begin(); p != il.end(); p++)
		tot += *p;
	return tot;
}

double average(const std::initializer_list < double> & ril)
{
	double tot = 0;
	int n = ril.size();
	double ave = 0.0;
	if (n > 0)
	{
		for (auto p = ril.begin(); p != ril.end(); p++)
			tot += *p;
		ave = tot / n;
	}
	return ave;
}

 

10-03 20:11