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

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

ただいまの
回答率

88.93%

c++ 類似度計算とリスト構造を理解できていないため、結果が出力されません。

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 273

asdfgpo

score 0

main文内の類似度計算結果が上手くできません。恐らくリストの先頭に戻す方法が間違っていると思うのですが、いまいちリスト構造を理解できておらず苦戦しています。よろしければ、ご教授お願いします。
<内容> 
mk_tfidf_list関数は、引数として指定した記事IDに含まれる名詞のTF・IDF値をリストにして返す関数です。最終的に類似度計算結果を出力します。

以下コード
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cmath>

#define N 227

using namespace std;

struct cell
{
   string key;
   int value; 
   double tfidf;  

   struct cell *next;
};

struct cell* make_cell(int value, string key) {
    struct cell* mk_cell;
    mk_cell = new struct cell;
    mk_cell->key = key;
    mk_cell->value = value;
    mk_cell->next = NULL;
    return mk_cell;
}

struct cell* search_cell(string key, cell* head) {
    struct cell* buf;
    buf = head;
    while (buf != NULL) {
        if (buf->key == key) {
            return buf;
        }
        buf = buf->next;
    }
    return NULL;
}

using namespace std;

// 機能:引数として指定した記事IDに含まれる名詞のTF・IDF値をリストにして返す
// 備考:TF・IDF計算プログラムを関数にしたもの
struct cell *mk_tfidf_list(string input_id)
{  
    int size = 0;
    ifstream f_data("posdata.txt"); // posdata.txt ファイルオープン 
    string line;
    struct cell* head;
    head = NULL;
    // postdata.txtから1行ずつ読み込み 
    while (f_data >> line) {
        // 記事IDと名詞例(noun1, noun2,...)のデータに分割 
        int index = line.find(",");
        string f_id = line.substr(0, index);
        string w_str = line.substr(index + 1);
        if (f_id == input_id) {
            // split 名詞列のデータから名詞を1つずつ取り出し 
            int n;
            for (int i = 0; i <= w_str.length(); i = n + 1) {
                n = w_str.find_first_of(",", i);
                if (n == string::npos) {
                    n = w_str.length();
                }
                string word = w_str.substr(i, n - i); //単語 
                if (search_cell(word, head) == NULL) { //単語がなかった場合 
                    struct cell* tmp;
                    tmp = make_cell(1, word);
                    tmp->next = head;
                    head = tmp;
                    size++;
                }
                else if (search_cell(word, head) != NULL) {
                    cell* tmp2;
                    tmp2 = search_cell(word, head);
                    tmp2->value++;
                }
            }
        }
    }
    ifstream fin("df.txt");
    string line2;
    cell* head2;
    head2 = NULL;
    while (fin >> line2) {
        int index = line2.find(",");
        string f_id2 = line2.substr(0, index);
        string w_str2 = line2.substr(index + 1);
        int num2 = atoi(w_str2.data());
        cell* tmp2 = make_cell(num2, f_id2);
        tmp2->next = head2;
        head2 = tmp2;
    }
    cell* buf = head;

    while (buf != NULL) {
        cell *tmp = search_cell(buf->key, head2);
        if (tmp != NULL) {
            buf->tfidf = buf->value * log2(N * 1.0 / tmp->value);
        }
        buf = buf->next;
    }
    f_data.close();
   buf = head;
   return buf;
}

int main(int argc, char *argv[])
{
    string id1 = argv[1];
    string id2 = argv[2];

    // 指定した記事ID1のTF・IDFリスト
    struct cell *tf_idf1;
    tf_idf1 = mk_tfidf_list(id1);

    // 指定した記事ID2のTF・IDFリスト
    struct cell *tf_idf2;
    tf_idf2 = mk_tfidf_list(id2);

    double sim = 0;
    double naiseki = 0;
    double size1 = 0;
    double size2 = 0;
    int cnt = 0;

    ```以下の部分で間違いがあると思われます。  
コード  
while (tf_idf1 != NULL) {  
if (cnt != 0) {  
tf_idf2 = tf_idf2->next;  
}  
cnt++;  
if (tf_idf1->key == tf_idf2->key) {  
naiseki += tf_idf1->tfidf * tf_idf2->tfidf;  
tf_idf1 = tf_idf1->next;  
cell *head = mk_tfidf_list(id2);  
tf_idf2 = head;  
cnt = 0;  
}  
if (tf_idf2 == NULL) {  
cell *head = mk_tfidf_list(id2);  
tf_idf2 = head;  
tf_idf1 = tf_idf1->next;  
cnt = 0;  
}  
}  

cell *head = mk_tfidf_list(id1);  
tf_idf1 = head;  
cell *head2 = mk_tfidf_list(id2);  
tf_idf2 = head2;  


while(tf_idf1 != NULL){  
size1 += tf_idf1->tfidf * tf_idf1->tfidf;  
tf_idf1 = tf_idf1->next;  
}  

while(tf_idf2 != NULL){  
size2 += tf_idf2->tfidf * tf_idf2->tfidf;  
tf_idf2 = tf_idf2->next;  
}  


sim = naiseki / (sqrt(size2) * sqrt(size1));  
cout << id1 << " - " << id2 << " : " << sim << endl;  
return 0;  
}  

```

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正の依頼

  • cateye

    2020/07/17 12:12 編集

    見にくいので、ソースは<code>で出てくる```と```の中に貼り付けて下さい。
    また、Cのヘッダファイル(stdlib.hなど)は、頭にcを付けて.hを外すとc++のヘッダにできます↓
    e.g. string.h→cstring

    キャンセル

  • asdfgpo

    2020/07/18 00:38

    失礼しました。コードの貼り付けと、頭にcを付けなおしました。

    キャンセル

まだ回答がついていません

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

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

関連した質問

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