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

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

ただいまの
回答率

87.34%

C/C++ STL algorithm find_if の使い方がわからない。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,082

score -23

STL を使って vector<string> に格納したテキストのないようから
特定の文字列を含んでいる場合、真を返し、イテレータで受け取り
そのイテレータをインクリメンタルすることで、特定の文字列を含んだ
内容を全部、出力した。
ここでは、特定の文字列を 「<a href=\"https://tsundora.com/」としている

「実行結果」
[INFO]STEP2: 0001/0001

STEP3 各トップページから番号を取り出します。
(INFO) 検索 HIT <ul id="menu-%e3%83%a1%e3%82%a4%e3%83%b3%e3%83%a1%e3%83%8b%e3%83%a5%e3%83%bc" class="menu"><li id="menu-item-243822" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-243822"><a href="https://tsundora.com/alist">繧「繝九Γ螢∫エ吶Μ繧ケ繝・/a></li>
[FIND]:<ul id="menu-%e3%83%a1%e3%82%a4%e3%83%b3%e3%83%a1%e3%83%8b%e3%83%a5%e3%83%bc" class="menu"><li id="menu-item-243822" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-243822"><a href="https://tsundora.com/alist">繧「繝九Γ螢∫エ吶Μ繧ケ繝・/a></li>

[FIND]:<li id="menu-item-112236" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-112236"><a href="https://tsundora.com/artist">繧「繝シ繝・ぅ繧ケ繝・/a></li>

[FIND]:<li id="menu-item-175902" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-175902"><a href="https://tsundora.com/pools">繝励・繝ォ</a></li>

[FIND]:<li id="menu-item-112659" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-112659"><a href="https://tsundora.com/keyword">莠コ豌励Ρ繝シ繝・/a></li>

[FIND]:<li id="menu-item-43608" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-43608"><a target="_blank" href="http://kjgame.sakura.ne.jp/rank/animewall/ranklink.cgi?id=otachan">螢∫エ吶Λ繝ウ繧ュ繝ウ繧ー</a></li>

[FIND]:<div class="clear"></div>

[FIND]:</div><!--//header_menu-->

[FIND]:                                 <div class="clear"></div>

[FIND]:                         <!-- right -->

[FIND]:                         <div class="clear"></div>

[FIND]:                 </div><!--//container-->

[FIND]:         </div><!--//header_top_cont-->

[FIND]:         <div class="logo_cont">

[FIND]:<div class="logo_2x">

[FIND]:<a href="https://tsundora.com" title="tsundora.com"><img src="https://tsundora.com/wp-content/themes/TsundoraTheme/images/logo.svg" alt="tsundora.com"></a>

[FIND]:<h2>鬮倩ァ」蜒丞コヲ繝サ鬮倡判雉ェ縺ェ繧「繝九Γ・・ご繝シ繝螢∫エ・/h2>

=========================================================================================

以下がソースコード(抜粋)です。

bool    検索(string szString)
{
    char* p;
    char szBuff[DEF_BUFFSIZE];
    strcpy_s(szBuff, szString.c_str());
    p = strstr(szBuff, "<a href=\"https://tsundora.com/");
    if (p)
    {
        printf("(INFO) 検索 HIT %s", szBuff);
    }
    if (p)
        return true;
    else
        return false;
}
//===============================================
//    各トップページから番号を取り出す
void Dic_Step3()
{
    printf("STEP3 各トップページから番号を取り出します。\n");


    vector<string> vText;

    int i;
    for (i = 1; i <= g_NUM; i++)
    {
        char szFile[80];
        sprintf_s(szFile, "top%04d%s", i, ".dat" );

        //    ファイルの内容を vText に保存
        Dic_ReadFile(szFile, &vText);
        vector<string>::iterator p;

        //    テキストの内容が vText に入っているので 関数「検索」で真偽判定をしてループで
        //    「検索」で true の値を返す イテレータの内容を出力する。
        p = find_if(vText.begin(), vText.end(), 検索 );
        if (p != vText.end())
        {
            while (p != vText.end())
            {
                char szBuff[DEF_BUFFSIZE];
                strcpy_s(szBuff, p->c_str());
                if( strlen(szBuff) > 20 )
                    printf("[FIND]:%s\n", szBuff );
                p++;
            }
        }
        vText.clear();
    }
}

(INFO) 検索 HIT が一件しかでなくて、特定の文字列を含んでいない文字列も
イテレータが運んでくるので、どこが悪いのでしょうか?

環境
OS:Windows10 Pro
IDE:Visual Studio 2019 Commnity
C/C++ STL

include<algorithm>

望む結果
(INFO 検索 HIT: xxxx 1件目
(INFO 検索 HIT: xxxx 2件目
..
..
(INFO 検索 HIT: xxx 終了
特定の文字列を含んだ文字列のみを抽出したい。
それをイテレータを使って、先頭から末尾まで表示(格納)したい。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

C++ なら、char * など使わずに string を使ったほうが良いのでは?

#include <iostream> // cout
#include <sstream>  // ostringstream
#include <fstream>  // ifstream
#include <string>   // getline
#include <vector>   // vector
#include <iomanip>  // setfill, setw
using namespace std;

const int g_NUM = 3;

bool 検索(const string& s)
{
    return s.find("<a href=\"https://tsundora.com/") != string::npos; 
}

bool Dic_ReadFile(const string& fname, vector<string>& vText)
{
    ifstream ifs(fname);
    if (!ifs) return false;
    string s;
    while (getline(ifs, s)) vText.push_back(s);
    return true;
}

int main()
{
    for (int i = 1; i <= g_NUM; i++) {
        ostringstream oss;
        oss << "top" << setfill('0') << setw(4) << i << ".dat";
        vector<string> vText;
        if (!Dic_ReadFile(oss.str(), vText)) break;
        for (vector<string>::iterator p = vText.begin(); p != vText.end(); ++p)
            if (検索(*p)) cout << "[FIND]:" << *p << '\n';
    }
}


STL の find_if ではなく、string::find を使ったので、
ご希望のものではないかもしれませんが。

追記
長さが 20以上という条件が要るんでしょうか?

        if (検索(*p) && p->size() > 20) cout << "[FIND]:" << *p << '\n';


追記2
STL の find_if 使って main を書き直してみました。

#include <algorithm>  // find_if

int main()
{
    for (int i = 1; i <= g_NUM; i++) {
        ostringstream oss;
        oss << "top" << setfill('0') << setw(4) << i << ".dat";
        vector<string> vText;
        if (!Dic_ReadFile(oss.str(), vText)) break;
        vector<string>::iterator p = vText.begin();
        for (; (p = find_if(p, vText.end(), 検索)) != vText.end(); ++p)
            if (p->size() > 20) cout << "[FIND]:" << *p << '\n';
    }
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/10/24 20:04

    長さ20というのは、なぜか3文字とかをひろってくるので、削除しようとして追加しました。

    教えていただいたソースコードを元にして修正したところ、
    ぶじ、目的が達成できました。
    ありがとうございました。

    キャンセル

0

find_ifは、条件に合致する最初の要素を返すため複数件の抽出には向きません。
copy_ifを用いましょう。

vector<string> result;
result.reserve(vText.size());

copy_if(vText.begin(), vText.end(), back_inserter(result), 検索);
for(const auto& str : result) {
    if(str.length() > 20)
        printf("[FIND]:%s\n", str.c_str() );
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/10/24 20:05

    kazuma-s様のご回答により解決できましたので、また機会がありましたら
    お答えくださると助かります。
    回答ありがとうございました。

    キャンセル

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

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

関連した質問

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