0

DVD タイトル (文字列) カテゴリ (文字列) 価格 (int) ランタイム (int) リリース年 (int) のようなオブジェクト クラスの特定の属性をリストするテキスト ファイルがあります。

ファイルは次のようにリストされます

Movie1
Action    
10.45
123
2008

Movie2
Sc-fi
12.89
99
2008

ファイルの名前を入力する機能があり、さまざまな属性をオブジェクトに読み込むことになっています

DVD* file(DVD arr[], string fileName, int s, int& e)
{
ifstream file(fileName);

DVD j;
string v;
string w;
double x;
int y;
int z;


while(!file.eof())
{
    file >> v;
    j.setTitle(v);

    file >> w;
    j.setCategory(w);

    file >> x;
    j.setPrice(x);

    file >> y;
    j.setRuntime(y);

    file >> z;
    j.setYear(z);

    arr=add(arr, j, s, e); //this is just a function that adds the object to an arry
}


file.close();

return arr;
}

しかし、それは正しく機能していません。各行を変数に読み込み、スペースがある場合はスキップしますが、ファイルの終わりでない場合は、文字列に到達するまで読み続けます。助言がありますか?

4

1 に答える 1

1

2つのこと。

まず:

while(!file.eof())読み取りが試行れるまで返されeof()ません。true

2 つ目は、1 行ずつ読みたい場合は、次のようなものを使用することをお勧めします。

void read_file(std::vector<DVD> & arr, string fileName) {
    ifstream file(fileName.c_str());

    DVD j;
    std::string line;
    enum State {
        TITLE, CATEGORY, PRICE, RUNTIME, YEAR
    } state = TITLE;

    while(std::getline(file, line)) {

        // if we encounter an empty line, reset the state    
        if(line.empty()) {
            state = TITLE;
        } else {

            // process the line, and set the attribute, for example
            switch(state) {
            case TITLE:
                j.setTitle(line);
                state = CATEGORY;
                break;
            case CATEGORY:
                j.setCategory(line);
                state = PRICE;
                break;
            case PRICE:
                j.setPrice(boost::lexical_cast<double>(line));
                state = RUNTIME;
                break;
            case RUNTIME:
                j.setRuntime(boost::lexical_cast<int>(line));
                state = YEAR;
                break;
            case YEAR:
                j.setYear(boost::lexical_cast<int>(line));
                arr.push_back(j);
                state = TITLE;
                break;
            default:
                // just in case
                state = TITLE;
                break;
            }
        }
    }
}

これは、ブール値のコンテキストで使用されたときに、最後の操作がストリームを「良好な」状態のままにしたstd::getline場合の参照を返すため、機能します。true

この例では、boost::lexical_cast<>必要に応じて文字列を数値型に変換するために使用std::stringstreamしていますが、これを手動で行うことも、最適と思われる他の方法を使用することもできます。たとえば、atoi()strtolstrtodなどです。

補足:std::vector<DVD>ネイティブ配列の代わりに使用する方がはるかに優れています。同じくらい高速ですが、サイズ変更とクリーンアップを適切に処理します。add次のことができるようになるため、関数は不要になります。arr.push_back(j);

于 2013-10-20T19:06:36.190 に答える