3

私は、400 以上の映画 (リンクされたリストを使用してリンクされている) をタイトル、ジャンル、年、評価、主演俳優などで検索するプログラムの作成を任されています。

ただし、問題があります。リンクされたリストを介して検索を実行するために許可されている検索機能は 1 つだけです。また、その検索関数内で許可される while ループは 1 つだけです。

  while (moviePtr != NULL)

明らかに、俳優検索やジャンル検索の場合は、さまざまなインスタンスになります。俳優、ジャンル、レーティング、年、サブジャンル、助演俳優の場合、見つかったすべてのインスタンスを出力する必要があります。(たとえば、Kevin Bacon が x-men とノートブックにいた場合、それらの 1 つだけでなく両方を出力する必要があります (画面ではなく出力ファイルに))。

私たちが与えられたこれらの制限に完全に困惑していることに気づきました. 検索関数はさまざまなデータ型をどのように処理しますか? (年と評価は整数として宣言する必要があります)。私が探しているものを正確に知るにはどうすればよいですか?俳優を検索している場合、タイトルも検索したくありません。

開始方法と開始方法に関する提案は非常に高く評価されます。

編集:こんにちは、私が何をしたかについてあなたたちを更新したと思ったすべてのID。私は3つの異なる検索機能を持っています。1 つは数値 (年と評価)、1 つはジャンルと俳優、最後に 1 つはタイトルです。

3つすべてのコードは次のとおりです。まずはタイトル探し。

void TitleSearched(MovieNode*head,
                string titleSearched,
                ofstream& outFile)
{
MovieNode* moviePtr;
bool found;

moviePtr = head;
found = false;

while (moviePtr !=NULL & !found)
{
    if (moviePtr-> title == titleSearched)
    {
        found = true;
    }
    else
    {
        moviePtr = moviePtr -> next;
    }

}
if (found)
{
    cout << endl << titleSearched << " has been found!\n";
    TitleOutput (moviePtr,outFile);
}
else
{
    cout << endl << titleSearched << " was not found.\n";
}
}

今、年/評価検索。

int NumSearched(MovieNode* head, int numSearched)
{

int instances;
MovieNode* moviePtr;

ofstream outFile;


    moviePtr = head;
    instances = 0;
    while (moviePtr !=NULL)
    {
        if (moviePtr-> year == numSearched)
        {

            instances = instances +1;
            NumOutList(moviePtr,outFile,"year",numSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else if (moviePtr->rating == numSearched)
        {

            instances = instances +1;
            NumOutList(moviePtr,outFile,"rating",numSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else
        {
            moviePtr = moviePtr ->next;
        }


    }
return instances;
}

最後にジャンル/俳優検索。

int ItemSearch (MovieNode* head,string itemSearched, ofstream& outFile)
{
int instances;
MovieNode* moviePtr;


moviePtr = head;
instances = 0;






    while (moviePtr !=NULL)
    {
        if (moviePtr-> genre == itemSearched || moviePtr ->subGenre == itemSearched)
        {

            instances = instances +1;
            OutList(moviePtr,outFile,"Genre",itemSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else if (moviePtr->leadActor == itemSearched || moviePtr->supportActor == itemSearched)
        {

            instances = instances +1;
            OutList(moviePtr,outFile,"Actor",itemSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else
        {
            moviePtr = moviePtr ->next;
        }


    }



    return instances;
}

私の仕事が何であるかを皆さんに思い出させたかったのです。1. これら 3 つの検索関数を 1 つに結合する 2. 検索で while ループを 1 つだけ持つ 3. 特定の関数で返されるのは 1 つだけです (ただし、これを結合すると void 関数になると仮定します)

私の主な問題は、int と文字列です。評価または年を文字列として宣言することは許可されていません。そして、一般的に3つすべてを組み合わせたコードの形式だけで頭が痛くなります

4

3 に答える 3

2

検索関数に「一致」関数をパラメータの1つとして使用させ、すべての映画でこの一致関数を呼び出して、映画が一致するかどうかを確認できます。次に、さまざまな一致関数を使用して検索関数を呼び出すことができます。

このようなもの:

template <typename MatchFunction>
void search_movies(movie* moviePtr, MatchFunction match)
{
    while (moviePtr != NULL)
    {
        if (match(*moviePtr))
        {
            // output movie
        }
        moviePtr = moviePtr->next;
    }
}

次に、次のような一致関数を宣言できます。

bool matches_actor(movie& m, const std::string& actor)
{
    return m.actor == actor;
}

次のような特定のクエリで呼び出します。

search_movies(moviePtr, std::bind(matches_actor, _1, "Morgan Freeman"));

std::bindからのC ++ 11関数<functional>です;あなたは同等にboost::bindまたはを使用することができますstd::bind2nd

あるいは、よりCスタイルの方法を好む場合は、次のようにすることができます。

void search_movies(movie* moviePtr, bool (*match)(movie*, void*), void* match_arg)
{
    while (moviePtr != NULL)
    {
        if (match(moviePtr, match_arg))
        {
            // output movie
        }
        moviePtr = moviePtr->next;
    }
}
...
bool matches_actor(movie* m, void* actor)
{
    return m.actor == *((std::string*)actor);
}
...
std::string actor = "Morgan Freeman";
search_movies(moviePtr, &matches_actor, (void*)(&actor));
于 2012-04-20T19:57:28.210 に答える
2

述語をパラメーターとして受け入れる方法で検索関数を書くことができます。述語は、ある種の「関数型」です(つまり、関数のように「呼び出される」機能を持つものはすべて、関数、ラムダ、または関数オブジェクトの場合があります)。

C ++標準ライブラリでは、多くの標準アルゴリズムに述語が使用されているため、次のようなコード(標準コンテナを使用)が表示されるのが一般的です。

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

bool begins_with_s(std::string s)
{
    return  s.length() > 0                  && 
            std::toupper( s.at(0) ) == 'S';
}

bool contains_a_number(std::string s)
{
    return std::find_if(s.begin(), s.end(), std::isdigit) != s.end(); 
}

int main()
{
    std::string movies_array[] =  
    { 
        "King Kong", 
        "Singin in the Rain", 
        "Die Hard 2", 
        "Superman", 
        "Star Wars", 
        "Jaws 3"
    };
    std::vector<std::string> movies( std::begin(movies_array), 
                                     std::end(movies_array) );

    // Use predicate - count if the movie name begins with "S"
    std::cout << "Movies beginning with S: " 
        << std::count_if(movies.begin(), movies.end(), begins_with_s) 
        << std::endl;

    // Use predicate - count if the movie name contains a number
    std::cout << "Movies containing a number: " 
        << std::count_if(movies.begin(), movies.end(), contains_a_number) 
        << std::endl;
}

C ++標準アルゴリズムがこのように実装される方法は、述語を表すテンプレート引数を次の行に沿って受け入れることです。

template< typename PredicateType >
void my_function(PredicateType predicate)
{
    Movie my_movie;
    predicate(my_movie);
}

これは、関数型プログラミングの考え方から生まれた手法です。関数を関数に渡す(関数を「第一級市民」として扱う)。

于 2012-04-20T19:55:16.270 に答える
2

ファンクターを渡して一致をチェックするオプションの他に、他のオプションがあります。そのようなオプションの 1 つは、一連のオプションの条件をチェックすることです (boost::optional手作りのアプローチを使用するか、ポインターを使用できます。たとえば、次のようになります。

void print_matching( node* list, int * year, std::string * actor... ) {
   // iterate over the list:
   while (...) {
      if (  ( !year  || ptr->year == *year )
         && ( !actor || ptr->actor == *actor ) 
         && ...
         )
      {
          // Film matches, print it
      }
   }
}

関数シグネチャを簡素化するために、search_patternテストするフィールドをカプセル化する型を作成できます (別のアプローチを使用する例: bools を使用してオプション性を決定します)。

struct pattern {
   bool check_actor;
   std::string actor;
   bool check_year;
   int year;
};

void print_matching( node* list, pattern const & p ) {
   // iterate over the list:
   while (...) {
      if (  ( !p.check_year  || ptr->year == p.year )
         && ( !p.check_actor || ptr->actor == p.actor ) 
         && ...
         )
      {
          // Film matches, print it
      }
   }
}

この最後のケースでは、実際にテストをpatternオブジェクトに移動して、関数を作成できます。

bool pattern::matches( movie cost& m ) const { return (!check_year || m.year == year ) &&(!check_actor || m.actor == 俳優 ); } void print_matching( node* list, pattern const & p ) { // リストを繰り返します: while (...) { if ( p.matches( list->data ) ) { // マッチをフィルム化して出力します } } }

于 2012-04-20T20:36:13.240 に答える