-1

C++ クラス入門の課題を完了しようとしていますが、行き詰まりました。このプログラムは、映画が構造体に格納されている VHS ビデオ マネージャーであると想定されています。映画は、ソース フォルダー内の .txt ファイルから取得され、映画のタイトルと年で構成されます。テキスト ファイルを読み取った後、最初の出力は次のようになります。

Initializing Video Collection:
What file should I use? movies.txt
A New Hope (1977)
Empire Strikes Back (1980)
Flight of the Navigator (1986)
Goonies (1985)
Last Crusade (1989)
Raiders of the Lost Ark (1981)
Return of the Jedi (1983)
Temple of Doom (1984)
War Games (1983)

ビデオは、次のような構造で保存されます。

struct Video
{
    string title; //the name of the video
    int year; // the year the movie was released
    int stars; // a rating out of five stars - this will be zero until you set it
    bool watched; // starts as false until you watch the movie and flip it to true
};

タイトルと年がそれぞれの配列の場所に配置されるように、ファイルを正しく読み取る方法がわからないようです。この目的のために私が持っている機能は次のとおりです。

void initialize(Video video_array[tapes_max], Video data)
{

    ifstream videofile;
    videofile.open("movies.txt");
    if(videofile.fail())
    {
        cout << "Could not open states file for reading!" << endl;
        exit(1);
    }
    for(int i = 0; i < tapes_max; i++)
    {
        getline(videofile, video_array[i].title);
    }

    videofile.close();
    for (int i = 0; i < tapes_max; i++)
    {
       cout << video_array[i].title << " " << video_array[i].year << endl;
    }

    cout << endl << endl;
}

これが私に割り当てられた PDF へのリンクです。皆さんは私よりもよく理解できるでしょうか? よろしくお願いします。

https://docs.google.com/open?id=0Bwr7dC-H4CCZUkkyUGNTRzRZdk0

4

2 に答える 2

2

これで、入力行が文字列に読み込まれました。ここで、タイトルと年という 2 つの部分に分割する必要があります。これは通常、解析と呼ばれます: 文字列からいくつかの情報を抽出します。

タスクの一部として正式な文法 (文字列形式を定義する規則のセット) を取得していないと思いますが、適切な推測を行うのは非常に簡単です: 行にはタイトル (おそらくスペースを含む) が含まれ、その後にスペース、左括弧、リリース年の 10 進数表現、その後に右括弧が続きます。

それを解析する方法がわかりますか?良い選択は、文字列を逆方向にスキャンすることです:

  1. 最後の文字が閉じ括弧でない場合は、形式が間違っていると文句を言います。それ以外の場合は、それを切り落とします。括弧の解析が完了しました。
  2. 左括弧を見つけます。誰もいない場合は、文句を言います。最後から検索する必要があります。タイトルには単独で括弧が含まれている可能性があるため、興味深い左括弧は最後の括弧でなければなりません。かっこの間にテキストを保存します(インデックスに注意してください!):それはあなたのyear.
  3. 年を数値に解析します(atoi詳細については、この回答またはGoogleを参照してください)。解析が失敗した場合、プログラムは間違った入力形式について文句を言う必要があります
  4. 前のスペースを切り取り、スペースが見つからない場合は文句を言う
  5. 文字列の残りの部分は動画のタイトルでなければなりません。少なくとも空でないことを確認してください。

解析には十分で、Videoオブジェクトにタイトルとリリース年が含まれるようになりました。他の 2 つのフィールドには、現時点ではデフォルト値があります。ただし、ユーザーが次にプログラムを起動したときに、これらのフィールドの状態が保持されるように、プログラムはそれらを変更し、場合によってはそれらをシリアル化 (情報をファイルに保存するための派手な言葉) できる必要があります。

これはおそらく、4 つのフィールドすべてを含むディスク上のデータのフォーマットを考案する必要があることを意味します (現在のフィールド.txtには 2 つしか含まれていません)。もちろん、その形式のパーサーも必要です。個人的には、あなたのケースでは非常に単純な形式を使用します。たとえば、1 行に 1 つのフィールドのみです。

ソフトウェア開発の世界へようこそ!

于 2012-11-16T21:47:37.980 に答える
0

boost::regex を使用する必要があると思います。
正規表現を使用して行を処理する方法のデモを次に示します。

#include <boost/regex.hpp>
#include <iostream>
#include <string>
#include <cstring>

int main()
{
  using namespace std;

  string line = "Hey Joe(1984) "; // an example line that you can read
  boost::smatch what;
  boost::regex e("(.*)\\(([0-9]+)\\).*"); // whatever comes before numbers in parentheses, is the title.

  if(boost::regex_match(line, what, e, boost::match_extra))
  {
    string title = what[1];
    int year = atoi(static_cast<string>(what[2]).c_str()); // perhaps there is a better code for this but it will do.
    cout<<"title: "<<title<<"\tyear: "<<year<<endl;
  }
  else
  {
    cout<<"No match"<<endl; // indicates a wrong line
  }
  return 0;
}

これをループに入れるだけで完了です。

ブーストの使い方がわからない場合:

ブーストをインストールします -- (Mac では、Macports でブーストをインストールしました)

私のためのコンパイル行:

g++ -I/opt/local/include -L/opt/local/lib -lboost_regex-mt boost_regex.cpp
# for testing
./a.out 

あなたにとっては、Windowsでも似たようなものかもしれません。( g++ -IC:\path\to\boost\includes -LC:\path\to\boost\libs -lboost_regex-something)。Windows では、「boost_regex.dll」のような名前の dll ファイルを検索する必要があると思います。dll は、ブースト インストールの lib ディレクトリにあります。

詳細情報:正規表現ドキュメント

于 2012-11-26T20:06:40.063 に答える