C言語の標準入出力

本記事C言語の標準入出力（シーげんごのひょうじゅんにゅうしゅつりょく）では、C言語で提供される、ファイル入出力用の、標準Cライブラリヘッダ の大部分を構成する標準Cライブラリ関数について述べる。これらの機能は、1970年代初頭にベル研究所のによって書かれた、「ポータブルI/Oパッケージ」に由来し、正式にVersion 7 UnixでUnixオペレーティングシステムの一部になった。

C言語の標準入出力機能は、現代使われるプログラミング言語の中ではかなり貧弱であり、すべてのファイル操作をバイトストリーム (「入力ストリーム」あるいは「出力ストリーム」) の操作に抽象化する。C言語以前のプログラミング言語とは異なり、C言語はランダムアクセスを直接サポートしていない。ファイルの途中から読み取るには、プログラマは、ストリームを作成し、ファイルの途中へシークし、ストリームからバイトを順番に読み取らなければならない。

ファイル入出力のストリームモデルは、C言語とほぼ同時に開発されたUnixによって普及した。最近のオペレーティングシステムの大部分はUnixのストリームモデルを継承している。また、C言語の影響を受けた多くの言語はC言語のファイル入出力インターフェイスを継承しており、差異はほぼ存在しない (例: PHP)。

 概要 
C言語の標準入出力機能は、ストリームと呼ばれるオブジェクトを使用して、キーボード、プリンタ、端末などの物理デバイス、またはシステムでサポートされている他の種類のファイルを操作する。ストリームは、これらのデバイスを
同じ操作で操作するための抽象化に利用される。すなわち、すべてのストリームは、関連付けられている物理デバイスの差異に関係なく、同様のプロパティを持つ。

 関数 
ほとんどのC言語入出力関数は、 (または、C++の場合 上の 名前空間) に定義されている。

+ C言語の標準入出力関数一覧 機能 バイト文字 ワイド文字 説明 ファイル アクセスfopenファイルを開く (Windows上では非Unicodeファイル名、Linux上ではUTF-8ファイル名を使用可能)freopen既存のストリームで別のファイルを開くfflush出力ストリームを実際のファイルと同期するfcloseファイルを閉じるsetbufファイルストリームのバッファを設定するsetvbufファイルストリームのバッファとサイズを設定するfwideファイルストリームの入出力単位を設定または取得する  直接入出力freadファイルから読み取るfwriteファイルに書き込む非フォーマット 入出力fgetcgetcfgetwcgetwcファイルストリームからバイトまたはワイド文字を読み取るfgetsfgetwsファイルストリームからバイトまたはワイド文字列を1行読み取るfputcputcfputwcputwcファイルストリームにバイトまたはワイド文字を書き込むfputsfputwsファイルストリームにバイトまたはワイド文字列を書き込むgetchargetwchar標準入力ストリームからバイトまたはワイド文字を読み取るgets 改行またはファイルの終端に達するまで、標準入力ストリームからバイト文字列を読み取る (C99で非推奨、C11で削除)putcharputwchar標準出力ストリームにバイトまたはワイド文字を書き込むputs 標準出力ストリームにバイト文字列を書き込むungetcungetwcバイトまたはワイド文字をファイルストリームに戻すフォーマット 入出力scanffscanfsscanfwscanffwscanfswscanf標準入力ストリーム、ファイルストリーム、またはバッファからフォーマットされたバイトまたはワイド文字列を読み取るvscanfvfscanfvsscanfvwscanfvfwscanfvswscanf可変長引数リストを使用して、標準入力ストリーム、ファイルストリーム、またはバッファからフォーマットされたバイトまたはワイド文字列を読み取るprintffprintfsprintfsnprintfwprintffwprintfswprintf標準出力ストリーム、ファイルストリーム、またはバッファにフォーマットされたバイトまたはワイド文字列を出力するvprintfvfprintfvsprintfvsnprintfvwprintfvfwprintfvswprintf可変長引数リストを使用して、標準出力ストリーム、ファイルストリーム、またはバッファにフォーマットされたバイトまたはワイド文字列を出力するperror 現在のエラーの説明を標準エラーストリームに書き込むファイル
位置操作ftellftello現在のファイル位置指示子を取得するfseekfseekoファイル内の任意の位置にファイル位置指示子を移動するfgetpos現在のファイル位置指示子を取得するfsetposファイル内の任意の位置にファイル位置指示子を移動するrewindファイル位置指示子をファイルの先頭に移動するエラー
ハンドリングclearerrエラーをクリアするfeofファイルの終端かチェックするferrorファイルのエラーをチェックするファイル
操作removeファイルを削除するrenameファイルの名前を変更するtmpfile一時ファイルのストリームを作成するtmpnam一時ファイルの名前を作成する

 定数 
 で定義されている定数は次の通りである。
定数名説明EOFファイルの終端を表現する、 型の負の整数BUFSIZ 関数に渡すバッファの大きさを表す定数FILENAME_MAX処理系が許すファイル名の 型配列としての最大長FOPEN_MAX同時に開くことのできるファイル数、最低で8_IOFBF 関数にフルバッファリングを行うことを要求する際使用する整数_IOLBF 関数に行バッファリングを行うことを要求する際使用する整数_IONBF 関数にバッファリングを行なわないことを要求する際使用する整数L_tmpnam 関数が生成するファイル名を保持するために必要な 型配列の大きさを表す。NULLNULLポインター定数に展開されるマクロ。メモリ内の有効なオブジェクトのアドレスではないことが保証されているポインタ値を表す定数SEEK_CUR 関数にファイルの現在位置を基準に位置変更を行うことを要求する際使用する整数SEEK_END 関数にファイルの終端位置を基準に位置変更を行うことを要求する際使用する整数SEEK_SET 関数にファイルの先頭位置を基準に位置変更を行うことを要求する際使用する整数TMP_MAX 関数で生成可能な一意のファイル名の最大数、最低で25

 変数 
 で定義されている変数は次の通りである。

名前説明stdin標準入力ストリーム (通常はキーボード) を参照する 型へのポインタstdout標準出力ストリーム (通常は表示する端末) を参照する 型へのポインタstderr標準エラーストリーム (通常は表示する端末) を参照する 型へのポインタ

 データ型 
 で定義されているデータ型は次の通りである。

 – ファイルハンドルとしても知られている。入出力操作を実行するために必要な以下のようなファイルまたはテキストストリームに関する情報を保持しているプログラマから隠蔽された型である。
 ファイル記述子など、関連する入出力デバイスのプラットフォーム固有の識別子
 バッファ
 ストリームの方向の状態
 バッファ状態
 入出力状態
 モード (バイナリもしくはテキスト)
 EOF状態
 エラー状態
 現在位置とマルチバイト変換状態
 再入可能ロック (C11では必須)
 – ファイル内の位置を表す型
 – 演算子の結果の型であり、符号なし整数型

 拡張機能 
POSIX標準では、 に拡張を定義している。それによって、 関数を使用してメモリを自動で割り当てること、 関数と 関数を使用して、 型とファイル記述子を接続すること、メモリ上を参照するFILE型の参照を作成することが可能になる。

 例 
以下のCプログラムでは、 hogefile というバイナリファイルを開き、5バイト読み取り、ファイルを閉じている。

#include <stdio.h>
#include <stdlib.h>

int main(void) {
 char buffer;
 FILE* fp = fopen("hogefile", "rb");

 if (fp == NULL) {
 perror("\"hogefile\"を開けませんでした。");
 return EXIT_FAILURE;
 }

 for (int i = 0; i < 5; i++) {
 int rc = getc(fp);
 if (rc == EOF) {
 fputs("ファイルの読み取り中にエラーが発生しました。\n", stderr);
 return EXIT_FAILURE;
 }
 
 buffer[i] = rc;
 }

 fclose(fp);

 printf("読み取ったバイト列: %x %x %x %x %x\n", buffer, buffer,
 buffer, buffer, buffer);

 return EXIT_SUCCESS;
}

 stdioの代替 
 の代替がいくつか開発されている。これらの中には、ISO C++標準の一部である ライブラリがある。

他には、ベル研究所が開発しているSfio (Safe-fast / string-file I/O) ライブラリがある。1991年に開発されたこのライブラリは、 の設計における矛盾、危険な慣行、非効率性を回避することを目的にしている。特徴として、コールバック関数を導入してストリームに対して読み書きを行い、より柔軟にデータ処理を行うことを可能とすることが挙げられる。1997年に外部に公開された。