- 締切済み
FILE構造体のファイルポインタについて質問です。
FILE構造体のファイルポインタについて質問です。 Microsoft VC++を使っています。 テキストファイル(1行の連続して文字が連なっている。)のn文字目からの文字を読み取る場合、fgetsでn-1文字目まで読み取ってから、fgetsでn文字目から読み取ればできるのですが、ファイルポインタを使用した場合について教えてください。 FILE *fp; fp = fopen("a.txt","r"); と宣言すると、fp->_ptrがファイルポインタになります。 この段階でfp->_ptrは0で、値を読み込みとエラーになります。(ファイルの実行が停止) fgets()で何文字でもいいから読み込むと、fp->_ptrにアドレスが読み込まれます。 fp->_ptrに加算してn-1文字目まで動かして、fgetsで文字を読み込めば読み込めるのですが、 ファイルの残りの文字数よりも読み込む文字数が大きい場合、その差分だけへ(アスキーコード205) が読み込まれます。 詳しく説明すると、テキストファイルにn文字目からabcdeという5文字があるとします。 n文字目から10文字読み込んだ場合、配列に格納される文字がabcdeヘヘヘヘヘになってしまいます。 へ(アスキーコード205)の数は最大でfp->ptrに加算した値となっています。 質問としましては (1)fp->ptrにアドレスが書き込まれるのはどのタイミングなのでしょうか? (2)なぜへ(アスキーコード205)が格納されてしまうのか? 分かる方、是非ご教授をよろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- peanus15
- ベストアンサー率36% (7/19)
同じC関数でもコンパイラーによってでも違うらしいのでC関数は扱い辛いです また、マルチタスク環境下ではシステム関数を推奨されていますので fopen は使いません。 (2)について その事象 '0xcdcdcdcd' は検索すれば見つかりますが、検索されたのでしょうか? OS提供のシステム関数(API)を使えば読込んだバイト数が戻ります 基よりファイルサイズを事前に取得して認識の上アクセスすれば良いことです http://homepage3.nifty.com/mmgames/c_guide/q_filesize.html
- asuncion
- ベストアンサー率33% (2127/6290)
FILE *型の中身がどうなっているか、 プログラマーは知らなくてよいはずです。
- peanus15
- ベストアンサー率36% (7/19)
fp->_ptrに加算して ??? fp->_ptr がファイルポインタであることは正しいですが、ファイルの現在位置を示すだけの出力情報です。 車のスピードメータを手で動かしても車のスピードが変らないのと同じです。 ファイルポインタを動かす関数を使ってファイルポインタは変更できます。 周辺を少し調べればわかる内容で質問することはスキルを上げる上では弊害となります。
お礼
fseekを使ってポインタを動かせば済むという話ですね。 私の環境だと、fp->_ptrの値は変えることが可能で、それを変えることによってファイルを読み込む位置は変わるので、単なる出力情報ではないようです。 回答ありがとうございました。
- hanabutako
- ベストアンサー率54% (492/895)
> FILE *fp; > fp = fopen("a.txt","r"); > と宣言すると、fp->_ptrがファイルポインタになります。 違います。 fpがファイルポインタです。 なお、fp->_ptrなどfpの中身を直接参照する行為はライブラリ作成者からは想定されていないため、この場合にどう動くかについては誰にも説明できません。 (1) fopenのタイミングではなく、freadやfgetsなど、ファイルの中身が読み込まれるタイミングでデータを構造体内の格納領域に格納するのが普通です。しかし、普通というだけで今後ともこのような動きであることは保証されません。 (2) Windowsの場合、プロセスには0クリアされたヒープ領域が割り当てられます。このことを考えると、一度何かに使っていてたメモリーを再利用し、そこにたまたま205が入っていただけでしょう。へが入っているのは、5文字目までしか読み込んでおらず、6文字目以降を読んだ時にその先を読み出すだけだからだと思います。 どちらにしても、fpの中身を直接参照する行為はライブラリ作成者からは想定されていませんので、やめた方がいいです。C言語のストリームI/Oの実装方法を知りたいなら、Googleコード検索( http://www.google.co.jp/codesearch )でfopenなどを入れて調べてみると、いくつかの実装を見ることができるでしょう。もちろん、Microsoft VC++のものはありませんが。 ちなみに、ファイルポインタを使う方法はC言語でよくあるカプセル化の実装方法です。カプセル化により中の構造を知ることなくライブラリを使えますが、その一方でライブラリ製作者は利用者に気兼ねすることなくライブラリの実装を変更できます。つまり、FILE構造体へのポインタとその操作関数というインタフェースによりプログラムを疎結合にして保守性を向上させるわけです。 いうなれば、ライブラリの作成者と利用者はこのインタフェースさえ守れば互いにどのように実装してもよいという安心ができるわけです。FILE構造体の中身を想定してプログラムを書くことはそのインタフェースを破壊する行為であり、ライブラリの作成者の想定していない行為です。それをわかっていてやっているならよいのですが...
お礼
回答ありがとうございます。 FILE *型の中身がどうなっているか知らなくても大丈夫なように、ライブラリ関数があるようですね。