ページ 11

自分で改造したプログラムがわかりません

Posted: 2013年7月12日(金) 22:38
by ただの屍のようだ
元のサンプルプログラム:diction.txt(単語20159個)からアルファベットの組み合わせが同じの単語グループをすべて抜き出す。
改造後のプログラム:diction.txt(単語20159個)から引数で指定した単語とアルファベットの組み合わせが同じのグループを抜き出す。
疑問に思う点が主に2つ。
1.PS.hの比較関数はどうしてメンバ関数ではなく、関数オブジェクトなのですか?(これは元々で一切変更を加えてません)
2.メインプログラムの27行目がどうしてうまくグループを抜き出せるのですか?(これは自分が書きましたが、sortせずともうまくいったのは予想外です)

コード:

// PS.h ヘッダ
#ifndef _PAIR_IN_STRUCT
#define _PAIR_IN_STRUCT
#include<string>
#include<functional>
#include<algorithm>
using namespace std;

struct PS : pair<string,string>{
	PS() : pair<string,string>(string(),string()){}
	PS(const string &s) : pair<string,string>(s,s){ sort(first.begin(),first.end());}
	operator string() const{return second;}
};

struct FirstLess : binary_function<PS,PS,bool>{
	bool operator()(const PS &a,const PS &b){return a.first < b.first;}
}firstLess;
struct FirstEqual : binary_function<PS,PS,bool>{
	bool operator()(const PS &a,const PS &b){return a.first == b.first;}
}firstEqual;

#endif

コード:

#include<iostream>
#include<iomanip>
#include<vector>
#include<iterator>
#include<fstream>
#include "PS.h";
#include <cassert>
using namespace std;

const int DICTION_SIZE = 20159;

ostream &error_message(ostream &stream){
	stream << "Could not find the word";
	return stream;
}

int main(int argc,char *argv[]){
	char path[] = "C:\\Users\\Owner\\Desktop\\src\\diction.txt";
	ifstream ifs(path);
	assert(ifs!=NULL && argc>1);
	vector<PS> dictionary;

	dictionary.reserve(DICTION_SIZE);
	copy(istream_iterator<string>(ifs),istream_iterator<string>(),back_inserter(dictionary));
	sort(dictionary.begin(),dictionary.end(),firstLess);
	while(--argc){
		pair<vector<PS>::iterator,vector<PS>::iterator> pi = equal_range(dictionary.begin(),dictionary.end(),string(*++argv),firstLess);
		if(pi.first==pi.second)	cout << error_message;
		copy(pi.first,pi.second,ostream_iterator<string>(cout,"\t"));
		cout << endl;
	}
	return 0;
}


Re: 自分で改造したプログラムがわかりません

Posted: 2013年7月13日(土) 12:26
by ただの屍のようだ
n十年プログラミング経験があっても、C++のジェネリックプログラミングスタイルを初見で理解するには難しいですね。
(だからといっていちいちコメント書いたら、コメントだらけになってしまいます)
元のコードを読み直したら、メインプログラムで関数アダプタが使われていました。よって、質問1は解決しました。
質問2は引き続き、回答を待ちます。

Re: 自分で改造したプログラムがわかりません

Posted: 2013年7月13日(土) 13:16
by a5ua
sortせずともうまくいったのは予想外です
PSのコンストラクタ(PS.h 11行目)で文字列ペアのfirst要素をソートしていますよ。
例えば、"the"という文字列からは、("eht", "the")というPSのオブジェクトが生成されます。

Re: 自分で改造したプログラムがわかりません

Posted: 2013年7月13日(土) 13:18
by ただの屍のようだ
いいところに聞いてくれましたね!
その通りです、渡したのはstring()のはずなのに、どうやら受けた先ではPS(const string&)のようです。
そこを説明してほしい

Re: 自分で改造したプログラムがわかりません

Posted: 2013年7月13日(土) 13:44
by a5ua
//説明になっているかわかりませんが。。。

コード:

vector<PS> dictionary;

PS ps(string("qw4iqty"));
dictionary.push_back(ps);
上のように、dictionaryに要素を追加するには、PS型のオブジェクトを作らなければならないように見えます。

しかし、実際には以下のコードで要素を追加できます。
これは、PS(const string &s)が「変換コンストラクタ」として暗黙的に呼び出されているためです。

コード:

vector<PS> dictionary;
dictionary.push_back(string("qw4iqty"));
ちなみに、変換コンストラクタが暗黙的に呼び出されないようにするには、コンストラクタの宣言時にexplicitをつけます。
(こうするとコンパイルエラーになるはずです)

コード:

explicit PS(const string &s) : ...(以下略)

Re: 自分で改造したプログラムがわかりません

Posted: 2013年7月13日(土) 14:07
by ただの屍のようだ
まさか、暗黙のコンストラクタ呼び出しに気付かなかったとは。。。
ありがとうございます。

Re: 自分で改造したプログラムがわかりません

Posted: 2013年7月16日(火) 13:24
by ただの屍のようだ
さて、ネットワークの勉強で精一杯、ジェネリックプログラミングを本格的に学習できるのはおそらく11月以降となるでしょう。
ですが、これからの質問となるコードはすべてジェネリックプログラミングスタイルがベースとなります。
親切なみなさんならきっと答えてくれると信じています。よろしくおねがいします。