Linux講座にようこそ。このページは「C言語プログラミング入門 - 第14章.ライブラリ関数 - 入出力ライブラリ」です。

C言語プログラミング入門

14. ライブラリ関数(8/36) - 入出力ライブラリ(7/10)

14.11 ファイル内の位置操作関数

入力関数でファイルから入力すると、通常はファイルの先頭のデータから順番に入力します。これは自動的に行われるため、入力関数を呼び出す度に次のデータを読むことができます。通常はこれで問題は無いと思いますが、ファイルの先頭からではなく、途中のデータを直接入出力したいような場合もあります。そのような場合は、ここで紹介する関数を使うとよいでしょう。

14.11.1 fseek関数

fseek関数はファイルポインタに対応したファイルの入出力位置(ファイルオフセット)を設定します。

【表14-1-30】 fseek関数
形式#include <stdio.h>
int fseek(FILE *fp, long offset, int whence);
返り値正常に処理ができた場合は0を返します。エラーの場合は-1を返します。
引数
FILE *fp
入出力位置を設定するファイルのファイルポインタを指定します。
long offset
新たに設定する入出力位置をバイト単位で指定します。位置の指定方法は第3引数のwhenceにより異なります。
int whence
第2引数のoffsetの値が何処を起点としたものかを指定します。SEEK_SETはファイルの先頭を、SEEK_CURは現在の位置を、SEEK_ENDはファイルの末尾を起点とする事を表します。
使用法、
正常に処理ができた場合は入出力位置に位置付いていますので、引き続き入出力関数により入出力を行います。

14.11.2 ftell関数

ftell関数はファイルポインタに対応したファイルの現在の入出力位置を取得します。

【表14-1-31】 fftell関数
形式#include <stdio.h>
long ftell(FILE *fp);
返り値正常に処理ができた場合は、現在の入出力位置を返します。エラーの場合は-1を返します。
引数
FILE *fp
入出力位置を取得するファイルのファイルポインタを指定します。

14.11.3 rewind関数

rewind関数はファイルポインタに対応したファイルの入出力位置をファイルの先頭に設定します。

【表14-1-32】 rewind関数
形式#include <stdio.h>
void rewind(FILE *fp);
返り値ありません。
引数
FILE *fp
入出力位置をファイルの先頭に設定するファイルのファイルポインタを指定します。
使用法、
この関数の実行後は入出力位置がファイルの先頭になっていますので、入出力関数を実行するとファイルの先頭から処理を行います。

14.11.4 例題

前ページの例題(ex14_1_9.prg)で作成したバイナリファイル(ex14_1_9_out.dat)のレコード番号を入力して、そのレコードの内容を標準出力に編集出力します。

  1. #include <stdio.h>
  2.  
  3. /* 個人情報構造体 */
  4. struct person_info {
  5.     int     number;          /* 番号 */
  6.     double  weight;          /* 体重 */
  7.     double  height;          /* 身長 */
  8.     char    blood[4];        /* 血液型 */
  9. };
  10.  
  11. int main(void)
  12. {
  13.     FILE                *fp_in;
  14.     char                in_file[] = "./DATA/ex14_1_9_out.dat";
  15.     struct person_info  person;
  16.     char                ans[10] = "y";
  17.     int                 number;
  18.     long                offset;
  19.     int                 return_code = 0;
  20.  
  21.     if((fp_in = fopen(in_file, "r")) != NULL)
  22.     {
  23.         while(ans[0] == 'y' || ans[0] == 'Y')
  24.         {
  25.             printf("番号を入力してください ==> ");
  26.             scanf("%d", &number);
  27.  
  28.             /* 指定されたレコード位置の設定 */
  29.             offset = sizeof(person) * (number - 1);
  30.             if(fseek(fp_in, offset, SEEK_SET) == 0)
  31.             {
  32.                 /*  レコードを入力 */
  33.                 if(fread(&person, sizeof(person), 1, fp_in) == 1)
  34.                 {
  35.                     /* レコードの内容を出力 */
  36.                     printf("%-4s  %-8s %-8s %s\n", "番号", "体重", "身長", "血液型");
  37.                     printf(" %03d %6.1f %6.1f  %s\n",
  38.                             person.number, person.weight, person.height, person.blood);
  39.                 }
  40.                 else
  41.                 {
  42.                     printf("指定された番号のレコードはありません。\n");
  43.                 }
  44.             }
  45.             else
  46.             {
  47.                 printf("入力位置の設定が出来ませんでした。\n");
  48.             }
  49.  
  50.             printf("処理を続けますか(y/n) ==> ");
  51.             scanf("%s", ans);
  52.         }
  53.         fclose(fp_in);
  54.     }
  55.     else
  56.     {
  57.         printf("%sがオープン出来ませんでした。\n", in_file);
  58.         return_code = 1;
  59.     }
  60.  
  61.     return return_code;
  62. }
$ ./ex14_1_10.prg
番号を入力してください ==> 3
番号  体重   身長   血液型
 003   43.2  156.5  AB
処理を続けますか(y/n) ==> y
番号を入力してください ==> 5
番号  体重   身長   血液型
 005   75.7  166.5  A
処理を続けますか(y/n) ==> y
番号を入力してください ==> 1
番号  体重   身長   血液型
 001   67.0  188.0  A
処理を続けますか(y/n) ==> y
番号を入力してください ==> 0
入力位置の設定が出来ませんでした。
処理を続けますか(y/n) ==> y
番号を入力してください ==> 6
指定された番号のレコードはありません。
処理を続けますか(y/n) ==> y
番号を入力してください ==> -3
入力位置の設定が出来ませんでした。
処理を続けますか(y/n) ==> n
30行目
ファイルの先頭を起点として、指定されたレコード位置に位置付けます。先頭からの距離は前の行で変数offsetに求めています。
33行目
30行目のfseek関数で入力位置に位置付いていますので、ここで1レコード入力します。

14.11.5 fgetpos関数

fgetpos関数はftell関数と同じく、ファイルポインタに対応したファイルの現在の入出力位置(ファイルの先頭を起点とする)を取得します。ftell関数との相違は、ftell関数は入出力位置をlong int型で返すため、ファイルの大きさは約2GBまで(long int型が4バイト長の場合)となります。これに対して、fgetpos関数は入出力位置を専用の構造体で管理することにより、2GB以上のファイルも取り扱えるようになっています。

【表14-1-33】 fgetpos関数
形式#include <stdio.h>
int fgetpos(FILE fp, fpos_t *pos);
返り値正常に処理ができた場合は0を返します。エラーの場合は-1を返します。
引数
FILE *fp
入出力位置を取得するファイルのファイルポインタを指定します。
fpos_t *pos
入出力位置を格納するfpos_t構造体変数を指定します。

14.11.6 fsetpos関数

fsetpos関数はfseek関数と同じく、ファイルポインタに対応したファイルの入出力位置を設定します。fseek関数との相違は、2GB以上のファイルも取り扱えるようになっていることです。

【表14-1-34】 fsetpos関数
形式#include <stdio.h>
int fsetpos(FILE fp, fpos_t *pos);
返り値正常に処理ができた場合は0を返します。エラーの場合は-1を返します。
引数
FILE *fp
入出力位置を設定するファイルのファイルポインタを指定します。
fpos_t *pos
新たに設定する入出力位置が格納されているfpos_t構造体変数を指定します。