本物のC

C の知識:stdio.h


「standard input/output」の名前の通り入出力が主です。

入出力

C の入出力はファイルであれ何らかのデバイスであれ、ストリーム(stream)へと抽象化して扱われます。

「stream」とは主に川などの「流れ」を意味しますが、これはファイル等とのデータのやり取りを、1 バイトずつ順に送るパイプの様なものを通してやっているイメージに基づきます。

プログラム
書き込み
… 'a' 'b' 'c' …

読み込み
ファイルとか

ストリームの情報はstdio.hの宣言するFILEという型で保持されます。(実際の受け渡しはポインタFILE *で行われます。)

例えばファイルに対して入出力を行う場合、fopenでファイルを開いてFILE *を取得し、最後にはfcloseでファイルを閉じます。

FILE *fopen(const char * restrict filename, const char * restrict mode);
int fclose(FILE *stream);

一方で OS の提供する標準入力stdin、標準出力stdout、標準エラー出力stderrは、プログラムの実行開始時点から開かれており利用可能です。

ストリームへの出力はfprintfなどの関数で行い、入力はfscanfなどで行います。

/* 出力関数 */
int fprintf(FILE * restrict stream, const char * restrict format, ...);
int fputs(const char * restrict s, FILE * restrict stream);
int fputc(int c, FILE *stream);
size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);
/* 入力関数 */
int fscanf(FILE * restrict stream, const char * restrict format, ...);
char *fgets(char * restrict s, int n, FILE * restrict stream);
int fgetc(FILE *stream);
size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);

stdio.hにはprintfなど先頭のfが無い関数もありますが、これは標準入出力を対象としたものです。つまりprintf("hello")fprintf(stdout, "hello")と同等です7.19.6.3#1

フォーマット指定

fprintfの三番目(printfの二番目)以降に渡された引数は、format中の%dといった部分へ順番に(文字列へ変換されて)出力されます。

C 言語の仕様上fprintfは引数の型の情報を何も受け取れないので、%に続く文字列によって引数のデータをどう解釈すべきか指示する必要があります。

%の後の文字列は次の要素で構成されます。

フラグ

0 個以上の以下のフラグ。

文字 意味
-符号が付かない場合に半角スペース を表示する
+ 符号(+-)を常に表示する。 よりも優先される
0 フィールドの空きを0で埋める
- 左詰めにする(デフォルトは右詰め)。0よりも優先される
# 出力を分かりやすくする。十六進数には0xを付ける、浮動小数点数は必ず.を表示するなど

最小フィールド幅(任意)

非負の整数か*

*ならば、今の引数は最小フィールド幅を指定するものと解釈され、その次の引数が変換対象となります。例えばprintf("%*d", 5, 1);printf("%5d", 1);と同じです。

フィールドの文字数がこの値に満たない場合、デフォルトでは半角スペース で左が埋められます。ただし0フラグがあれば0で、-フラグがあれば右が埋められます。

精度(任意)

.に続く*か整数。.のみだと.0に解釈されます。

.*は上と同様、引数を一つ取って精度を指定する整数に解釈します。

主に浮動小数点数の小数点以下の桁数を指定します。

サイズの指定(任意)

以下の様に解釈を行う型を変更します。

文字
hh char
h short
l long
ll long long
L long double
j intmax_t
z size_t
t ptrdiff_t

変換指定子

以下の何れかの文字により出力形式を指定します。

文字 デフォルトの型 意味 出力例
d i int 十進法の符号付き整数 123
u o x X unsigned int 符号無し整数
oは八進法、xXは十六進法
7B
f F double 十進法の浮動小数点数 12.300000
e E double 指数表記の浮動小数点数 1.230000E+001
g G double feFE
桁数に応じて選ばれる
12.3
a A double 十六進法の浮動小数点数 0XC.4CCCCCCCCCCDP+0
c unsigned char 文字 a
s char[] 文字列 abc
p void * ポインタ。書式は処理系依存 0061ff24
% %自身。%%の形でなければならない %
n int * ここまでに出力された文字数を引数の
ポインタの先へ書き込む

大文字/小文字は出力に於ける十六進数のafや指数表記のeなどに影響します。%xならば7b%Xならば7Bなど。

ファイル操作

stdio.hはファイルを削除するremove関数や、名前を変更するrename関数も提供しています。

int remove(const char *filename);
int rename(const char *old, const char *new);