2

非常に単純なファイル データベースを実装しています。私は2つの基本的な操作を持っています:

void Insert(const std::string & i_record)
{
   //create or append to the file
    m_fileStream.open(m_fileName.c_str(), std::ios::out | std::ios::app);

    if (m_fileStream.is_open())
    {
        m_fileStream << i_record << "\n";
    }

    m_fileStream.flush();
    m_fileStream.close();
}

/*
* Returns a list with all the items in the file.
*/
 std::vector<std::string> SelectAll()
 {
    std::vector<std::string> results;

    m_fileStream.open(m_fileName.c_str(), std::ios::in);

    std::string line;
    if (m_fileStream.is_open())
    {
        while (!m_fileStream.eof())
        {
            getline (m_fileStream, line);
            results.push_back(line);

        }
    }

    m_fileStream.close();

    return results;
 }    

このクラスには、プライベート メンバーとして m_fileStream と m_fileName があります。

OK - 問題は次のとおりです。

私が次のようなことをした場合:

db->Insert("a");
db->SelectAll();
db->Insert("b");

最終的に、ファイルには「a」のみが含まれます。なぜ?

注: getline() は失敗ビットを設定するようです。しかし、なぜ?

4

2 に答える 2

4

変化する

    while (!m_fileStream.eof())
    {
        getline (m_fileStream, line);
        results.push_back(line);

    }

    while (getline (m_fileStream, line))
    {
        results.push_back(line);
    }

そうしないと、最後に空行が 1 行追加されます。次の読み取りがファイルの末尾を超えた場合ではなくeof()、ファイルの末尾を超えて読み取ろうとした場合にのみ true を返します。

ストリームから文字を抽出しようとするfailbitため、 を設定します。getline文字が残っていない場合 ('\n'まだ表示されていない場合)、stream.get(c)文字にfailbit. 次にgetline、を設定してeofbittrue.eof()を返し、ループを終了します。

設定したくない場合はfailbit、条件を から!stream.eof()に変更stream.peek() != EOFします (ファイルの末尾に改行があることを確認してください)。

これは、問題の解決策でもあります。ストリームで.close()はないため、ファイルを再度開くと静止画が設定されます。あなたのものを読み込んだ後に呼び出すと、それが機能します。.clear()failbitstream.clear()

于 2008-11-15T17:01:57.793 に答える
1

litb はかなりうまくいったと思います。しかし、私の $0.02 を追加するだけです:

1) 私は常に以下を支持しました。

while ( stream && (stream.peek() != EOF) )  {...}

EOF以外の[悪い]イベントが発生する可能性があるため。

(そして、litb で言及されているように、peek()!=EOF は、ストリームが最後まで読み込もうとするまで EOF を設定しないという問題を回避します。)

.

2)「m_fileStream」は、これらの両方の方法で開かれ、読み取り/書き込み/フラッシュされ、閉じられるため...

スタック上でローカルに宣言しないのはなぜですか? そうすることで、以前の状態の問題が残ってあなたを台無しにすることはありません。そして、あなたはディスクにアクセスしているので、効率は最大の関心事ではないかもしれません...

その上、あなたは怠け者になることができます:

ifstream stream ( m_fileName.c_str() );
ASSERT( stream, !=, NULL );  // Uses my own ASSERT macro && stream.operator().
while ( stream && (stream.peek() != EOF) )  {...}
于 2008-11-15T18:36:53.423 に答える