ページ 11

ifstreamのseekgの挙動について

Posted: 2011年8月24日(水) 14:11
by chibago
皆様、お世話になっております。
現在、ifstreamで読み込んだテキストデータをgetlineで一行ずつ取り込み、
処理することを考えております。まずは、目的の行であるかサーチして
目的のキーワードを見つけたらその行から処理をします.
検索機能と処理機能を分けたいと思いますので、検索でヒットした
行を処理ルーチンでもう一度読み込みたいのでファイルの参照位置を
一行戻したいと考えております。

この、ファイルの参照位置を一行戻すというところで苦労しておりますので
ご意見をお聞かせいただきたいと思います。

当然、seekgを使うと言うことになると思いますが、
この挙動がマニュアルを見てもよくわかりません。
istream& seekg ( streampos pos );
istream& seekg ( streamoff off, ios_base::seekdir dir );
とありますが、2番めの関数は基準位置からの移動ということで
わかりやすいのですが、一番目のpositionはどこからのものなのでしょうか。
直感的に、2番めのios_base::curのことかと思ったのですが、
そうでも無さそうです。

この様な状況を踏まえて、いろいろ実験をしてみました.

コード:

#include <iostream>
#include <fstream>

int main(){

std::ifstream ifs("./test.txt");
 std::string buf;
 getline(ifs, buf);
 std::cout<<buf<<std::endl;
 ifs.seekg(-1);
 getline(ifs, buf);
 std::cout<<buf<<std::endl;
}

test.txtは

コード:

hello
world
[EOF]
の様なものですが、このseekg(-1)で一応目的は達成でき
helloの出力が2回行われます。ただ、他の例(どこが違うのか
よくわからないためサンプルが示せませんが)では値が得られない
(EOF扱いだと思われます)ため、この例だとたまたま動いている
だけかとおもわれます。
seekg(i, ios_base::cur) (iは任意の負のint)だと当然ですが、行単位ではなく、
文字数ごとに遡ります。(これを使って、改行文字を探すしかないのかとも
考えております。)

istream& seekg ( streampos pos );
の使い方についてアドバイスいただけると幸です。

Re: ifstreamのseekgの挙動について

Posted: 2011年8月24日(水) 14:34
by softya(ソフト屋)
MSDNにThe absolute position in which to move the read pointer.と書かれていますので、先頭からの位置だと思います。
「basic_istream::seekg」
http://msdn.microsoft.com/ja-jp/library/y2d6fx99.aspx
なので、ios_base::begと同じ動作になるのではないでしょうか。

それと読み直す必要があるのか疑問なのですが?
別の変数などに保存しておいてはダメなのでしょうか?

どうしても読み込むのなら、今の行の読み込み前に位置をtellg();で取り込んで覚えておくのも手です。

Re: ifstreamのseekgの挙動について

Posted: 2011年8月24日(水) 15:12
by chibago
softyaさん
アドバイスありがとうございます。

先頭からの位置ならば、(-1)でEOFが出たのは頷けます。
(一行前の戻った例は何だったのでしょうか)

それから、読み直す必要があるのかと言うことに関しては、
好き好きといいますか、そういうコーディングを積み重ねて
きたので今更修正出来ないと言う面が強いです。

現在私の作っているプログラムはFortranのフォーマットで
書き出された数値群を読み込もうとしておりますが、
コンストラクタにファイルパスを渡すとifstreamに勝手に開いてくれて、
Fortranフォーマットの文字列(E8.3,X,I4,A10など)を渡すとそれにしたがって
getlineで読んだ1行を自動的に分解して返す(boost::anyを使っています)
というものです。(自分では非常に便利だと自負しております)

ですので、この様な要求のもとプログラミングをしております。
読み込む前のtellg()の案採用させていただきます。

大変助かりました。