seekpについて教えてください。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
non

seekpについて教えてください。

#1

投稿記事 by non » 16年前

「猫でもわかる」の粂井さんのホームページで勉強中です。
さて、住所録を作ろうの所を行ってます。下のページです。
http://www.kumei.ne.jp/c_lang/cpp/cpp_38.htm

このままではVC2008ExpressEditionでエラーでしたので、修正しました。
それが添付ファイルです。
住所録を2回書き込んだとき、先頭にデータ件数、そのあとに2人分のデータが出力されなければ
いけないはずですが、2人目のデータしか書き込まれていません。すなわち、上書きされてます。
問題となる部分です。
Jout.open(JFILE, ios::out | ios::ate);
	Jout.seekp(0, ios::beg);
	Jout << no_of_data + 1 << endl;
    Jout.seekp(0, ios::end);

    Jout << data.name << endl;
さらに、まったく同じプログラムをBC++5.0で実行すると、すべてのデータが1件目の後に追加されます。
すなわち、先頭にシークできていません。

私の、何が間違っているのでしょうか?教えてください。

non

Re:seekpについて教えてください。

#2

投稿記事 by non » 16年前

どなたからも回答がいただけないので、スレッドが古くならないように自己レスです。

プログラムが長いと、見たくないという方のために、要点だけを抜き取ったプログラムです。
#include <iostream>
#include <fstream>
using namespace std;

void infile()
{
	ifstream ifs;
	char ch;
	ifs.open("abc.txt");
	ifs.seekg(4,ios::beg);
	ifs >> ch;
	cout << ch <<endl;	
	ifs.seekg(-4,ios::end);
	ifs >> ch;
	cout << ch <<endl;
	ifs.close();
}
void outfile()
{
	ofstream ofs;
	ofs.open("abc.txt",ios::ate);
	ofs.seekp(4,ios::beg);
	ofs << 'E';
	ofs.seekp(-4,ios::end);
	ofs << 'Y';
	ofs.close();
}
int main(void)
{
	infile();
	outfile();
	return 0;
}
ファイル abc.txtの中身は
abcdefghijklmnopqrstuvwxyz
最後は改行して終わってます。
従って実行結果の予想は、eとyが画面に出た後、ファイルの中身がeがE、yがYになるはずでした。
実際に実行してみると、
最初に
e
y
とディスプレイに出力されるところまではいいのですが、
その後のファイル出力で、abc.txtは

VisualC++2008ExpressEditionの場合とgccの場合は
.Y..E   (.はNULLです)になります。
バイナリエディタで見ると、00 59 00 00 45 です。

また、BorlandC++5.0の場合
abcdefghijklmnopqrstuvwxyz
EY
になります。

このようにコンパイラで結果が違うとともに、思った通りの動作をしません。

non

Re:seekpについて教えてください。

#3

投稿記事 by non » 16年前

再び、自己レスです。
Cで作成してみました。
#include <stdio.h>

void infile()
{
	FILE *fp;
	int ch;
	fp=fopen("abc.txt","r");
	fseek(fp,4,SEEK_SET);
	ch=fgetc(fp);
	putchar(ch);
	fseek(fp,-4,SEEK_END);
	ch=fgetc(fp);
	putchar(ch);	
	fclose(fp);
}
void outfile()
{
	FILE *fp;
	fp=fopen("abc.txt","r+");
	fseek(fp,4,SEEK_SET);
	fputc('E',fp);
	fseek(fp,-4,SEEK_END);
	fputc('Y',fp);	
	fclose(fp);
}
int main(void)
{
	infile();
	outfile();
	return 0;
}
これから言えることは、
ofs.open("abc.txt",ios::ate); は、
VC++2008の場合は、C言語の場合の
fp=fopen("abc.txt","w");のように働き、
BC++では
fp=fopen("abc.txt","a");のように働いているという事です。
C言語の"r+"のようなものはないのでしょうか?

non

Re:seekpについて教えてください。

#4

投稿記事 by non » 16年前

自己解決しました。
void outfile()
{
	fstream ofs;
	ofs.open("abc.txt",ios::in | ios::out);
	ofs.seekp(4,ios::beg);
	ofs << 'E';
	ofs.seekp(-4,ios::end);
	ofs << 'Y';
	ofs.close();
}
正解かどうかは知りませんが、とにかく思った通り動きました。

Justy

Re:seekpについて教えてください。

#5

投稿記事 by Justy » 16年前

 もう解決してしまっているようなので、ご参考までに。

 Visual C++ 7.1/9.0ではこんな対応になっているようです。
[color=#d0d0ff" face="monospace]
ios_base::in "r"
ios_base::out "w"
ios_base::out | ios_base::trunc "w"
ios_base::out | ios_base::app "a"
ios_base::in | ios_base::binary "rb"
ios_base::out | ios_base::binary "wb"
ios_base::out | ios_base::trunc | ios_base::binary "wb"
ios_base::out | ios_base::app | ios_base::binary "ab"
ios_base::in | ios_base::out "r+"
ios_base::in | ios_base::out | ios_base::trunc "w+"
ios_base::in | ios_base::out | ios_base::app "a+"
ios_base::in | ios_base::out | ios_base::binary "r+b"
ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary "w+b"
ios_base::in | ios_base::out | ios_base::app | ios_base::binary "a+b"[/color]


これとは別に ios_base::ate があった場合は fseek(fp, 0, SEEK_END) をしています。


# そのケースですと、ios_base::out | ios_base::appでも望み通りの動作になるのかもしれません。

non

Re:seekpについて教えてください。

#6

投稿記事 by non » 16年前

Justy さん。ご丁寧に、ありがとうございます。
あっちこっちのサイトを探しても情報がなく、苦労しました。
まして、ateの動作がコンパイラによって異なるとは、困ったものです。
もしかしたら、ateの動作が異なるのではなく、スイッチを省略したときの
defaultが異なるのかも知れませんが。

たかぎ

Re:seekpについて教えてください。

#7

投稿記事 by たかぎ » 16年前

少し調べてみました。
どうやら、Borland C++ Compiler 5.5.1のバグのようです。
少なくともBorland C++ Compiler 5.6.4では改善されています。
ボーランドの処理系は、バージョンによって標準C++ライブラリの実装がコロコロ変わるのが困ったものです。

なお、seekpは最終的にはstd::fseekを呼び出しますので、

> ofs.seekp(4,ios::beg);
> ofs.seekp(-4,ios::end);

のように、offsetに0またはtellpが返した値以外を指定した場合の動作は未定義だったはずです。

non

Re:seekpについて教えてください。

#8

投稿記事 by non » 16年前

たかぎさんへ
バグですか。了解しました。
>offsetに0またはtellpが返した値以外を指定した場合の動作は未定義だったはずです。
未定義ですか。しかし、欲しい機能ですよね。VCもBCも動いたのでよしとしましょう。

閉鎖

“C言語何でも質問掲示板” へ戻る