のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

C++でMeCabを使おう

Sponsored Links

皆さんこんにちは
お元気ですか。私は元気です。

今日はC++でMeCabを使います。
MeCabのインストールはこちらをご確認くださいませ。

MeCabの使い方

一番オーソドックスな使い方を見てみましょう。

コンパイルコマンド

初めにコンパイルについてですが、

g++ `mecab-config --cflags` `mecab-config --libs` [file name]

簡単な形態素解析

ソースコード
void parseTest(){
	char input[1024] = "私は朝ごはんを食べます";

	MeCab::Tagger *tagger = MeCab::createTagger("");
	const char *result = tagger->parse(input);

	std::cout << result << std::endl;

	delete tagger;
}
出力
私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
朝	名詞,副詞可能,*,*,*,*,朝,アサ,アサ
ごはん	名詞,一般,*,*,*,*,ごはん,ゴハン,ゴハン
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
食べ	動詞,自立,*,*,一段,連用形,食べる,タベ,タベ
ます	助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
EOS

最も簡単な使い方です。

わかち書き

ソースコード
void wakachigakiTest(){
	char input[1024] = "私は朝ごはんを食べます";

	MeCab::Tagger *tagger = MeCab::createTagger("-Owakati");
	const char *result = tagger->parse(input);

	std::cout << result << std::endl;

	delete tagger;
}
出力
私 は 朝 ごはん を 食べ ます

いわゆる分割

ノードごとに頑張る。

ソースコード
void parseNodeTest(){
	char input[1024] = "私は朝ごはんを食べます";

    MeCab::Tagger *tagger = MeCab::createTagger("");
    const MeCab::Node* node = tagger->parseToNode(input);

    for (; node; node = node->next) {
    	cout << string(node->surface,node->length) << endl;
        std::cout << "==========" << std::endl;
        std::cout << "id        : " << node->id        << std::endl;
        std::cout << "surface   : " << node->surface   << std::endl;
        std::cout << "feature   : " << node->feature   << std::endl;
        std::cout << "length    : " << node->length    << std::endl;
        std::cout << "rlength   : " << node->rlength   << std::endl;
        std::cout << "rcAttr    : " << node->rcAttr    << std::endl;
        std::cout << "lcAttr    : " << node->lcAttr    << std::endl;
        std::cout << "posid     : " << node->posid     << std::endl;
        std::cout << "char_type : " << (int)node->char_type << std::endl;
        std::cout << "stat      : " << (int)node->stat      << std::endl;
        std::cout << "isbest    : " << (int)node->isbest    << std::endl;
        std::cout << "alpha     : " << node->alpha     << std::endl;
        std::cout << "beta      : " << node->beta      << std::endl;
        std::cout << "prob      : " << node->prob      << std::endl;
        std::cout << "wcost     : " << node->wcost     << std::endl;
        std::cout << "cost      : " << node->cost      << std::endl;
    }

    delete tagger;
}
出力

長いので、最初だけ

==========
id        : 1
surface   : 私は朝ごはんを食べます
feature   : 名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
length    : 3
rlength   : 3
rcAttr    : 1306
lcAttr    : 1306
posid     : 59
char_type : 2
stat      : 0
isbest    : 1
alpha     : 0
beta      : 0
prob      : 0
wcost     : 3480
cost      : 2737

この書き方は最も使われる内容で、分割されたノードごとに利用されます。
lengthで長さを示します。一番注意しなければならないのは、surfaceです。
なぜなら、surfaceにのっているのは文章全てです。
string(node->surface,node->length) を使って解析している言葉だけを切り出しています。
後はfeatureで名詞だけを取り出すこともあります。

気が向いたらこれを使って別のプログラムでも書きます。