質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Mecab

Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

Q&A

解決済

1回答

2528閲覧

分解できた文章を配列に入れて、メモに書いた文字と比較して文字を置き換えたい

KZK13

総合スコア43

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Mecab

Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

0グッド

0クリップ

投稿2020/07/19 17:17

mecabを使うことに成功したのですが、文章"頑張れカカロット、貴様がナンバーワンだ。"を分解すると以下のように品詞が出てきますが、この品詞はいらないのですが、
消す方法などはないでしょうか?

頑張れ 動詞,自立,*,*,五段・ラ行,命令e,頑張る,ガンバレ,ガンバレ カカロット 名詞,一般,*,*,*,*,* 、 記号,読点,*,*,*,*,、,、,、 貴様 名詞,一般,*,*,*,*,貴様,キサマ,キサマ が 助詞,格助詞,一般,*,*,*,が,ガ,ガ ナンバーワン 名詞,一般,*,*,*,*,ナンバーワン,ナンバーワン,ナンバーワン だ 助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ 。 記号,句点,*,*,*,*,。,。,。 EOS

というのも、分解できた文章を配列に入れて、メモに書いた文字と比較して文字を置き換えたいためです。
例えば、メモに以下のようなことが書いて合ったとして、

頑張れ→おめえも頑張れ。 カカロット→ベジータ。

bufferに入った文章がmecabにより分解され、
「頑張れ」「カカロット」「、」「貴様」「が」「ナンバーワン」「だ」「。」
メモに書いた文字と比較され、「おめえも頑張れ。ベジータ」となるようにしたいと考えたためです。

以下はコードです。

#pragma warning(disable: 4996) #include "DxLib.h" #include <string> #include <iostream> #include <mecab.h> #pragma comment(lib, "libmecab.lib") int InputHandle; char buffer[256]; const char* result; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { SetGraphMode(1500, 780, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 // DXライブラリの初期化 if (DxLib_Init() == -1) return -1; SetFontSize(33); //サイズを42に変更 // 描画先を裏にする SetDrawScreen(DX_SCREEN_BACK); InputHandle = MakeKeyInput(150, FALSE, FALSE, FALSE); //これで総計150バイトの文字データを保持できる。 // 作成したキー入力ハンドルをアクティブにする SetActiveKeyInput(InputHandle); while (ProcessMessage() == 0) { // 画面の初期化 ClearDrawScreen(); //まずは描画する部分から作る。 // 入力モードを描画 DrawKeyInputModeString(1500, 0); // 入力モードを描画 // 入力途中の文字列を描画 DrawKeyInputString(0, 0, InputHandle);//InputHandleはint型とリファレンスに書いてあったんで //エンターキーが押された時の部分。 if (CheckKeyInput(InputHandle) != 0) { // 入力された文字列を取得、その文字列を数値に変換 GetKeyInputString(buffer, InputHandle);//ここでInputHandleに入力された文字列の数値をGetKeyInputStringにより文字コードに変換したものを上でchar型で定義したbufferに入れる。 MeCab::Tagger* tagger = MeCab::createTagger(""); result = tagger->parse(buffer); //duration = 1; // 再度インプットハンドルをアクティブにする SetActiveKeyInput(InputHandle); // 入力文字列を初期化する SetKeyInputString("", InputHandle); //++mozicount; } DrawFormatString(100, 600, GetColor(175, 80, 100), "resultは%s", result); // 裏画面の内容を表画面に反映させる ScreenFlip(); } // 用済みのインプットハンドルを削除する DeleteKeyInput(InputHandle); // 画面の初期化 ClearDrawScreen(); // 裏画面の内容を表画面に反映させる ScreenFlip(); // キー入力待ち // WaitKey(); //ループないやループから出た後で何かしらの問題が発生したら終了する。 // DXライブラリの使用終了 DxLib_End(); // 終了 return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

C++

1#pragma warning(disable: 4996) 2#include "DxLib.h" 3#include <mecab.h> 4#pragma comment(lib, "libmecab.lib") 5 6int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) 7{ 8 SetGraphMode(1500, 780, 32); // ウィンドウの大きさを指定 9 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 10 if (DxLib_Init() == -1) return -1; // DXライブラリの初期化 11 SetFontSize(33); // サイズを変更 12 SetDrawScreen(DX_SCREEN_BACK); // 描画先を裏にする 13 int InputHandle = MakeKeyInput(256, FALSE, FALSE, FALSE); 14 SetActiveKeyInput(InputHandle); // 作成したキー入力ハンドルをアクティブにする 15 char buffer[256]; 16 const char *result = ""; 17 char buf[4096]; 18 const char *words[100]; 19 int n = 0; 20 unsigned word_color = GetColor(0, 255, 255); 21 22 while (ProcessMessage() == 0) { 23 ClearDrawScreen(); // 画面の初期化 24 DrawKeyInputModeString(1500, 0); // 入力モードを描画 25 DrawKeyInputString(0, 0, InputHandle); // 入力途中の文字列を描画 26 27 if (CheckKeyInput(InputHandle) != 0) { //エンターキーが押された時 28 GetKeyInputString(buffer, InputHandle); // 入力された文字列を取得 29 30 MeCab::Tagger* tagger = MeCab::createTagger(""); 31 result = tagger->parse(buffer); 32 strcpy_s(buf, sizeof buf, result); 33 delete tagger; 34 n = 0; 35 words[n] = strtok(buf, "\t\n"); 36 while (n < 100 && words[n]) { 37 strtok(NULL, "\t\n"); 38 words[++n] = strtok(NULL, "\t\n"); 39 } 40 41 SetActiveKeyInput(InputHandle); // 再度インプットハンドルをアクティブにする 42 SetKeyInputString("", InputHandle); // 入力文字列を初期化する 43 } 44 //DrawFormatString(100, 600, GetColor(175, 80, 100), "resultは%s", result); 45 for (int i = 0; i < n; i++) 46 DrawString(100, 200 + i*40, words[i], word_color); 47 48 ScreenFlip(); // 裏画面の内容を表画面に反映させる 49 } 50 DeleteKeyInput(InputHandle); // 用済みのインプットハンドルを削除する 51 DxLib_End(); // DXライブラリの使用終了 52 return 0; 53}

追記
MeCab には品詞を出さないオプションがあるではありませんか。

C++

1#pragma warning(disable: 4996) 2#pragma comment(lib, "libmecab.lib") 3#include <mecab.h> 4#include <iostream> // cout 5#include <sstream> // istringstream 6#include <string> // string 7using namespace std; 8 9int main() { 10 char buffer[] = "頑張れカカロット、貴様がナンバーワンだ。"; 11 MeCab::Tagger* tagger = MeCab::createTagger("-Owakati"); 12 const char* result = tagger->parse(buffer); 13 cout << "[" << result << "]\n" "----------\n"; 14 istringstream iss(result); 15 string word; 16 while (iss >> word) cout << "[" << word << "]\n"; 17 delete tagger; 18 return 0; 19}

実行結果

[頑張れ カカロット 、 貴様 が ナンバーワン だ 。 ] ---------- [頑張れ] [カカロット] [、] [貴様] [が] [ナンバーワン] [だ] [。]

追記2
MeCab::Tagger* tagger = MeCab::createTagger(""); で作った
MeCab::Tagger オブジェクトは、delete tagger; で解体しないと
メモリーリークするので、上の 2つのコードを修正しました。

投稿2020/07/19 18:51

編集2020/07/22 12:43
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KZK13

2020/07/19 19:59

どうもありがとうございます。 お時間のある時で構いませんので、他の質問にも答えて頂けるとありがたいです。 どうかよろしくお願いいたします。
episteme

2020/07/19 23:36

> bufferに入った文章がmecabにより分解され、 >「頑張れ」「カカロット」「、」「貴様」「が」「ナンバーワン」「だ」「。」 > メモに書いた文字と比較され、「おめえも頑張れ。ベジータ」となるようにしたいと考えたためです。 他の質問ってこれ? 変換規則を明示してください。 mecabが切り出した単語の群 と 入力文字列 から あなたの望む文字列を組み立てるルールを。
kazuma-s

2020/07/21 00:48

単語だけを切り出すコードの例を書いたつもりなのに、それを理解して応用しようとしないから、また無意味な質問を繰り返すのです。 https://teratail.com/questions/279207
episteme

2020/07/21 00:51

彼の「どうもありがとうございます」に虚しさを覚えるよね。
kazuma-s

2020/07/21 12:03

解決済みになっていますが、コードが理解できたということでしょうか? 理解できたのなら、コードの詳細な説明をお願いします。
KZK13

2020/07/21 13:08

打ち込んだ文章を品詞を消した上で分解できるコードだと認識しています。
episteme

2020/07/21 15:58

> 打ち込んだ文章を品詞を消した上で分解できるコードだと認識しています。 それは what:「何をしているか」 kazuma-sさんが求めているのは how:「"どうやって"それを実現しているか」なんだがな。
KZK13

2020/07/22 06:39

>>MeCab には品詞を出さないオプションがあるではありませんか。 その方法をどうやって探したのでしょうか。
kazuma-s

2020/07/22 08:01

mecab tagger parse C++ でググって、 http://www.mwsoft.jp/programming/nlp/mecab_cpp.html に書いてあった。 "ジョニーは戦場へ行った" の例があったから、あなたも見たのでは? それより、コードはちゃんと読みましたか? strtok って何をする関数か分かっていますか? グローバル変数を使わなくてもコードが書けることが分かりませんか?
KZK13

2020/07/22 10:06

strtok は文章をトークン(単語)ごとに分ける関数だとわかりました。 すなわち変数を使わなくても分解できるとわかりました。 あの、単語ごとにわける部分はわかったのですが、どこの部分で単語を説明する品詞を消しているのでしょうか? また 元々のこちらのプログラム https://pastebin.com/dB2vvHwV にkazuma-sさんから頂いたプログラムを組み込みました。 そして以下 https://pastebin.com/izXK9jcJ のようになってビルドはうまくいったのですが、 「タバコ」と入力するとメモに書いた「健康に悪いのでやめたほうがいいですね」と表示されるのですが、組み込んだ後では「タバコ」と入力するとウィンドウが閉じてしまいます。 何がいけないのでしょうか。 if (my_str2(buffer2, words[1]) == 1)の部分は怪しく感じます。 どうかよろしくお願いいたします。
episteme

2020/07/22 11:21

> 単語ごとにわける部分はわかったのですが、どこの部分で単語を説明する品詞を消しているのでしょうか? words[n] = strtok(buf, "\t\n"); // 0番目 while (n < 100 && words[n]) { strtok(NULL, "\t\n"); // 1, 3, 5 ... 番目 words[++n] = strtok(NULL, "\t\n"); // 2, 4, 6... 番目 } 奇数番目(品詞等が得られるはず)を"空読み"してる。
episteme

2020/07/22 13:41

やっぱり理解してなかったね、strtokのふるまい。 howが語れないから他のコードに使えない。 なので貰ったコードのツギハギすらできず、同じ誤りで質問を繰り返す。 > 単語だけを切り出すコードの例を書いたつもりなのに、それを理解して応用しようとしないから、また無意味な質問を繰り返すのです。 > https://teratail.com/questions/279207
KZK13

2020/07/22 15:41

https://pastebin.com/eHJ500WU epistemeさんの分かりにくい解説は当てにならず(余計なことまで書いてあるし)、word[]の中身を確認して言ったら原因がわかりました。
episteme

2020/07/23 12:40 編集

原因? 何の原因ですか? KZK13,kazuma-s,episteme の誰一人として何かの原因を問うてはいませんが。
KZK13

2020/08/03 08:27

今更ですいません、 while (n < 100 && words[n]) { strtok(NULL, "\t\n"); words[++n] = strtok(NULL, "\t\n"); } の部分が「名詞,一般,*,*,*,*,タバコ,タバコ,タバコ」などの必要ない部分を省いていると思うのですが、 どうやって省いているのか処理の動きがわかりません。どうか教えて頂けないでしょうか?
episteme

2020/08/03 08:45

> word[]の中身を確認して言ったら原因がわかりました。 これは「"どこの部分で単語を説明する品詞を消しているのでしょうか?"の答えにたどり着いた」 を意味していないということか。 ならば何の原因がわかったのですか?
KZK13

2020/08/03 13:43

>>「タバコ」と入力するとウィンドウが閉じてしまいます。 のウィンドウが閉じる原因がわかったのです。 if (my_str2(buffer2, words[0]) == 1)と書くところを if (my_str2(buffer2, words[1]) == 1)と書いてしまったため、入力した文字が正しくwords[]に入らなかったとわかりました。 この原因とは別に、原因ではないのですが、プログラムの 「"どこの部分で単語を説明する品詞を消しているのか?"という疑問が出てきました。 多分、 while (n < 100 && words[n]) { strtok(NULL, "\t\n"); words[++n] = strtok(NULL, "\t\n"); } の部分で品詞を消していると思うのですが、 多分、 strtok(NULL, "\t\n");の部分は\t\nがなかった場合、空(NULL)の返り値を渡すため、 「タバコ」の後に続く「名詞,一般,*,*,*,*,タバコ,タバコ,タバコ」の部分は空になり、「タバコ」のみがwords[++n] に渡され、それを繰り返すことで、品詞を含まない単語のみがwords[++n] に入り、「タバコ」「を」「吸っている」などと表せるのかなと考えています。
episteme

2020/08/03 13:54

その推理/推察が正しいか、コード書いて試してみればいい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問