C言語のファイル入出力について解説

C言語のファイル入出力の解説ページアイキャッチ

このページではC言語でのファイルの入出力(読み込み・書き込み)について解説します。

ファイル入出力

まずはファイル入出力の流れについて解説していきたいと思います。

一般的に、ファイルの中身を読み込んだり、ファイルを編集したりするときは下記の流れで行うと思います。

  1. ファイルのオープン(ファイルを開く)
  2. ファイルからの読み込み or ファイルへの書き込み
  3. ファイルのクローズ(ファイルを閉じる)

C言語においても全く処理の流れは同じです。つまり、下記の3つのステップでファイルの入出力処理を行います。

  1. ファイルのオープン(ファイルを開く)
  2. ファイルからの読み込み or ファイルへの書き込み
  3. ファイルのクローズ(ファイルを閉じる)

ストリームと FILE 構造体

C言語でのファイル入出力において重要な要素が2つあります。それはストリームと FILE 構造体です。

ストリーム

ストリームとはデータの流れを表す言葉です。Apple Music や spotify などの音楽配信サービスをストリーミングサービスと言ったりしますよね?ここで使われてるストリーム(ストリーミング)と同じ意味です。

ストリーミングサービス

ユーザーが音楽を再生したとき、このストリーミングサービスでは下記の処理が繰り返し行われることになります。

  • 再生位置の音楽データを受信してバッファ(メモリ)に格納する
  • 受信した音楽データを音として再生する
  • 次の再生位置のデータを受信したバッファ(メモリ)に上書きする
  • 受信した音楽データを音として再生する
  • ・・・・・

ここでバッファのデータに注目すると、ちょうど川の流れのように、必要なデータがどんどん流れていくことになります。聴き終わったデータはどんどんバッファから流れ出ていく感じですね。

データの流れを川の流れで表現した様子

こういったデータが連続してどんどん流れていくバッファのことをストリームといいます。音楽配信サービスもストリームを利用したサービスなのでストリーミングサービスと呼ばれたりするんです。

で、C言語のファイル入出力においても同様にストリームを利用して処理が行われます

FILE 構造体

前述の通り、ファイルの入出力においてはまずファイルのオープンを行います。これは実際には、ファイルとプログラムの間にストリームを作成する処理になります。

ストリームのイメージ

ストリームにはファイルのデータの一部が格納されますので、そのストリームに対して処理を行うことで、ファイルのデータを読み込んだりファイルにデータを書き込みを行うことができます。

そして、そのストリームの情報が格納される構造体が FILE 構造体です。ストリームのサイズやストリームバッファへのポインタなどの情報もこの FILE 構造体に格納されています。

FILE 構造体の説明図

ただし、C言語では一般的に FILE 構造体のデータを自分で作成したり変更するようなことは行わないです。標準関数を利用して FILE 構造体を扱うことになります。

例えば fopen という標準関数を使用することで自動的に FILE 構造体が作成されますし、fread や fwrite などの標準関数を使用することで、その FILE 構造体に紐付けされたストリームからデータを読み込んだり書き込んだりすることができます(これらの関数の説明については後述します)。ストリームに必要なデータを格納したり、次のデータを格納したりする処理も標準関数の中で実行してくれるので、このあたりの処理も自分でプログラミングする必要もありません。

逆に自分で FILE 構造体を変更してストリームを制御しようと思うとめちゃめちゃ大変です。OS を自作したりしない限りは FILE 構造体のデータを自分で変更することは避けた方が良いです。

ですので、C言語でファイル入出力を行う場合は、すでに用意されている標準関数(fopen、fread、fgets などなど)を素直に使いましょう!ここまでストリームについて解説してきましたが、実は標準関数を使用することでこのストリームを意識することなく、あたかもファイルに直接アクセスしているかのようにファイルの入出力を行うことができます。

ただし、ストリームなのでデータがどんどん流れていく点だけは注意しましょう。例えば fread 関数などでデータを読み込んだ場合、ストリームからその読み込んだデータはどんどん吐き出されていきます(実際にはストリームに入ってるデータを全部読み込んだら吐き出される)。この辺りはここから解説していく各関数の説明の中でも説明していこうと思います。

ファイルのオープン

ファイルのオープン(ファイルを開く)に用いる代表的な関数は fopen 関数です。前述の通り、ファイルをオープンすることでストリームが作成され、そのストリームからデータをファイルを読み込んだり書き込んだりすることができるようになります。

fopen 関数

fopen 関数はファイルをオープンしてストリームを作成する関数です。fopen 関数の定義は下記の通りになっています。

#include <stdio.h>
FILE* fopen(const char*, const char*);

fopen 関数の引数

fopen 関数の引数には下記を指定します。

  • 第一引数:開きたいファイル名(の文字列)
  • 第二引数:ファイルを開くモード(の文字列)

ファイルを開くモードの基本となるのは下記の三つです。

r:読み込みモード。ファイルが存在しない場合はエラー。 

 

w:書き込みモード。ファイルが存在しない場合はファイルを作成する。ファイルが存在する場合はファイルの先頭から上書きする。

 

a:追記モード。ファイルが存在しない場合はファイルを作成する。ファイルが存在する場合はファイルの最後から追記する。

さらに各モードの後ろに “+” を付加することで下記のように読み込みも書き込みも可能なモードになります。

r+:読み込み書き込みモード。ファイルが存在しない場合はエラー。 

 

w+:読み込み書き込みモード。ファイルが存在しない場合はファイルを作成する。ファイルが存在する場合はファイルの先頭から上書きする。

 

a+:読み込み追記モード。ファイルが存在しない場合はファイルを作成する。ファイルが存在する場合はファイルの最後から追記する。

“r+” と “w+” は同じようなモードになりますが、ファイルの有無により動作が異なります。”r+” は開くファイルが無い時はエラーになりますが、”w+” はエラーになりません。

またここまで解説してきたモードにさらに “b” を付加することでファイルをバイナリモードで開くことが可能です。

テキストモードとバイナリモードの大きな違いは、開いたファイルへの操作時に OS によって異なる改行コードを考慮して処理してくれるかどうかの違いです。

例えば “Hello, World\n” という文字列をファイルに書き出すとき、テキストモードでは下記のように動作が異なります。

  • Mac:’\n’ をそのまま ‘\n’ で出力
  • Windows:’\n’ を ‘\r\n’ に置き替えて出力

つまり、テキストモードでは改行コードを OS に応じて変換して処理してくれるというわけです。

バイナリモードの場合はこのような変換は行わず、バイナリモードでは指定されたデータをそのまま出力します。

  • Mac:’\n’ をそのまま ‘\n’ で出力
  • Windows:’\n’ をそのまま ‘\n’ で出力

基本的に、

  • テキストファイル(文字列のみから作られるファイル)にはテキストモード
  • それ以外にはバイナリモード

を使用する考え方で良いと思います。

fopen 関数の戻り値

fopen 関数の戻り値は下記の通りです。

  • 成功時:ストリームの情報が格納された FILE 構造体のアドレス
  • 失敗時:NULL

第一引数で指定されたファイルのオープンに成功した場合は、そのファイル関連づけられたストリームの情報を格納した FILE 構造体のアドレスが返却されます。

fopen 関数の注意点

fopen 使用時に特に注意していただきたいのは下記の二点です。

  • 第二引数で指定するのは文字列であること
  • もともと存在するファイルを書き込みモードで開くと上書きされる

後者に関しては、せっかく苦労したファイルも書き込みモードで開いてしまうと中身が空になってしまいますので特に注意してください。

fopen 関数の使用例

例えば “input.txt” を “テキストモード” で開くときは下記のように fopen 関数を実行します。

FILE *fi;
  
/* ファイルのオープン */
fi = fopen("input.txt", "r");
if(fi == NULL){
  printf("file open error:input.txt\n");
  return -1;
}

“input.jpg” を “バイナリモード” で開くときは下記のように fopen 関数を実行します。

FILE *fi;
  
/* ファイルのオープン */
fi = fopen("input.jpg", "r");
if(fi == NULL){
  printf("file open error:input.jpg\n");
  return -1;
}

スポンサーリンク

ファイルのクローズ

fopen 関数で開いたファイルのクローズ(ファイルを閉じる)に用いる代表的な関数は fclose 関数です。

fclose 関数

fclose 関数はストリームを解放し、ファイルを閉じる関数です。fclose 関数の定義は下記の通りになっています。

#include <stdio.h>
int fclose(FILE*);

fclose 関数の引数

fclose 関数の引数には下記を指定します。

  • 第一引数:閉じたいファイルに関連づけられた FILE 型ポインタ

引数には fopen の戻り値である FILE 型ポインタを指定するだけであり、モードの指定なども不要ですので使い方は簡単です。

fclose 関数の戻り値

fclose 関数の戻り値は下記のようになっています。

  • 成功時:0
  • 失敗時:EOF

ですが(本当は良くないかもしれませんが…)、あまり fclose 関数の戻り値って見ないんですよね。失敗するときは指定したファイルがオープンされていない場合くらいじゃないかなぁ…。その場合はクローズが不要ですから失敗しても問題ないですよね…。

fclose 関数の使用例

FILE *fi;
  
/* ファイルのオープン */
fi = fopen("input.txt", "r");
if(fi == NULL){
  printf("file open error:input.txt\n");
  return -1;
}
/* ファイル入出力処理 */

fclose(fi);

ファイルの入力(ファイルからの読み込み)

ファイルの入力(ファイルからの読み込み)で使用する代表的な関数には、fgetc、fgets、fread などがあります。

使用例で読み込むファイルは下記を「input.txt」という名前で保存したテキストファイルとして動きを解説しています。

Good Morning...
  
"Hello"

Who are you?
Good Bye!!

fgetc 関数

fgetc 関数は、ストリームから(ファイルから)1文字分読み込む関数です。1文字といっても半角英数字の1文字(unsigned char 型のデータ)と考えて良いです。テキストファイル向けの関数です。

#include 
int fgetc(FILE*);

fgetc 関数の引数

fgetc 関数の引数には下記を指定します。

  • 第一引数:読み込みたいファイルの FILE 構造体のアドレス

fopen 関数の戻り値の FILE 構造体へのポインタを指定すれば良いです。

fgetc 関数の戻り値

fgetc 関数の戻り値は下記のようになっています。

  • 成功時:読み込んだ1文字分の文字
  • 失敗時:EOF

ファイルの終端まで読み終わっている状態や読み込みに失敗した場合は EOF が返却されます。ですので、テキストファイルの場合はファイルをまだ読み込めるかどうかは fgetc 関数の戻り値が EOF であるかどうかで判断することが可能です。

MEMO

画像などのバイナリデータの場合は EOF の値自体がデータ内に存在する場合があります。ですので、戻り値が EOF の場合でもファイルの終端でない場合があり、ファイルの終端を判断することが難しいです。こういった理由でちょっとバイナリデータの読み込みには使いにくいと思います。

fgetc 関数の使用例

fgetc 関数の使用例は下記の通りです。

#include <stdio.h>
  
int main(void){
  FILE *fi;
  int ret;

  /* ファイルのオープン */
  fi = fopen("input.txt", "r");
  if(fi == NULL){
    printf("file open error:input.txt\n");
    return -1;
  }

  while(1){
    /* 1文字読み込み */
    ret = fgetc(fi);
  
    if(ret == EOF){
      /* 戻り値がEOFの場合読み込み終了 */
      break;
    }
    printf("%c", (char)ret);
  }

  /* ファイルのクローズ */
  fclose(fi);

  return 0;
}

実行すると下記のように表示されます。

Good Morning...

"Hello"

Who are you?
Good Bye!!

「input.txt」の中身がそのまま出力されていることが確認できると思います。注目していただきたいのは、fi 変数は fopen 関数実行後何も変更していないのに、fgetc 関数で読み込むデータが次々と変化している点です。これこそがストリームの動きです。

読み込んだ文字はストリームから流れ出ていき、次の文字が次々とストリームに流れ入ってきているイメージが伝わるのではないかと思います。このようなストリームの制御は fgetc 関数の中で行われていますので、ファイルの読み込み位置の移動などは意識することなくプログラミングすることが可能です。

fgets 関数

fgets 関数はストリームから(ファイルから)一行分データを読み込む関数です。もう少し正確にいうと、改行コードまでのデータを読み込む関数になります。読み込んだ文字列の最後にはヌル文字(’\0’)が格納されます。fgets 関数はテキストファイル向けの関数です。

#include <stdio.h>
char *fgets(char*, int, FILE*);

fgets 関数の引数

fgets 関数の引数には下記を指定します。

  • 第一引数:読み込んだ文字列を格納するバッファ(メモリ領域)のアドレス
  • 第二引数:読み込む文字列の最大文字数
  • 第三引数:読み込みたいファイルの FILE 構造体のアドレス

ポイントは第二引数です。第二引数で最大文字数を指定することで、fgets 関数が一度に読み込む文字数を制限することが可能です(実際には読み込んだ文字列の最後には ‘\0’ が格納されるので(最大文字数 – 1)文字が読み込まれることになる)。

ですので、1行の長さが分からないようなファイルの読み込みの場合でも、第一引数で指定するアドレスのバッファサイズは第二引数で指定した文字数分のメモリさえ確保しておけば、メモリ不足になってエラーやプログラムが落ちてしまったりするようなこともありません。

fgets 関数の戻り値

fgets 関数の戻り値は下記のようになっています。

  • 成功時:読み込んだ文字列を格納したバッファの先頭アドレス
  • 失敗時:NULL

成功時の戻り値は、読み込んだ文字列を格納したバッファの先頭アドレスですので、つまりは第一引数と同じアドレスが返却されることになります。

失敗時は NULL が返却されますので、ファイルがまだ読み込めるかどうかは fgets 関数の戻り値が NULL かどうかで判断することが可能です。

fgets 関数の使用例①

fgets 関数の使用例は下記の通りです。ポイントは fgets 関数の第二引数と、fgets 関数での読み込み結果を格納する str 配列の大きさを同じにしているところです。

#include <stdio.h>
  
#define LINE_MAX 256

int main(void){
  FILE *fi;
  char str[LINE_MAX];
  char *ret;

  /* ファイルのオープン */
  fi = fopen("input.txt", "r");
  if(fi == NULL){
    printf("file open error:input.txt\n");
    return -1;
  }

  while(1){
    /* 1行読み込み */
    ret = fgets(str, LINE_MAX, fi);

    if(ret == NULL){
      /* 戻り値がNULLの場合読み込み終了 */
      break;
    }
    printf("%s\n", str);
  }

  /* ファイルのクローズ */
  fclose(fi);

  return 0;
}

出力結果は下記の通りです。

Good Morning...



"Hello"



Who are you?

Good Bye!!

fgets 関数で読み込んだ文字列には、改行コードも含まれますので、上記ソースコードのようにその文字列の末尾に ‘\n’ を含ませて表示すると改行が2回行われるようになります。割と間違いやすい(私はよく間違う)ところなのでわざとこんな表示にしてみました。

また fputc 同様に、fgets 関数でも FILE 構造体の変更をしていないのに fgets 関数を実行するたびに読み込まれるデータ(ファイルの中の読み込み先)が変化しています。一方で、読み込んだデータを格納する str のアドレスは fgets 関数を実行しても変化しません(変わるのはアドレスの先のメモリに格納されているデータのみ)。ここがストリームと単なるバッファの違いですね。

fgets 関数の使用例②

今度は fgets 関数の第二引数の大きさを小さくしてみましょう。

#include <stdio.h>
  
#define LINE_MAX 4

int main(void){
  FILE *fi;
  char str[LINE_MAX];
  char *ret;

  /* ファイルのオープン */
  fi = fopen("input.txt", "r");
  if(fi == NULL){
    printf("file open error:input.txt\n");
    return -1;
  }

  while(1){
    /* 1行読み込み */
    ret = fgets(str, LINE_MAX, fi);

    if(ret == NULL){
      /* 戻り値がNULLの場合読み込み終了 */
      break;
    }
    printf("%s\n", str);
  }

  /* ファイルのクローズ */
  fclose(fi);

  return 0;
}

表示結果は下記のようになりました。第二引数で指定した文字数 – 1 分の文字しか一度に読み込まれていないことが確認できると思います。

Goo
d M
orn
ing
...




"He
llo
"



Who
 ar
e y
ou?


Goo
d B
ye!
!

fread 関数

fread 関数はストリームから(ファイルから)指定したサイズ分のデータを読み込む関数です。どちらかというとバイナリファイル向けの関数です。がテキストファイルでも使えます。ただし、fgets のように自動的に読み込んだデータにヌル文字(’\0’)を付加したりはしてくれませんので、テキストファイルを扱う場合はその辺りに注意しながらプログラミングする必要があります。 

#include <stdio.h>
size_t fread(void*, size_t, size_t, FILE*);

fread 関数の引数

fread 関数の引数には下記を指定します。

  • 第一引数:読み込んだデータを格納するバッファ(メモリ領域)のアドレス
  • 第二引数:読み込むデータ単位のサイズ(バイト)
  • 第三引数:読み込むデータの個数
  • 第四引数:読み込みたいファイルの FILE 構造体のアドレス

“第二引数で指定したサイズ x 第三引数で指定した個数” バイトのデータが読み込まれることになります。ややこしいのは第二引数と第三引数の使い分けですね。

基本的には

  • 第二引数:第一引数のバッファ(配列等)の型のサイズ
  • 第三引数:読み込むデータ数

を指定するので良いと思います。重要なのは、読み込むデータのサイズ(つまり「第二引数 x 第三引数」)が第一引数で指定したアドレスのバッファのサイズを超えないことです。

fread 関数の戻り値

fread 関数の戻り値は下記のようになっています。

  • 読み込んだデータの個数

つまり、戻り値が「第三引数で指定したデータの個数」と同じであれば、まだ読み込めるデータが存在すると判断できますし、戻り値が「第三引数で指定したデータの個数」よりも小さいのであれば、ファイルの終端まで読み終わったと判断することが可能です。

fread 関数の使用例

fread 関数の使用例は下記の通りです。テキストファイルの読み込みを行なっています。ポイントはファイル読み込み終了の判断部分と、fgets 関数時と違って自分でヌル文字を付加している部分です。

#include <stdio.h>
  
#define READ_SIZE 4

int main(void){
  FILE *fi;
  char str[READ_SIZE+1];
  size_t ret;

  /* ファイルのオープン */
  fi = fopen("input.txt", "r");
  if(fi == NULL){
    printf("file open error:input.txt\n");
    return -1;
  }

  while(1){
    /* READ_SIZEバイト分読み込み */
    ret = fread(str, sizeof(char), READ_SIZE, fi);

    str[ret] = '\0';
    printf("%s\n", str);
    if(ret < READ_SIZE){
      /* 戻り値が第三引数よりも小さい
         のでファイルの終端に行き着いた */
      break;
    }
  }

  /* ファイルのクローズ */
  fclose(fi);

  return 0;
}

出力結果は下記の通りです。

Good
 Mor
ning
...


"He
llo"


Wh
o ar
e yo
u?
G
ood 
Bye!
!

ファイルの出力(ファイルへの書き込み)

ファイルの出力(ファイルへの書き込み)で使用する代表的な関数には、fputc、fwrite、fprintf などがあります。

fputc 関数

fputc 関数は、ストリームへ(ファイルへ)1文字分書き込む関数です。fgetc の書き込みバージョンみたいな感じですね。テキストファイル・バイナリファイル両方に向いている関数です。が、テキストモードだと改行コードの変換が行われることがありますので、改行コードの変換をしたくない場合は fopen 関数でバイナリモードを指定するようにしましょう。

#include 
int fputc(int, FILE*);

fputc 関数の引数

fputc 関数の引数には下記を指定します。

  • 第一引数:書き込みたい文字
  • 第二引数:書き込みたいファイルの FILE 構造体のアドレス

第一引数は int 型ですが、実際に書き込まれる文字は int 型を char 型にキャストした文字となります。

fputc 関数の戻り値

fputc 関数の戻り値は下記のようになっています。

  • 成功時:書き込んだ文字
  • 失敗時:EOF

fputc 関数の使用例

fputc 関数の使用例は下記の通りです。

#include <stdio.h>
#include <string.h> /* strlen用 */

int main(void){
  char str[] = "Hello\n World!";
  FILE *fo;
  int ret;
  int i;

  /* ファイルのオープン */
  fo = fopen("output.txt", "w");
  if(fo == NULL){
    printf("file open error:output.txt\n");
    return -1;
  }

  for(i = 0; i < strlen(str); i++){
    /* 1文字書き込み */
    ret = fputc(0x200 + str[i], fo);
  }

  /* ファイルのクローズ */
  fclose(fo);

  return 0;
}

実行すると output.txt が作成されます。ファイルの中身は下記のようになります。

Hello
 World!

読み込みで用いた関数同様に、fputc 関数実行するたびにファイルの書き込み位置が変化している点がポイントですね。これも fputc 関数の中でデータが流れていくようにストリームの処理を行なってくれているからです。

fprintf 関数

fprintf 関数は、おなじみの printf 関数と同じような使い方でファイルに書き込みを行うことができる関数です。テキストファイル向けの関数です。

#include<stdio.h>
int fprintf(FILE*, char*, ・・・);

fprintf 関数の引数

fprintf 関数の引数には下記を指定します。

  • 第一引数:書き込みたいファイルの FILE 構造体のアドレス
  • 第二引数:書式文字列
  • 第三引数:引数リスト

第一引数以外は printf 関数と全く同じ引数となります。

実は第一引数に “stdout” を指定すると、コンソールに文字が出力され、printf と全く同じ働きをします。

fprintf 関数の戻り値

fprintf 関数の戻り値は下記の通りです。

  • 成功:書き込んだ文字数
  • 失敗:負の値

fprintf 関数の使用例

fprintf 関数の使用例は下記の通りです。

include <stdio.h>
  
int main(void){
  FILE *fo;
  char *ret;
  char name[5][10] = {
    "taro", "hanako", "miki", "ziro", "emi"
  };
  int i;

  /* ファイルのオープン */
  fo = fopen("output.txt", "w");
  if(fo == NULL){
    printf("file open error:output.txt\n");
    return -1;
  }

  for(i = 0; i < 5; i++){
    fprintf(fo, "%d : %s\n", i+1, name[i]);
  }

  /* ファイルのクローズ */
  fclose(fo);

  return 0;
}

実行して作成される output.txt の中身は下記のようになります。

1 : taro
2 : hanako
3 : miki
4 : ziro
5 : emi

fwrite 関数

fwrite 関数ストリームへ(ファイルへ)指定したサイズ分データを書き込む関数です。fread 関数の書き込みバージョンみたいな感じです。fwrite 関数はどちらかというとバイナリファイル向きの関数です。テキストファイルでも使用できますが、改行コードの変換に注意しましょう。

#include<stdio.h>
size_t fwrite(void*, size_t, size_t, FILE*);

fwrite 関数の引数

fwrite 関数の引数には下記を指定します。

  • 第一引数:書き込むデータを格納するバッファ(メモリ領域)のアドレス
  • 第二引数:書き込むデータ単位のサイズ(バイト)
  • 第三引数:書き込むデータの個数
  • 第四引数:書き込みたいファイルの FILE 構造体のアドレス

基本的に fread 関数と同様にして引数を指定すれば良いです。読み込むのか、書き込むのかが違うくらいですね。

fwrite 関数の戻り値

fwrite 関数の戻り値は下記の通りです。

  • 書き込んだデータの個数

fwrite 関数の使用例

fwrite 関数の使用例は下記の通りです。input.txt を読み込み、そのままコピーして output.txt に書き出す使用例としています。

include <stdio.h>

#define READ_SIZE 10

int main(void){
  FILE *fi;
  FILE *fo;
  
  char str[READ_SIZE];
  size_t ret;
  
  /* ファイルのオープン */
  fi = fopen("input.txt", "r");
  if(fi == NULL){
    printf("file open error:input.txt\n");
    return -1;
  } 
  
  fo = fopen("output.txt", "w");
  if(fo == NULL){
    printf("file open error:output.txt\n");
    fclose(fi);
    return -1;
  } 
  
  while(1){
    /* READ_SIZEバイト分読み込み */
    ret = fread(str, sizeof(char), READ_SIZE, fi);
    
    fwrite(str, sizeof(char), ret, fo);
    
    if(ret < READ_SIZE){
      /* 戻り値が第三引数よりも小さい
         のでファイルの終端に行き着いた */
      break; 
    } 
  } 
  
  /* ファイルのクローズ */
  fclose(fi);
  fclose(fo);
  
  return 0;
}

実行して作成される output.txt の中身は下記のようになります。

Good Morning...

"Hello"

Who are you?
Good Bye!!

スポンサーリンク

まとめ

このページではファイルの入出力の仕組みやファイル入出力に使用する標準関数の仕方について解説しました。ファイル入出力が出来るとC言語でできることの幅がかなり広がりますのでしっかりマスターしておきましょう!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です