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

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

ただいまの
回答率

88.92%

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

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 924

KZK13

score -9

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;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

#pragma warning(disable: 4996)
#include "DxLib.h"
#include <mecab.h>
#pragma comment(lib, "libmecab.lib")

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    SetGraphMode(1500, 780, 32);        // ウィンドウの大きさを指定
    ChangeWindowMode(TRUE);             // 全画面ではなくウインドウを使用
    if (DxLib_Init() == -1) return -1;  // DXライブラリの初期化
    SetFontSize(33);                    // サイズを変更
    SetDrawScreen(DX_SCREEN_BACK);      // 描画先を裏にする
    int InputHandle = MakeKeyInput(256, FALSE, FALSE, FALSE);
    SetActiveKeyInput(InputHandle); // 作成したキー入力ハンドルをアクティブにする
    char buffer[256];
    const char *result = "";
    char buf[4096];
    const char *words[100];
    int n = 0;
    unsigned word_color = GetColor(0, 255, 255);

    while (ProcessMessage() == 0) {
        ClearDrawScreen(); // 画面の初期化
        DrawKeyInputModeString(1500, 0); // 入力モードを描画
        DrawKeyInputString(0, 0, InputHandle); // 入力途中の文字列を描画

        if (CheckKeyInput(InputHandle) != 0) { //エンターキーが押された時
            GetKeyInputString(buffer, InputHandle); // 入力された文字列を取得

            MeCab::Tagger* tagger = MeCab::createTagger("");
            result = tagger->parse(buffer);
            strcpy_s(buf, sizeof buf, result);
            delete tagger;
            n = 0;
            words[n] = strtok(buf, "\t\n");
            while (n < 100 && words[n]) {
                strtok(NULL, "\t\n");
                words[++n] = strtok(NULL, "\t\n");
            }

            SetActiveKeyInput(InputHandle); // 再度インプットハンドルをアクティブにする
            SetKeyInputString("", InputHandle); // 入力文字列を初期化する
        }
        //DrawFormatString(100, 600, GetColor(175, 80, 100), "resultは%s", result);
        for (int i = 0; i < n; i++)
            DrawString(100, 200 + i*40, words[i], word_color); 

        ScreenFlip(); // 裏画面の内容を表画面に反映させる
    }
    DeleteKeyInput(InputHandle); // 用済みのインプットハンドルを削除する
    DxLib_End(); // DXライブラリの使用終了
    return 0;
}


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

#pragma warning(disable: 4996)
#pragma comment(lib, "libmecab.lib")
#include <mecab.h>
#include <iostream>  // cout
#include <sstream>   // istringstream
#include <string>    // string
using namespace std;

int main() {
    char buffer[] = "頑張れカカロット、貴様がナンバーワンだ。";
    MeCab::Tagger* tagger = MeCab::createTagger("-Owakati");
    const char* result = tagger->parse(buffer);
    cout << "[" << result << "]\n" "----------\n";
    istringstream  iss(result);
    string word;
    while (iss >> word) cout << "[" << word << "]\n";
    delete tagger;
    return 0;
}


実行結果

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/03 17:45

    > word[]の中身を確認して言ったら原因がわかりました。

    これは「"どこの部分で単語を説明する品詞を消しているのでしょうか?"の答えにたどり着いた」 を意味していないということか。

    ならば何の原因がわかったのですか?

    キャンセル

  • 2020/08/03 22: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] に入り、「タバコ」「を」「吸っている」などと表せるのかなと考えています。

    キャンセル

  • 2020/08/03 22:54

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

    キャンセル

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

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • トップ
  • Cに関する質問
  • 分解できた文章を配列に入れて、メモに書いた文字と比較して文字を置き換えたい