<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mediawiki.zeropage.org/index.php?action=history&amp;feed=atom&amp;title=AcceleratedC%2B%2B%2FChapter7</id>
	<title>AcceleratedC++/Chapter7 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mediawiki.zeropage.org/index.php?action=history&amp;feed=atom&amp;title=AcceleratedC%2B%2B%2FChapter7"/>
	<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=AcceleratedC%2B%2B/Chapter7&amp;action=history"/>
	<updated>2026-05-15T16:07:11Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.8</generator>
	<entry>
		<id>https://mediawiki.zeropage.org/index.php?title=AcceleratedC%2B%2B/Chapter7&amp;diff=84054&amp;oldid=prev</id>
		<title>Maintenance script: Repair batch-0001 pages from live compare</title>
		<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=AcceleratedC%2B%2B/Chapter7&amp;diff=84054&amp;oldid=prev"/>
		<updated>2026-03-26T23:56:00Z</updated>

		<summary type="html">&lt;p&gt;Repair batch-0001 pages from live compare&lt;/p&gt;
&lt;a href=&quot;https://mediawiki.zeropage.org/index.php?title=AcceleratedC%2B%2B/Chapter7&amp;amp;diff=84054&amp;amp;oldid=27501&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
	<entry>
		<id>https://mediawiki.zeropage.org/index.php?title=AcceleratedC%2B%2B/Chapter7&amp;diff=27501&amp;oldid=prev</id>
		<title>imported&gt;Unknown at 05:22, 7 February 2021</title>
		<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=AcceleratedC%2B%2B/Chapter7&amp;diff=27501&amp;oldid=prev"/>
		<updated>2021-02-07T05:22:25Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[AcceleratedC++/Chapter6]]&lt;br /&gt;
| [[AcceleratedC++/Chapter8]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| __TOC__&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Chapter 7 Using associative containers =&lt;br /&gt;
기존에 이용한 vector, list는 모두 push_back, insert를 이용해서 요소를 넣어주었을 때,&lt;br /&gt;
요소가 순서대로 들어가는 순차 컨테이너이다.&lt;br /&gt;
이러한 순차컨테이너가 모든 프로그램의 자료구조의 대안이 되어 줄 수는 없다.&lt;br /&gt;
(예를 들자면 WikiPedia:Binary_search_tree, WikiPedia:AVL_tree 와 같이 최적화된 알고리즘을 통해서 우리는&lt;br /&gt;
단순한 순차검색보다 더욱 빠른 수행 시간을 갖는 프로그램의 작성을 하고 싶을 수 있다.)&lt;br /&gt;
&lt;br /&gt;
== 7.1 Containers that support efficient look-up ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;연관컨테이너(Associative Container)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
| 요소들을 삽입한 순서대로 배열하지 않고, 요소의 값에 따라 삽입 순서를 자동적으로 조정한다. 따라서 검색알고리즘의 수행시 기존의 순차컨테이너 이상의 성능을 보장한다.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Key&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
| 요소의 검색을 위해서 사용되는 검색어. 한개의 요소를 다른 요소와 구분하는 역할을 한다. 키는 요소의 변경시에 변경되지 않는 값이다. 이에 반하여 vector의 인덱스는 요소의 제거와 추가시 인덱스가 변화한다. 참조)DB의 WikiPedia:Primary_key 를 알아보자.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;&amp;amp;lt;map&amp;amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
| C++에서 제공되는 &amp;#039;&amp;#039;&amp;#039;연관 배열(Associative Array)&amp;#039;&amp;#039;&amp;#039;. 인덱스는 순서를 비교할 수 있는 것이면 무엇이든 가능하다. 단점으로는 자체적 순서를 갖기 때문에 순서를 변경하는 일반 알고리즘을 적용할 수 없다.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 7.2 Counting words ==&lt;br /&gt;
 //word_cout.cpp&lt;br /&gt;
 #include &amp;amp;lt;iostream&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;map&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;string&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 using std::cin;&lt;br /&gt;
 using std::cout;&lt;br /&gt;
 using std::endl;&lt;br /&gt;
 using std::map;&lt;br /&gt;
 using std::string;&lt;br /&gt;
 &lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
 	string s;&lt;br /&gt;
 	map&amp;amp;lt;string, int&amp;amp;gt; counters; // store each word and an associated counter&lt;br /&gt;
 &lt;br /&gt;
 	// read the input, keeping track of each word and how often we see it&lt;br /&gt;
 	while (cin &amp;amp;gt;&amp;amp;gt; s)&lt;br /&gt;
 		++counters[s];&lt;br /&gt;
 &lt;br /&gt;
 	// write the words and associated counts&lt;br /&gt;
 	for (std::map&amp;amp;lt;string, int&amp;amp;gt;::const_iterator it = counters.begin();&lt;br /&gt;
 	     it != counters.end(); ++it) {&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; it-&amp;amp;gt;first &amp;amp;lt;&amp;amp;lt; &amp;quot;\t&amp;quot; &amp;amp;lt;&amp;amp;lt; it-&amp;amp;gt;second &amp;amp;lt;&amp;amp;lt; endl;&lt;br /&gt;
 	}&lt;br /&gt;
 	return 0;&lt;br /&gt;
 }&lt;br /&gt;
* 상기에서 지정된 map&amp;lt;string, int&amp;gt;는 &amp;quot;string에서 int로의 map&amp;quot;라는 용어로 부름. string type key, int type value&lt;br /&gt;
* 최초로 등장한 string key에 대해서 map&amp;lt;k, v&amp;gt;은 새로운 요소를 생성. value-initialized.&lt;br /&gt;
* map은 []연산자를 통해 키값을 통해서 접근이 가능하나, 이 경우 string type key이기 때문에 모든 배열의 요소를 돌기위해서 일반적인 방식을 선택하였다. map의 각각의 요소는 &amp;#039;&amp;#039;&amp;#039;pair&amp;#039;&amp;#039;&amp;#039;라는 자료의 타입으로 구성. map은 pair의 first 요소에는 key, second 요소에는 value를 담는다.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| map&amp;amp;lt;class T&amp;amp;gt;::iterator&lt;br /&gt;
| K&lt;br /&gt;
| V&lt;br /&gt;
|-&lt;br /&gt;
| pair&lt;br /&gt;
| const K&lt;br /&gt;
| V&lt;br /&gt;
|}&lt;br /&gt;
 따라서 한번 성성된 Key는 변경이 불가하다.&lt;br /&gt;
&lt;br /&gt;
* Visual C++ 6.0 에서 소스를 컴파일 할때 책에 나온대로 (using namespace std를 사용하지 않고 위와 같이 사용하는 것들의 이름공간만 지정할 경우) map&amp;lt;string, int&amp;gt;::const_iterator 이렇게 치면 using std::map; 이렇게 미리 이름공간을 선언 했음에도 불구하고 에러가 뜬다.  6.0에서 제대로 인식을 못하는것 같다. 위와 같이 std::map&amp;lt;string, int&amp;gt;::const_iterator 이런식으로 이름 공간을 명시하거나 using namespace std; 라고 선언 하던지 해야 한다.&lt;br /&gt;
* Visual C++에서 map을 사용할때 warning이 많이 뜬다면 [http://zeropage.org/wiki/STL_2fmap] 이 페이지를 참고.&lt;br /&gt;
== 7.3 Generating a cross-reference table ==&lt;br /&gt;
 //cross_reference_table.cpp&lt;br /&gt;
 #include &amp;amp;lt;map&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;iostream&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;string&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;vector&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;split.h&amp;quot;  // 6.1.1. 절에서 만들어 놓은 함수&lt;br /&gt;
 &lt;br /&gt;
 using std::cin;            using std::cout;&lt;br /&gt;
 using std::endl;           using std::getline;&lt;br /&gt;
 using std::istream;        using std::string;&lt;br /&gt;
 using std::vector;         using std::map;&lt;br /&gt;
 &lt;br /&gt;
 // find all the lines that refer to each word in the input &lt;br /&gt;
 // 기본적으로 split 함수를 이용하여서 단어를 tokenize 한다. 만약 인자로 find_url을 주게되면 url이 나타난 위치를 기록한다.&lt;br /&gt;
 map&amp;amp;lt;string, vector&amp;amp;lt;int&amp;amp;gt; &amp;amp;gt; xref(istream&amp;amp;amp; in, vector&amp;amp;lt;string&amp;amp;gt; find_words(const string&amp;amp;amp;) = split)&lt;br /&gt;
 {&lt;br /&gt;
 	string line;&lt;br /&gt;
 	int line_number = 0;&lt;br /&gt;
 	map&amp;amp;lt;string, vector&amp;amp;lt;int&amp;amp;gt; &amp;amp;gt; ret;&lt;br /&gt;
 &lt;br /&gt;
 	// read the next line&lt;br /&gt;
 	while (getline(in, line)) {&lt;br /&gt;
 		++line_number;&lt;br /&gt;
 &lt;br /&gt;
 		// break the input line into words&lt;br /&gt;
 		vector&amp;amp;lt;string&amp;amp;gt; words = find_words(line);&lt;br /&gt;
 &lt;br /&gt;
 		// remember that each word occurs on the current line&lt;br /&gt;
 		for (vector&amp;amp;lt;string&amp;amp;gt;::const_iterator it = words.begin();&lt;br /&gt;
 		     it != words.end(); ++it)&lt;br /&gt;
 			ret[*it].push_back(line_number);   // ret[*it] == (it-&amp;amp;gt;second) = vector&amp;amp;lt;int&amp;amp;gt; 같은 표현이다.&lt;br /&gt;
                                                            // 따라서 백터에는 각 요소가 나타난 곳의 라인이 순서대로 저장된다.&lt;br /&gt;
 	}&lt;br /&gt;
 	return ret;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
 	// call `xref&amp;#039; using `split&amp;#039; by default&lt;br /&gt;
 	map&amp;amp;lt;string, vector&amp;amp;lt;int&amp;amp;gt; &amp;amp;gt; ret = xref(cin);&lt;br /&gt;
 &lt;br /&gt;
 	// write the results&lt;br /&gt;
 	for (map&amp;amp;lt;string, vector&amp;amp;lt;int&amp;amp;gt; &amp;amp;gt;::const_iterator it = ret.begin();&lt;br /&gt;
 	     it != ret.end(); ++it) {&lt;br /&gt;
 		// write the word&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; it-&amp;amp;gt;first &amp;amp;lt;&amp;amp;lt; &amp;quot; occurs on line(s): &amp;quot;;  // key 값인 string을 출력한다.&lt;br /&gt;
 &lt;br /&gt;
 		// followed by one or more line numbers&lt;br /&gt;
 		vector&amp;amp;lt;int&amp;amp;gt;::const_iterator line_it = it-&amp;amp;gt;second.begin();  // it-&amp;amp;gt;second == vector&amp;amp;lt;int&amp;amp;gt; 동일 표현&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; *line_it;	// write the first line number&lt;br /&gt;
 &lt;br /&gt;
 		++line_it;&lt;br /&gt;
 		// write the rest of the line numbers, if any&lt;br /&gt;
                 // second 값인 vector&amp;amp;lt;int&amp;amp;gt; 를 이용하여서 string이 나타난 각 줄의 번호를 출력한다.&lt;br /&gt;
 		while (line_it != it-&amp;amp;gt;second.end()) {&lt;br /&gt;
 			cout &amp;amp;lt;&amp;amp;lt; &amp;quot;, &amp;quot; &amp;amp;lt;&amp;amp;lt; *line_it;&lt;br /&gt;
 			++line_it;&lt;br /&gt;
 		}&lt;br /&gt;
 		// write a new line to separate each word from the next&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; endl;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	return 0;&lt;br /&gt;
 }&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;map&amp;lt;string, vector&amp;amp;lt;int&amp;amp;gt; &amp;gt; xref(istream&amp;amp; in, vector&amp;amp;lt;string&amp;amp;gt; find_words(const string&amp;amp;) = split)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
  &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;주의) STL을 이용하면서 많이 범하는 실수: &amp;gt; &amp;gt; (0) &amp;gt;&amp;gt;(X) 컴파일러는 &amp;gt;&amp;gt;에 대해서 operator&amp;gt;&amp;gt;()를 기대한다.&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
  기본인자(default argument)설정. 함수의 선언식에 매개변수로 = 를 할당하면 기본 인자로 등록된다.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;int main()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
  기본 변수 split 을 이용해서 입력받은 값을 이용해서 ret를 초기화한다.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| map&amp;lt;string, vector&amp;amp;lt;int&amp;amp;gt; &amp;gt;::const_iterator&lt;br /&gt;
| K&lt;br /&gt;
| V&lt;br /&gt;
|-&lt;br /&gt;
| pair&lt;br /&gt;
| first = string&lt;br /&gt;
| second = vector&amp;amp;lt;int&amp;amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
 &lt;br /&gt;
== 7.4 Generating sentences ==&lt;br /&gt;
 문법과 주어진 단어를 이용하여서 간단한 문장조합 프로그램을 만들어 본다. 제시된 규칙은 다음과 같다.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| cat&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| dog&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| table&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| large&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| brown&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| absurd&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| sits&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| jumps&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| on the stairs&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| under the sky&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| wherever it wants&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| the &amp;lt;noun-phrase&amp;gt; &amp;amp;lt;verb&amp;amp;gt; &amp;amp;lt;location&amp;amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
 상기의 규칙을 통해서 우리는 간단하게 &lt;br /&gt;
 ~cpp the table[noun-phrase, noun] jumps[verb] wherever it wants[location]&lt;br /&gt;
같은 프로그램을 만들어 볼 수 있다.&lt;br /&gt;
 참고) [http://douweosinga.com/projects/googletalk Google Talks] [http://bbs.kldp.org/viewtopic.php?t=54500 KLDP google talks perl clone]&lt;br /&gt;
&lt;br /&gt;
 === 7.4.1 규칙 표현하기 ===&lt;br /&gt;
 상기에서는 map&amp;lt;string, vector&amp;amp;lt;string&amp;amp;gt; &amp;gt;의 형태로 구현해야한다. 그러나 &amp;amp;lt;adjective&amp;amp;gt;, &amp;amp;lt;location&amp;amp;gt;, &amp;amp;lt;noun&amp;amp;gt;과 같이 동일한 키 값에 대해서 규칙이 여러개가 존재하는 경우를 다루기 위해서 &amp;#039;&amp;#039;&amp;#039;map &amp;lt;string, vector&amp;lt; vector&amp;amp;lt;string&amp;amp;gt; &amp;gt; &amp;gt;&amp;#039;&amp;#039;&amp;#039; 의 타입을 이용한다.&lt;br /&gt;
   // typedef 를 이용해서 좀더 읽기에 수월하도록 형을 지정하는 것이 가능하다.&lt;br /&gt;
 typedef vector&amp;amp;lt;string&amp;amp;gt; Rule;&lt;br /&gt;
 typedef vector&amp;amp;lt;Rule&amp;amp;gt; Rule_collection;&lt;br /&gt;
 typedef map&amp;amp;lt;string, Rule_collection&amp;amp;gt; Grammar;&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
 === 7.4.2 문법 읽어들이기 ===&lt;br /&gt;
 Grammar read_grammar(istream&amp;amp;amp; in) {&lt;br /&gt;
 	Grammar ret;&lt;br /&gt;
 	string line;&lt;br /&gt;
 	while (getline(in, line)) {&lt;br /&gt;
 		vector&amp;amp;lt;string&amp;amp;gt; entry = split(line); // split 함수를 이용해서 입력된 문자열을 &amp;#039; &amp;#039;를 기존으로 tokenize 한다.&lt;br /&gt;
 		if (!entry.empty())&lt;br /&gt;
 			ret[entry[0]].push_back(&lt;br /&gt;
 				Rule(entry.begin() + 1, entry.end()));&lt;br /&gt;
 			//vector&amp;amp;lt;string&amp;amp;gt;의 첫번째 요소를 entry의 키값으로 이용한다. 2번째 요소부터 마지막 요소까지는 entry의 값으로 저장한다.&lt;br /&gt;
 	}&lt;br /&gt;
 	return ret;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
 === 7.4.3 문장 생성하기 ===&lt;br /&gt;
 vector&amp;amp;lt;string&amp;amp;gt; gen_sentence(const Grammar&amp;amp;amp; g) {&lt;br /&gt;
 	vector&amp;amp;lt;string&amp;amp;gt; ret;&lt;br /&gt;
 	gen_aux(g, &amp;quot;&amp;amp;lt;sentence&amp;amp;gt;&amp;quot;, ret);&lt;br /&gt;
 	return ret;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 g:Grammar map에서 &amp;amp;lt;sentence&amp;amp;gt; 키값으로 실제의 문장에 관한 문법을 읽어들인다.&lt;br /&gt;
&lt;br /&gt;
 bool bracketed(const string&amp;amp;amp; s) {&lt;br /&gt;
 	return s.size() &amp;amp;gt; 1 &amp;amp;amp;&amp;amp;amp; s[0] == &amp;#039;&amp;amp;lt;&amp;#039; &amp;amp;amp;&amp;amp;amp; s[s.size()-1] == &amp;#039;&amp;amp;gt;&amp;#039;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //Recursive function call 재귀 함수의 이용&lt;br /&gt;
 void gen_aux(const Grammar&amp;amp;amp; g, const string&amp;amp;amp; word, vector&amp;amp;lt;string&amp;amp;gt;&amp;amp;amp; ret) {&lt;br /&gt;
 	if (!bracketed(word)) {&lt;br /&gt;
 		ret.push_back(word);		// 실제로 ret:vector&amp;amp;lt;string&amp;amp;gt; 에 값이 저장되고 재귀 함수가 끝이 나는 조건식이 된다.&lt;br /&gt;
 	} else {&lt;br /&gt;
 		Grammar::const_iterator it = g.find(word);		// g[word]로 참조를 할경우 map 컨테이너의 특성상 새로운 map이 생성된다.&lt;br /&gt;
 		if (it == g.end())&lt;br /&gt;
 			throw logic_error(&amp;quot;empty rule&amp;quot;);                // 규직이 존재하지 않는 다면 word로 전달된 규칙이 존재하지 않는 다는 말이된다.&lt;br /&gt;
                                                                         // 즉 입력이 잘못된 경우가 된다.&lt;br /&gt;
 &lt;br /&gt;
 		const Rule_collection&amp;amp;amp; c = it-&amp;amp;gt;second;                 &lt;br /&gt;
 &lt;br /&gt;
 		const Rule&amp;amp;amp; r = c[nrand(c.size())];&lt;br /&gt;
 &lt;br /&gt;
 		// &amp;amp;lt;noun-phrase&amp;amp;gt; 와 같이 연결된 문법이 &amp;amp;lt;noun&amp;amp;gt; 인경우에는 재귀적 함수 호출을 통해서 마지막 단어까지 내려간다.&lt;br /&gt;
 		// 마지막 단어까지 내려갓을 경우 재귀 함수를 호출하고 bracketed = false 의 조건이 되기 때문에 재귀 함수가 종료된다.&lt;br /&gt;
 		for(Rule::const_iterator i = r.begin(); i != r.end(); ++i) &lt;br /&gt;
 			gen_aux(g, *i, ret);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 map&amp;amp;lt;class T&amp;amp;gt;.find(K) : 주어진 키를 갖는 요소를 찾고, 있다면 그 요소를 가리키는 반복자를 리턴한다. 없다면 map&amp;amp;lt;class T&amp;amp;gt;.end()를 리턴한다.&lt;br /&gt;
 nrand(c.size()) : 7.4.4 절에서 설명함. pseudo rand 함수를 통해서 [0, c.size()) 의 범위를 갖는 가상적 임의의 수를 리턴한다.&lt;br /&gt;
 재귀함수의 호출은 반드시 함수의 내부에 재귀호출을 탈출 할 수 잇는 코드가 존재해야한다. 그렇지 않을 경우 stack_overflow가 발생한다.&lt;br /&gt;
&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
 	// generate the sentence&lt;br /&gt;
 	vector&amp;amp;lt;string&amp;amp;gt; sentence = gen_sentence(read_grammar(cin));&lt;br /&gt;
 &lt;br /&gt;
 	// write the first word, if any&lt;br /&gt;
 	vector&amp;amp;lt;string&amp;amp;gt;::const_iterator it = sentence.begin();&lt;br /&gt;
 	if (!sentence.empty()) {&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; *it;&lt;br /&gt;
 		++it;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	// write the rest of the words, each preceded by a space&lt;br /&gt;
 	while (it != sentence.end()) {&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; &amp;quot; &amp;quot; &amp;amp;lt;&amp;amp;lt; *it;&lt;br /&gt;
 		++it;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	cout &amp;amp;lt;&amp;amp;lt; endl;&lt;br /&gt;
 	return 0;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
 === 7.4.4 무작위 요소를 선택하기 ===&lt;br /&gt;
 int nrand(int n) {&lt;br /&gt;
 	if (n &amp;amp;lt;= 0 || n &amp;amp;gt; RAND_MAX)&lt;br /&gt;
 		throw domain_error(&amp;quot;Argument to nrand is out of range&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 	const int bucket_size = RAND_MAX / n;&lt;br /&gt;
 	int r;&lt;br /&gt;
 &lt;br /&gt;
 	do r = rand() / bucket_size;&lt;br /&gt;
 	while (r &amp;amp;gt;= n)&lt;br /&gt;
 	return r;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
 rand() 는 C Standard Library &amp;amp;lt;cstdlib&amp;amp;gt; 라이브러리에 존재한다. 일반적으로 cstdlib 에 정의된 RAND_MAX보다 작은 값을 임의적으로 리턴한다.&lt;br /&gt;
 RAND_MAX % n를 이용해서 임의의 수를 구할 경우 Pseudo 임의 값의 한계로 인해서 문제점이 발생한다.&lt;br /&gt;
** n 이 작은 경우: rand()함수는 홀수 짝수를 번갈아 출력하는 성질이 있기 때문에 n이 2일경우 0과 1이 반복적으로 출력된다.&lt;br /&gt;
** n 이 너무 큰 경우에도 특정한 수가 반복적으로 나타나게 된다.&lt;br /&gt;
 따라서 우리는 RAND_MAX를 n으로 나누어서 전체 RAND_MAX를 bucket이라는 단위로 나눈뒤에 이 bucket으로 rand()가 발생시키는 난수를 나누어 줌으로써 우리가 원하는 [0, n) 의 임의의 수를 얻을 수 있다.&lt;br /&gt;
&lt;br /&gt;
 === Addition. Entire Source Filie ===&lt;br /&gt;
 //grammar.cpp&lt;br /&gt;
 #include &amp;amp;lt;algorithm&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;cstdlib&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;iostream&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;map&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;stdexcept&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;string&amp;amp;gt;&lt;br /&gt;
 #include &amp;amp;lt;vector&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;quot;split.h&amp;quot;&lt;br /&gt;
 #include &amp;amp;lt;time.h&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 using std::istream;           using std::cin;&lt;br /&gt;
 using std::copy;              using std::cout;&lt;br /&gt;
 using std::endl;              using std::find;&lt;br /&gt;
 using std::getline;           using std::logic_error;&lt;br /&gt;
 using std::map;               using std::string;&lt;br /&gt;
 using std::vector;            using std::domain_error;&lt;br /&gt;
 using std::rand;&lt;br /&gt;
 &lt;br /&gt;
 typedef vector&amp;amp;lt;string&amp;amp;gt; Rule;&lt;br /&gt;
 typedef vector&amp;amp;lt;Rule&amp;amp;gt; Rule_collection;&lt;br /&gt;
 typedef map&amp;amp;lt;string, Rule_collection&amp;amp;gt; Grammar;&lt;br /&gt;
 &lt;br /&gt;
 // read a grammar from a given input stream&lt;br /&gt;
 Grammar read_grammar(istream&amp;amp;amp; in)&lt;br /&gt;
 {&lt;br /&gt;
 	Grammar ret;&lt;br /&gt;
 	string line;&lt;br /&gt;
 &lt;br /&gt;
 	// read the input&lt;br /&gt;
 	while (getline(in, line)) {&lt;br /&gt;
 &lt;br /&gt;
 		// `split&amp;#039; the input into words&lt;br /&gt;
 		vector&amp;amp;lt;string&amp;amp;gt; entry = split(line);&lt;br /&gt;
 &lt;br /&gt;
 		if (!entry.empty())&lt;br /&gt;
 			// use the category to store the associated rule&lt;br /&gt;
 			ret[entry[0]].push_back(&lt;br /&gt;
 				Rule(entry.begin() + 1, entry.end()));&lt;br /&gt;
 	}&lt;br /&gt;
 	return ret;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void gen_aux(const Grammar&amp;amp;amp;, const string&amp;amp;amp;, vector&amp;amp;lt;string&amp;amp;gt;&amp;amp;amp;);&lt;br /&gt;
 &lt;br /&gt;
 int nrand(int);&lt;br /&gt;
 &lt;br /&gt;
 vector&amp;amp;lt;string&amp;amp;gt; gen_sentence(const Grammar&amp;amp;amp; g)&lt;br /&gt;
 {&lt;br /&gt;
 	vector&amp;amp;lt;string&amp;amp;gt; ret;&lt;br /&gt;
 	gen_aux(g, &amp;quot;&amp;amp;lt;sentence&amp;amp;gt;&amp;quot;, ret);&lt;br /&gt;
 	return ret;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 bool bracketed(const string&amp;amp;amp; s)&lt;br /&gt;
 {&lt;br /&gt;
 	return s.size() &amp;amp;gt; 1 &amp;amp;amp;&amp;amp;amp; s[0] == &amp;#039;&amp;amp;lt;&amp;#039; &amp;amp;amp;&amp;amp;amp; s[s.size() - 1] == &amp;#039;&amp;amp;gt;&amp;#039;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void&lt;br /&gt;
 gen_aux(const Grammar&amp;amp;amp; g, const string&amp;amp;amp; word, vector&amp;amp;lt;string&amp;amp;gt;&amp;amp;amp; ret)&lt;br /&gt;
 {&lt;br /&gt;
 &lt;br /&gt;
 	if (!bracketed(word)) {&lt;br /&gt;
 		ret.push_back(word);&lt;br /&gt;
 	} else {&lt;br /&gt;
 		// locate the rule that corresponds to `word&amp;#039;&lt;br /&gt;
 		Grammar::const_iterator it = g.find(word);&lt;br /&gt;
 		if (it == g.end())&lt;br /&gt;
 			throw logic_error(&amp;quot;empty rule&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 		// fetch the set of possible rules&lt;br /&gt;
 		const Rule_collection&amp;amp;amp; c = it-&amp;amp;gt;second;&lt;br /&gt;
 &lt;br /&gt;
 		// from which we select one at random&lt;br /&gt;
 		const Rule&amp;amp;amp; r = c[nrand(c.size())];&lt;br /&gt;
 &lt;br /&gt;
 		// recursively expand the selected rule&lt;br /&gt;
 		for (Rule::const_iterator i = r.begin(); i != r.end(); ++i)&lt;br /&gt;
 			gen_aux(g, *i, ret);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
 	// generate the sentence&lt;br /&gt;
 	vector&amp;amp;lt;string&amp;amp;gt; sentence = gen_sentence(read_grammar(cin));&lt;br /&gt;
 &lt;br /&gt;
 	// write the first word, if any&lt;br /&gt;
 	vector&amp;amp;lt;string&amp;amp;gt;::const_iterator it = sentence.begin();&lt;br /&gt;
 	if (!sentence.empty()) {&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; *it;&lt;br /&gt;
 		++it;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	// write the rest of the words, each preceded by a space&lt;br /&gt;
 	while (it != sentence.end()) {&lt;br /&gt;
 		cout &amp;amp;lt;&amp;amp;lt; &amp;quot; &amp;quot; &amp;amp;lt;&amp;amp;lt; *it;&lt;br /&gt;
 		++it;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	cout &amp;amp;lt;&amp;amp;lt; endl;&lt;br /&gt;
 	return 0;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // return a random integer in the range `[0,&amp;#039; `n)&amp;#039;&lt;br /&gt;
 int nrand(int n)&lt;br /&gt;
 {&lt;br /&gt;
 	if (n &amp;amp;lt;= 0 || n &amp;amp;gt; RAND_MAX)&lt;br /&gt;
 		throw domain_error(&amp;quot;Argument to nrand is out of range&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 	const int bucket_size = RAND_MAX / n;&lt;br /&gt;
 	int r;&lt;br /&gt;
 &lt;br /&gt;
 	do r = rand() / bucket_size;&lt;br /&gt;
 	while (r &amp;amp;gt;= n);&lt;br /&gt;
 &lt;br /&gt;
 	return r;&lt;br /&gt;
 }&lt;br /&gt;
  &lt;br /&gt;
== 7.5 A note on performance ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Hash Table&lt;br /&gt;
| 각 키값에 대하여 해쉬 값을 제공해야함. 성능이 해쉬 함수에 크게 영향을 받음. 요소들을 원하는 순서대로 얻기 쉽지 않음&lt;br /&gt;
|-&lt;br /&gt;
| Associative Container in STL&lt;br /&gt;
| 키 값이 &amp;lt;. == 연산으로 비교만 된다면 무엇이든 무관, 요소로의 접근 시간이 logn으로 커짐. 항상 정렬 상태를 유지&lt;br /&gt;
|}&lt;br /&gt;
STL의 Associative Container는 balanced self-adjusting tree(참고 WikiPedia:AVL_tree )구조를 이용하여서 연관 컨테이너를 구현했음.&lt;br /&gt;
----&lt;br /&gt;
[[AcceleratedC++]]&lt;br /&gt;
&lt;/div&gt;</summary>
		<author><name>imported&gt;Unknown</name></author>
	</entry>
</feed>