【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.23064

std::search の使い方と戻り値
投稿者---DD.(2005/09/14 15:26:50)


お世話になっております。DD.でございます。

現在 std::search アルゴリズムを用いて文字列の検索を行っております。

以下ソース抜粋:
int main()
{
    std::vector< std::string > vs1;
    std::vector< std::string > vs2;

    vs1.push_back( "abcd" );
    vs1.push_back( "efgh" );
    vs1.push_back( "ijkl" );
    vs1.push_back( "mnop" );
    vs1.push_back( "qrst" );
    vs1.push_back( "uvwx" );
    vs1.push_back( "yz" );

    vs2.push_back( "mn" );

    std::vector< std::string >::iterator it = std::search( vs1.begin(), vs1.end(), vs2.begin(), vs2.end() );
    if ( it != vs1.end() ) {
        std::vector< std::string > vs3;
        vs3.push_back( *it );
        std::copy( vs3.begin(), vs3.end(), std::ostream_iterator< std::string >( std::cout, "" ) );
    } else {
        std::cout << "not found";
    }
    return 0;
}


私の望む結果としては、vs1 の中の"mnop"の文字列が戻り値として
返ってき、vs3 にそれを格納。と、したかったのですが、
結果は、it が不定値となり、エラーになってしまいました。

std::search の扱い方が間違っているのでしょうか?
なぜ it が不定値となってしまうのでしょうか?
ご教授頂ければと思います。



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:std::search の使い方と戻り値 23065 DD. 2005/09/14 15:39:42


No.23065

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/14 15:39:42)


すいません。
上記の std::search で、"mnop" 文字列から "mn" だけを一致させるのは
無理みたいですね。。。

#内部ではやっぱり <> か == で要素ごとの判定してるぽいですね。
#vs2 を "mn" から "mnop" にするとやっぱりうまくいきます。

少し質問をかえさせて頂きたいと思います。

vector< string > 内の文字列要素から、
一部の文字列もしくは文字を含むものを抜粋してくるようなアルゴリズム
だと何を使えばいいのでしょうか?

それとも、自作で関数オブジェクトを作成して、中で
要素ごとの文字列判定を行わないとだめなんでしょうか?

よろしくお願い致します。



この投稿にコメントする

削除パスワード

No.23067

Re:std::search の使い方と戻り値
投稿者---tetrapod(2005/09/14 16:36:41)


basic_string の部分比較を行いたい?
basic_string の部分比較で find_if したい?
話はどっちなのでしょうか。
とりあえず前者なら basic_string のメンバ関数 find とか rfind とか使いましょう。
std::string a("alpharomeoalpharomeo");
str::string::size_type n=a.find("romeo"); // 5
str::string::size_type m=a.rfind("romeo"); // 15
後者なら、部分比較を行う関数オブジェクトを作って find_if に渡す。

search は「シーケンスの一致」を取るための algorithm なので
単純に要素1つを探す目的にはヘヴィすぎます。 find/find_if で十分。



この投稿にコメントする

削除パスワード

No.23074

Re:std::search の使い方と戻り値(解決)
投稿者---DD.(2005/09/14 16:54:08)


tetrapodさんありがとうございます。
>basic_string の部分比較を行いたい?
>basic_string の部分比較で find_if したい?
>話はどっちなのでしょうか。
前者です。
必要であれば後者でもよかったのですが。

>search は「シーケンスの一致」を取るための algorithm なので
>単純に要素1つを探す目的にはヘヴィすぎます。 find/find_if で十分。
string::find の存在を忘れておりました。
申し訳ないです^^;
アルゴリズムで〜ばかり探しておりましたorz

やりたかったことは無事思い通りの操作をしてくれましたソースの提示で。

int main()
{
    std::vector< std::string > vs1;
    std::vector< std::string > vs2;

    vs1.push_back( "abcd" );
    vs1.push_back( "efgh" );
    vs1.push_back( "ijkl" );
    vs1.push_back( "mnop" );
    vs1.push_back( "qrst" );
    vs1.push_back( "uvwx" );
    vs1.push_back( "yz" );

    std::vector< std::string >::iterator it = vs1.begin();
    for ( ; it != vs1.end(); ++it ) {
        if ( (*it).find( "mn" ) != (*it).npos ) {
            vs2.push_back( *it );
        }
    }
    if ( !vs2.empty() ) {
        std::copy( vs2.begin(), vs2.end(), std::ostream_iterator< std::string >( std::cout,  " " ) );
    } else {
        std::cout << "not found";
    }
    return 0;
}




この投稿にコメントする

削除パスワード

No.23071

Re:std::search の使い方と戻り値
投稿者---iijima(2005/09/14 16:51:11)


>std::search の扱い方が間違っているのでしょうか?
>なぜ it が不定値となってしまうのでしょうか?

不定値にはなりませんよ。
it==vs1.end()となり、結果は"not found"と表示されるはずです。

掲げられたソースは、

配列vs1:{ "abcd", "efgh", ... "yz" }(文字列はいずれもstd::string型)

の中から

配列vs2:{ "mn" }(同上)

に一致する「最初の範囲」の「最初の要素の位置」を探しています。

結果として"mnop"を得たいのであれば、使うべきアルゴリズムが違います。
tetrapodさんがおっしゃるように、find系を使うべきところですね。



この投稿にコメントする

削除パスワード

No.23075

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/14 16:59:28)


iijimaさんありがとうございます。

>>std::search の扱い方が間違っているのでしょうか?
>>なぜ it が不定値となってしまうのでしょうか?
一応VSでデバッグしてみたところ it の値が不定値となっていましたので。

>結果として"mnop"を得たいのであれば、使うべきアルゴリズムが違いま
>す。
>tetrapodさんがおっしゃるように、find系を使うべきところですね。
ですね^^;
各コンテナに用意されたメンバ及びアルゴリズムの数が多すぎて
覚えれば覚えるほどにどれを的確に判断して選べばいいのか
だんだんわけがわからなくなってきますorz

それ専門の参考書買おうか迷ってます^^;

#別掲示板でもちょっと書かせていただいちゃいました、
#iijimaさんの「STLアルゴリズム練習帳」の更新をこっそり期待。
#↑のソースより上質なものとか乗せて頂けるととってもうれし。



この投稿にコメントする

削除パスワード

No.23077

Re:std::search の使い方と戻り値
投稿者---iijima(2005/09/14 17:23:18)


No.23074,DD.さんのコードで十分と思います。

「上質」かどうか分かりませんが、"find_if"を使った例:

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

struct InString {
    const std::string& s_;
    InString( const std::string& s ) : s_(s){}
    bool operator()( const std::string& elem ) const
    {
        return elem.find( s_ ) != std::string::npos;
    }
};

int main()
{
    std::vector< std::string > vs1;

    vs1.push_back( "abcd" );
    vs1.push_back( "efgh" );
    vs1.push_back( "ijkl" );
    vs1.push_back( "mnop" );
    vs1.push_back( "qrst" );
    vs1.push_back( "uvwx" );
    vs1.push_back( "yz" );

    std::vector< std::string > vs2;
    std::string target = "mn";

    std::vector< std::string >::iterator it = std::find_if( vs1.begin(), vs1.end(), InString( target ) );
    while( it != vs1.end() ){
        vs2.push_back( *it );
        it = std::find_if( ++it, vs1.end(), InString( target ) );
    }

    if( !vs2.empty() ){
        std::copy( vs2.begin(), vs2.end(), std::ostream_iterator< std::string >( std::cout, " " ) );
    }
    else {
        std::cout << "not found";
    }
    std::cout << std::endl;
}



この投稿にコメントする

削除パスワード

No.23078

Re:std::search の使い方と戻り値
投稿者---tetrapod(2005/09/14 17:31:38)


ぢゃちょっとだけ変更して
template<class InputIterator, class OutputIterator, class Predicate>
inline OutputIterator copy_if(InputIterator first, InputIterator last,
                  OutputIterator result, Predicate pred) {
    for ( ; first != last; ++first )
    if ( pred(*first) )
        *result++ = *first;
    return result;
}
を手作りして
copy_if(vs1.begin(), vs1.end(), std::back_inserter(vs2), InString(target));




この投稿にコメントする

削除パスワード

No.23087

Re:std::search の使い方と戻り値
投稿者---解説者(2005/09/14 20:38:47)


おぉ、なるほど^^

たしかにこれで比較&コピーがいっぺんに^^
こういうのをすぱっと思いつかない自分がなんとも情けない(´Д⊂

大変参考になります。ありがとうございます。



この投稿にコメントする

削除パスワード

No.23088

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/14 20:39:45)


すいません。さっきの解説者はDD.ですorz

PCが違うから名前が変わってた。。。



この投稿にコメントする

削除パスワード

No.23079

Re:std::search の使い方と戻り値
投稿者---iijima(2005/09/14 17:43:56)


そうなんですよね。標準には"copy_if"がないんですよね〜

ファンクタを書き換えて"std::remove_copy_if"を使った例(オマケです):

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

struct NotInString {
    const std::string& s_;
    NotInString( const std::string& s ) : s_(s){}
    bool operator()( const std::string& elem ) const
    {
        return elem.find( s_ ) == std::string::npos;
    }
};

int main()
{
    std::vector< std::string > vs1;

    (略)

    std::vector< std::string > vs2;
    std::string target = "mn";
    std::remove_copy_if( vs1.begin(), vs1.end(), std::back_inserter( vs2 ), NotInString( target ) );

    (略)
}



この投稿にコメントする

削除パスワード

No.23089

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/14 20:42:01)


>そうなんですよね。標準には"copy_if"がないんですよね〜
そっか。そうですよね。
昔の HP STL にはあったとか。。。

なるほど、remove_copy_if を使っての copy_if の実装。
Effective STLにあった気がする。

大変参考になりました。ありがとうございました。



この投稿にコメントする

削除パスワード

No.23103

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/15 17:26:01)


一応、大文字・小文字の区別なく検索できるようにしてみました。
あんまりスマートでないような気がするのですが。。。
また、よい方法あればよろしくお願い致します。

    struct InString
    {
        std::string &target_;
        InString( std::string& target ) : target_( target ) {}
        bool operator() ( std::string& elem ) const
        {
            std::string find_elem, find_target;
            std::transform( elem.begin(), elem.end(), std::back_inserter( find_elem ), toupper );
            std::transform( target_.begin(), target_.end(), std::back_inserter( find_target ), toupper );
            return find_elem.find( find_target ) != std::string::npos;
        }
    };




この投稿にコメントする

削除パスワード

No.23104

Re:std::search の使い方と戻り値
投稿者---tetrapod(2005/09/15 17:54:43)


根本的に大文字小文字を区別しない string クラスっつーのがお望み?
ならばこんなところを参照。
http://www.geocities.co.jp/SiliconValley-Oakland/3676/reading/talk005.html
最初に見たときは「Traits ってこんなふうに使うんだ」と感動したのは内緒

ないしは多少? ヘヴィかもしれないけど boost::regex++ とか。




この投稿にコメントする

削除パスワード

No.23105

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/15 19:35:43)


>根本的に大文字小文字を区別しない string クラスっつーのがお望み?
>最初に見たときは「Traits ってこんなふうに使うんだ」と感動したのは
>内緒
ほぅ。なるほど。
って char_traits は string? のヘッダ見てないので
詳しくわかってないですが^^;
あ、でも string 自体が char_traits<char> のtypedefだったかな?

char_traits を継承して仕様自体を変えて作っちゃうってゆーことですね。
確かに、最初から作っちゃえば早い^^
大変参考になります。ありがとうございます。

>ないしは多少? ヘヴィかもしれないけど boost::regex++ とか。
実は boost まだ勉強していないのですorz
勉強しないと。。。



この投稿にコメントする

削除パスワード

No.23106

Re:std::search の使い方と戻り値
投稿者---iijima(2005/09/15 20:23:42)


引数を値渡しにすればもう少しスッキリするかな。

#include <string>
#include <algorithm>
#include <cctype>

struct InString {
    std::string s_;
    InString( std::string s )
    {
        std::transform( s.begin(), s.end(), std::back_inserter( s_ ), std::toupper );
    }
    bool operator()( std::string elem ) const
    {
        std::transform( elem.begin(), elem.end(), elem.begin(), std::toupper );
        return elem.find( s_ ) != std::string::npos;
    }
};

# ところで、ここは「C言語」関係の掲示板です。
# 管理人さんは大目に見てくださっていますが、C言語を学ぶ方が主な閲覧
# 者でしょうから、C以外の話題は控えめにした方が良いと思います。
# さらに掘り下げるならば、ここはそろそろ終了して、C++言語のサイトに
# 移られてはいかがでしょうか。



この投稿にコメントする

削除パスワード

No.23107

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/15 21:06:56)


そっか、コンストラクタで変換してしまえばいいんですよね。

# ところで、ここは「C言語」関係の掲示板です。
# 管理人さんは大目に見てくださっていますが、C言語を学ぶ方が主な閲覧
# 者でしょうから、C以外の話題は控えめにした方が良いと思います。
うぁ、、、C系じゃなかったんですね。。。
C、C++の掲示板かと勝手に思ってました。
管理人さん申し訳ないです。

# さらに掘り下げるならば、ここはそろそろ終了して、C++言語のサイトに
# 移られてはいかがでしょうか。
他で利用している掲示板は VC 系なので C++ に関する質問はこっちで
してしまってました。
C++ 掲示板 とかでよくググったりするのですが、
C++の掲示板があまりないような気がします。
どこかいい場所ありましたら、よろしければ教えて頂ければうれしいです。



この投稿にコメントする

削除パスワード

No.23108

Re:std::search の使い方と戻り値
投稿者---επιστημη(2005/09/15 21:26:48)


MLでしたらいいトコが (^^


この投稿にコメントする

削除パスワード

No.23110

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/15 21:35:52)


>MLでしたらいいトコが (^^
tietewさんのとこですよね。
既に閲覧させて頂いてますがあそこにこの程度のことで書き込みなんて
とても・・・^^;

議題に上がる内容がHighLvすぎてほとんど理解ががgorz
#MLってどういう意味なんでしょうか?



この投稿にコメントする

削除パスワード

No.23113

Re:std::search の使い方と戻り値
投稿者---επιστημη@cppll管理人(2005/09/15 21:58:25)


>>MLでしたらいいトコが (^^
>tietewさんのとこですよね。
>既に閲覧させて頂いてますがあそこにこの程度のことで書き込みなんて
>とても・・・^^;

ビギナ向け姉妹店 cppll_novice も併設しております。どぞご贔屓に。

>議題に上がる内容がHighLvすぎてほとんど理解ががgorz
>#MLってどういう意味なんでしょうか?

Mailing List



この投稿にコメントする

削除パスワード

No.23115

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/16 08:29:52)


>ビギナ向け姉妹店 cppll_novice も併設しております。どぞご贔屓に。
おぉ、そんなところがあったんですね。
覗いてみます。

>>議題に上がる内容がHighLvすぎてほとんど理解ががgorz
>>#MLってどういう意味なんでしょうか?
>Mailing List
メーリングリストのことだったんですね。
ありがとうございます。




この投稿にコメントする

削除パスワード

No.23109

Re:std::search の使い方と戻り値
投稿者---Blue(2005/09/15 21:33:14)


> C++ 掲示板 とかでよくググったりするのですが、
> C++の掲示板があまりないような気がします。
> どこかいい場所ありましたら、よろしければ教えて頂ければうれしいです。

まぁ、ここも一応C言語関係の掲示板なんでC++も関連しているので
とりあえずはOKだと思っているんですけどねぇ。
# なにより、HTMLタグが使えるのが一番いいとこなんですが。

私のみている掲示板もだいたいVC++になっていますね。

> 他で利用している掲示板は VC 系なので C++ に関する質問はこっちで
> してしまってました。
VCの掲示板で聞いても差し支えないかと思うんですが。

しいて、C++用の掲示板をあげるとしたら、
ディスカッション フォーラム のC and C++ラウンジですかね。



この投稿にコメントする

削除パスワード

No.23111

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/15 21:40:23)


>まぁ、ここも一応C言語関係の掲示板なんでC++も関連しているの
>でとりあえずはOKだと思っているんですけどねぇ。
ありがとうございます<(_ _)>

>VCの掲示板で聞いても差し支えないかと思うんですが。
VC関連の掲示板よりもこちらのほうがC++の議題を出しやすいと
思ってましたので^^;

>ディスカッション フォーラムのC and C++ラウンジですかね。
実はこちらも既に閲覧させて頂いていたり。。。
じゃぁ、あっちに書き込めばいいじゃないかというつっこみなのですが、
こちらのほうがレスが早そうかなと。



この投稿にコメントする

削除パスワード

No.23112

Re:std::search の使い方と戻り値
投稿者---Blue(2005/09/15 21:46:24)


> こちらのほうがレスが早そうかなと。
大体見ている方々は一緒なんですけどねぇ。
レスのスピードなんて、ドコが早いかなんてわからないものです。
気長に待ちませうw

# でも、自分が質問者の立場になった時、どこの掲示板を使うか迷うかも。



この投稿にコメントする

削除パスワード

No.23114

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/15 22:00:01)


>大体見ている方々は一緒なんですけどねぇ。
そうなんですけどね^^;
なんだかここはすごく早く回答得られるという思い込みが。

># でも、自分が質問者の立場になった時、どこの掲示板を使うか迷うか
ですです。


この投稿にコメントする

削除パスワード

No.23116

Re:std::search の使い方と戻り値
投稿者---DD.(2005/09/16 08:35:43)


>そっか、コンストラクタで変換してしまえばいいんですよね。
すいません。なんかボケてました。orz



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧