[C言語 標準ライブラリ] stdio.hの使い方

※本ブログでは、商品・サービスのリンク先にプロモーションを含みます。

スポンサーリンク

stdio.hは入出力の手段を実装するためのマクロ、型、関数が宣言および定義されています。

  1. マクロ
    1. _IOFBF
    2. _IOLBF
    3. _IONBF
    4. BUFSIZ
    5. EOF
    6. FILENAME_MAX
    7. FOPEN_MAX
    8. L_tmpnam
    9. NULL
    10. SEEK_CUR
    11. SEEK_END
    12. SEEK_SET
    13. TMP_MAX
    1. FILE
    2. fpos_t
    3. size_t
  2. 標準ストリーム
    1. stderr
    2. stdin
    3. stdout
  3. ファイル操作関数
    1. int remove(const char *filename)
    2. int rename(const char *old, const char *new)
    3. FILE *tmpfile(void)
    4. char *tmpnam(char *s)
  4. ファイルアクセス関数
    1. int fclose(FILE *stream)
    2. int fflush(FILE *stream)
    3. FILE *fopen(const char *filename, const char *mode)
    4. FILE *freopen(const char *filename, const char *mode, FILE *stream)
    5. void setbuf(FILE *stream, char *buf)
    6. int setvbuf(FILE *stream, char *buf, int mode, size_t size)
    7. int fprintf(FILE *stream, const char *format, …)
    8. int fscanf(FILE *stream, const char *format, …)
    9. int printf(const char *format, …)
    10. int scanf(const char *format, …)
    11. int snprintf(char * restrict s, size_t n, const char * restrict format, …)
    12. int sprintf(char *s, const char *format, …)
    13. int sscanf(const char *s, const char *format, …)
    14. int vfprintf(FILE *stream, const char *format, va_list arg)
    15. int vfscanf(FILE * restrict stream, const char * restrict format, va_list arg)
    16. int vprintf(const char *format, va_list arg)
    17. int vscanf(const char * restrict format, va_list arg)
    18. int vsnprintf(char * restrict s, size_t n, const char * restrict format, va_list arg)
    19. int vsprintf(char *s, const char *format, va_list arg)
    20. int vsscanf(const char * restrict s, const char * restrict format, va_list arg)
  5. 文字入出力関数
    1. int fgetc(FILE *stream)
    2. char *fgets(char *s, int n, FILE *stream)
    3. int fputc(int c, FILE *stream)
    4. int fputs(const char *s, FILE *stream)
    5. int getc(FILE *stream)
    6. int getchar(void)
    7. char *gets(char *s)
    8. int putc(int c, FILE *stream)
    9. int putchar(int c)
    10. int puts(const char *s)
    11. int ungetc(int c, FILE *stream)
  6. 直接入出力関数
    1. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
    2. size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  7. ファイル位置付け関数
    1. int fgetpos(FILE *stream, fpos_t *pos)
    2. int fseek(FILE *stream, long int offset, int whence)
    3. int fsetpos(FILE *stream, const fpos_t *pos)
    4. long int ftell(FILE *stream)
    5. void rewind(FILE *stream)
  8. エラー処理関数
    1. void clearerr(FILE *stream)
    2. int feof(FILE *stream)
    3. int ferror(FILE *stream)
    4. int perror(const char *s)
スポンサーリンク

マクロ

_IOFBF

setvbuf関数の第3引数として使用します。
入出力の完全バッファリングを行うことを指示します。

_IOLBF

setvbuf関数の第3引数として使用します。
入出力の行バッファリングを行うことを指示します。

_IONBF

setvbuf関数の第3引数として使用します。
入出力のバッファリングをしないことを指示します。

BUFSIZ

setbuf関数で使用されるバッファの大きさを示す整数です。
環境依存ですが、最低でも256が保証されます。

EOF

ファイルの終端(End Of File)を示す、int型の負の値をもつ整数です。

FILENAME_MAX

オープン可能なファイル名の最大長(char型の配列要素数)を示す整数です。(値は実装依存)

FOPEN_MAX

同時にオープン可能なファイル数を示す整数です。(値は実装依存)

L_tmpnam

tmpnam関数によって生成される一時ファイルを保持するために必要なchar型の配列要素数を示す整数です。

NULL

空(ヌル)ポインタ定数です。
locale.h、stddef.h、stdlib.h、string.h、time.h、wchar.hヘッダでも定義されています。

SEEK_CUR

fseek関数の第3引数として使用します。
シークの起点を現在のファイル位置にすることを指示します。

SEEK_END

fseek関数の第3引数として使用します。
シークの起点をファイルの終端にすることを指示します。

SEEK_SET

fseek関数の第3引数として使用します。
シークの起点をファイルの先頭にすることを指示します。

TMP_MAX

tmpnam関数によって生成されるファイルの最大数を示す整数です。(値は実装依存)

FILE

ファイル位置表示子、紐づけられたバッファへのポインタ、エラー表示子、ファイル終了表示子などのストリームを制御するために必要なすべての情報を記録することができるオブジェクト型です。

  • ファイル位置表示子(file position indicator)
    ファイル内のすべての位置を特定するために必要なすべての情報。
  • 紐づけられたバッファへのポインタ
  • エラー表示子(error indicator)
    読み取りエラーまたは書き込みエラーが起こったかどうかを記録します。
  • ファイル終了表示子(end-of-file indicator)
    ファイルの終わりに達したかどうかを記録します。

fpos_t

ファイルの中の任意の位置を指定するために、必要な全ての情報を記録することが可能なオブジェクト型です。

size_t

sizeof演算子の結果を表すための符号無し整数型です。
メモリ領域のオブジェクトサイズを表すのに適しており、配列の要素を参照する際に使用します。
stddef.h、stdlib.h、string.h、time.h、wchar.hヘッダでも定義されています。

標準ストリーム

OSのシェルで実装されている標準化された機能です。

stderr

標準エラーストリームに結び付けられた、FILEオブジェクトへのポインタです。

stdin

標準入力ストリームに結び付けられた、FILEオブジェクトへのポインタです。

stdout

標準出力ストリームに結び付けられた、FILEオブジェクトへのポインタです。

ファイル操作関数

int remove(const char *filename)

引数のfilenameで指定されたファイルを削除します。
既にファイルがオープンされている場合に、remove()を実行した場合の動作は実装依存です。
成功したときは0、失敗したときは0以外の値が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    if(remove("example.txt") == 0){
        printf("ファイルの削除に成功しました。\n");
    }else{
        printf("ファイルの削除に失敗しました。\n");
    }

    return 0;
}

このコードは、”example.txt”という名前のファイルを削除しようとします。
remove関数が成功すると0を返し、その場合は”ファイルの削除に成功しました。”と表示します。
ファイルが存在しないか、あるいは何らかの理由で削除に失敗した場合、remove関数は非0の値を返し、”ファイルの削除に失敗しました。”と表示します。

int rename(const char *old, const char *new)

引数oldで指定された名前のファイル名を、引数newで指定された名前に変更します。
newで指定したファイル名が既にしていた場合の動作は実装依存です。
成功したときは0、失敗したときは0以外の値が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    if(rename("old_name.txt", "new_name.txt") == 0){
        printf("ファイル名の変更に成功しました。\n");
    }else{
        printf("ファイル名の変更に失敗しました。\n");
    }

    return 0;
}

このコードは、”old_name.txt”という名前のファイルを”new_name.txt”にリネームします。
rename関数が成功すると0を返し、その場合は”ファイル名の変更に成功しました。”と表示します。
ファイルが存在しないか、あるいは何らかの理由でリネームに失敗した場合、rename関数は非0の値を返し、”ファイル名の変更に失敗しました。”と表示します。

FILE *tmpfile(void)

一時的なファイルを作成します。この関数で作成された関数はプログラムの終了時に自動的に削除されます。このためファイルをクローズする必要がありません。
ただし、プログラムが異常終了(abortなどで終了)した場合、一時ファイルが削除されるかどうかは実装依存です。
成功したときは、一時ファイルへのポインタが返され、失敗したときはNULLポインタが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *tmpf = tmpfile();
    fputs("Hello World", tmpf);
    rewind(tmpf);
    char buf[12];
    fgets(buf, sizeof(buf), tmpf);
    printf("%s\n", buf);

    // ファイルは自動的に削除されますが、明示的に閉じることもできます。
    fclose(tmpf);

    return 0;
}

このコードは次の手順で動作します。

  1. tmpfile関数は一時的なファイルを作成し、そのファイルへのポインタを返します。
  2. fputs関数を使用して、そのファイルに”Hello World”と書き込みます。
  3. rewind関数を使用して、ファイルポインタをファイルの始めに戻します。
  4. fgets関数を使用して、書き込んだ文字列を読み取ります。
  5. 読み取った文字列をprintfで出力します。

なお、tmpfile関数はバイナリモードでファイルを開くため、テキストとバイナリデータの両方を書き込むことができます。

char *tmpnam(char *s)

一時ファイルとして使用可能なファイル名を生成します。
この関数は、呼ばれる度に異なるファイル名を最大でTMP_MAX回生成します。
TMP_MAX回以上呼ばれた場合の動作は実装依存です。
引数がNULLポインタの場合、内部の静的オブジェクトに結果を書き込み、そのオブジェクトへのポインタを返します。 続けて呼んだ場合、このオブジェクトは変更される場合があります。
引数がNULLポインタではない場合、少なくともL_tmpnam文字の長さを持つ配列とみなされ、この配列に結果が書き込まれ、引数を返します。
ファイル名の生成に失敗したときはNULLポインタが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    char tempname[L_tmpnam];
    char *filename = tmpnam(tempname);
    
    if(filename){
        printf("生成されたテンポラリファイル名:%s\n", filename);
    }else{
        printf("テンポラリファイル名の生成に失敗しました\n");
    }

    return 0;
}

このコードは次の手順で動作します。

  1. tmpnam関数を使用して一時的なファイル名を生成します。ファイル名はtempnameという文字配列に格納されます。
  2. tmpnam関数が成功すると、filenameは一時ファイル名を指すポインタとなります。失敗すると、NULLを返します。
  3. 生成したファイル名を表示します。

注意すべきは、この関数が生成する名前は一意であると保証されていますが、その名前のファイルがすでに存在しないとは限らないということです。また、tmpnam関数はtmpnam(NULL)の形式でも呼び出すことができ、この場合は静的に確保されたバッファに一時ファイル名が書き込まれ、そのバッファへのポインタが返されます。しかし、この形式を使用すると、スレッドセーフではなくなるため注意が必要です。

さらに、tmpnam関数は一部の環境ではセキュリティ上のリスクがあるとされ、代わりにより安全なmkstempやtmpfileなどの関数が推奨されています。

スポンサーリンク

ファイルアクセス関数

int fclose(FILE *stream)

引数streamで指定されるストリームをフラッシュし、関連付けられているファイルを閉じます。
ストリームにバッファされた、書き込まれていないデータはすべてファイルに書き込まれます。
バッファされただけで、まだ読み込まれていないデータは破棄されます。
ストリームとバッファは切り離され、バッファは解放されます。
成功したときは0が返され、失敗したときはEOFが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp = fopen("sample.txt", "r");
    if(fp == NULL){
        printf("ファイルオープンに失敗しました。\n");
        return 1;
    }

    // 何らかのファイル操作
    // ...

    if(fclose(fp) == EOF){
        printf("ファイルクローズに失敗しました。\n");
        return 1;
    }

    return 0;
}

このコードは次の手順で動作します。

  1. fopen関数を使用して、ファイル sample.txt を読み込みモードで開きます。戻り値は FILE ポインタで、これが後続のファイル操作で使用されます。ファイルのオープンに失敗すると、fopenはNULLを返します。
  2. ファイル操作(ここでは省略)を行います。
  3. fclose関数を使用してファイルを閉じます。fcloseは成功すると0を返し、エラーが発生するとEOFを返します。

int fflush(FILE *stream)

引数streamが出力ストリームまたは最新の操作が入力されていない更新ストリームを指している場合、fflush関数は、そのストリームに対する未書き込みのデータをホスト環境に配信してファイルに書き込ませます。
それ以外の場合の動作は未定義です。
streamがNULLポインタの場合、上記の動作が定義されているすべてのストリームに対してこのフラッシュ動作を実行します。
ストリームのエラーインジケータを設定し、成功した場合は0が返され、書き込みエラーが発生した場合はEOFが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;

    fp = fopen("test.txt", "w");
    if(fp == NULL){
        printf("ファイルのオープンに失敗しました。\n");
        return -1;
    }

    // この時点でファイルへの書き込みはバッファされている可能性がある
    fprintf(fp, "ファイルへの書き込み中...\n");
    
    // ここでバッファを強制的にフラッシュ(実際のファイルへの書き込みを強制)
    fflush(fp); 

    fprintf(fp, "ファイルに書き足す...\n");

    fclose(fp);

    return 0;
}

このコードでは、fprintf関数を使用してファイルに文字列を書き込み、その後でfflush関数を呼び出してバッファをフラッシュ(空に)します。その結果、最初のfprintfによる文字列が確実にファイルに書き込まれます。

注意点としては、fclose関数を呼び出すと、関連付けられたバッファは自動的にフラッシュされるため、通常は手動でfflushを呼び出す必要はありません。ただし、ファイルをクローズせずにデータを確実に書き込みたい場合などには、fflushを使うことがあります。

FILE *fopen(const char *filename, const char *mode)

引数filenameが指す名前のファイルを、引数modeで指定したモードでオープンします。
modeは次のいずれかの文字列を指定します。下表以外の文字列を指定した場合の動作は未定義です。

modeに指定する文字列モードの説明
rテキストファイルの読み取りモード
wテキストファイルの書き込みモード
x書き込み用テキストファイルの作成 ※C11
aテキストファイルの追加書き込みモード
rbバイナリファイルの読み取りモード
wbバイナリファイルの書き込みモード
wbx書き込み用バイナリファイルの作成 ※C11
abバイナリファイルの追加書き込みモード
r+テキストファイルの読み取り/書き込みモード
w+テキストファイルの書き込み/読み取りモード
a+テキストファイルの読み取り/追加書き込みモード
r+b または rb+バイナリファイルの読み取り/書き込みモード
w+b または wb+バイナリファイルの書き込み/読み取りモード
w+bx または wb+xアップデート用バイナリファイルの作成 ※C11
a+b または ab+バイナリファイルの読み取り/追加書き込みモード

排他モード(最後の文字が’x’)でファイルオープンしたとき、ファイルがすでに存在するか、作成できない場合は失敗します。
成功したときはストリームを制御するオブジェクトへのポインタが返され、失敗したときはNULLポインタが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;
    char ch;

    fp = fopen("test.txt", "r");
    if(fp == NULL){
        printf("ファイルのオープンに失敗しました。\n");
        return -1;
    }

    while((ch = fgetc(fp)) != EOF){
        putchar(ch);
    }

    fclose(fp);

    return 0;
}

このコードでは、まずfopen関数を使用してファイルを読み込みモードで開きます。それからfgetc関数を使用してファイルから一文字ずつ読み込み、putchar関数を使用してその文字を表示します。この操作をファイルの終わり(EOF)まで行います。最後にfclose関数を使用してファイルを閉じます。

注意点としては、fopen関数を使用してファイルを開いた後は、必ずfclose関数を使用してファイルを閉じることが重要です。これは、開いたファイルがシステムリソースを占有してしまうためです。また、ファイルが開けなかった場合(例えばファイルが存在しない場合やパーミッションがない場合など)には、fopenはNULLを返すため、そのチェックも必要です。

FILE *freopen(const char *filename, const char *mode, FILE *stream)

引数filenameが指す文字列をファイル名とするファイルを開き、引数streamが指すストリームをそれに関連付けます。
引数modeはfopen関数と同様に使用されます。
filenameがNULLポインタの場合、ストリームのモードをmodeで指定されたものに変更し、現在のストリームに関連付けられているファイルの名前が使われているかのように動作します。どのようなモードの変更が許可されるか、またどのような状況下で許可されるかは実装定義です。
指定されたストリームに関連付けられているすべてのファイルを閉じます。
ファイルのクローズに失敗しても無視されます。
ストリームのエラー・インジケータとファイル終了インジケータはクリアされます。
成功したときはstreamの値が返され、失敗したときはNULLポインタが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;

    // 標準出力をoutput.txtにリダイレクト
    fp = freopen("output.txt", "w", stdout);
    if(fp == NULL){
        fprintf(stderr, "標準出力のリダイレクトに失敗しました。\n");
        return -1;
    }
    printf("これは、output.txtに書き込まれます。\n");

    // 標準エラー出力をerror.txtにリダイレクト
    fp = freopen("error.txt", "w", stderr);
    if(fp == NULL){
        fprintf(stderr, "標準エラー出力のリダイレクトに失敗しました。\n");
        return -1;
    }
    fprintf(stderr, "これはerror.txtに書き込まれます。\n");

    return 0;
}

このコードでは、freopen関数を使用して、標準出力をoutput.txtに、標準エラー出力をerror.txtにリダイレクトしています。その結果、それぞれの出力が指定したファイルに書き込まれます。

このコードでは、freopen関数が失敗した場合のエラーチェックも行っています。freopenが失敗した場合(例えば、指定したファイルが開けない場合など)、NULLが返されます。

ただし、一般的にはプログラムが終了すると、標準入出力ストリームは自動的にクローズされます。しかし、リダイレクトした場合でも確実にファイルをクローズするため、明示的にfclose関数を呼び出すことをお勧めします。また、標準出力や標準エラー出力を再度コンソールにリダイレクトするための汎用的な方法は存在しないため、再リダイレクトが必要な場合には別のアプローチを考慮する必要があります

void setbuf(FILE *stream, char *buf)

引数streamが指すファイルのストリームに対して、引数bufが指す配列をバッファとした、入出力用のバッファを設定します。
modeを_IOFBF, sizeをBUFSIZとしたsetvbuf関数と同じ動作です。ただし、bufがNULLポインタの場合、modeを_IONBFとしたsetvbuf関数と同じ動作です。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;

    fp = fopen("output.txt", "w");
    if(fp == NULL){
        perror("ファイルオープンに失敗しました。");
        return -1;
    }

    // ファイルストリームfpのバッファリングを無効にする
    setbuf(fp, NULL);

    fprintf(fp, "Hello, World!\n");
    fprintf(fp, "これはすぐに書き込む。\n");

    fclose(fp);

    return 0;
}

このコードでは、setbuf関数を使用して、ファイルストリームfpのバッファリングを無効にしています。その結果、fprintfによる出力はすぐにファイルに書き込まれます(バッファリングが無効であるため)。

通常、ファイルストリームはバッファリングが有効になっています。つまり、出力は一定のサイズのバッファに保存され、バッファが満たされるか、明示的にフラッシュされる(fflush関数の使用)、あるいはファイルが閉じられるまで、実際のファイルには書き込まれません。

しかし、場合によっては、このバッファリングを無効にすることが有用な場合があります。例えば、デバッグ出力をすぐにファイルに書き込むようにしたい場合や、多くの小さな書き込みを行うプログラムでバッファリングの遅延が許容できない場合などです。このようなケースでsetbuf関数を使用してバッファリングを無効にします。

int setvbuf(FILE *stream, char *buf, int mode, size_t size)

引数streamが指すファイルのストリームに対して、引数sizeの大きさを持った引数bufが指す配列をバッファとし、引数modeで指定したバッファリングの方法で、入出力用のバッファを設定します。
bufにNULLを指定した場合、setvbuf関数がsizeの大きさを持ったバッファを割り付けます。
modeは次のいずれかを指定します。

modeに指定する値モード説明
_IOFBF完全バッファリングバッファがいっぱいになった時点で、ホスト環境へ、またはホスト環境から文字をブロック単位で転送します。
_IOLBF行バッファリング改行文字に達した時点で、ホスト環境へ、またはホスト環境から文字をブロック単位で転送します。
_IONBFバッファリングをしない文字が入力元から、または出力先へ可能な限りすぐ現れる。

成功したときは0が返され、modeに無効な値が指定された場合、または要求に従うことができなかった場合は0以外の値が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;
    char buf[BUFSIZ];

    fp = fopen("output.txt", "w");
    if(fp == NULL){
        perror("ファイルオープンに失敗しました。");
        return -1;
    }

    // ファイルストリームfpのバッファリングをフルバッファリングに設定し、自分のバッファを使用する
    if(setvbuf(fp, buf, _IOFBF, BUFSIZ) != 0){
        perror("バッファの設定に失敗しました。");
        return -1;
    }

    fprintf(fp, "Hello, World!\n");
    fprintf(fp, "バッファがいっぱいになったときや、ファイルが閉じられたときに書き込まれます。\n");

    fclose(fp);

    return 0;
}

このコードでは、ファイルストリームfpのバッファリングをフルバッファリングに設定し、バッファとして配列bufを使用しています。その結果、fprintfによる出力は、バッファが満たされるか、明示的にフラッシュされる(fflush関数の使用)、あるいはファイルが閉じられるまで、実際のファイルには書き込まれません。

int fprintf(FILE *stream, const char *format, …)

引数formatが指す書式文字列に従って、引数streamが指すストリームへ書き込みます。
書式文字列には、それに続く任意個数の実引数と同じ数だけの変換指定が含まれる必要があります。
書式文字列に含まれる変換指定の部分が、それに対応する後の実引数の値によって置換されます。
成功したときは書き出された文字数が返されます。出力エラーまたは表現形式エラーが発生したときは負の値が返されます。
変換指定は次のように指定します。

%[フラグ][最小フィールド幅][.][精度][長さ修飾子]変換指定子

※[]は省略可能であることを示します。

フラグ

  • ‘-‘
    変換結果をフィールド内に左詰めにします(デフォルトでは右詰)。
  • ‘+’
    符号付き変換の結果を常に正符号又は負符号で始めます(デフォルトでは負の値の場合のみ負符号で始めます)。
  • ‘ ‘ (space)
    符号付き変換の結果の最初の文字が符号でない場合、1個の空白を結果の前に付けます。
  • ‘#’
    変換指定子がoなら「0」を、xなら「0x」を、Xなら「0X」を結果の前に付加します。変換指定子がa, A, e, E, f, F, g, Gなら、小数点文字の後ろに数字が続かない場合でも、浮動小数点数の変換の結果に常に小数点文字を含めます。変換指定子がg, Gなら、後ろの続く0を結果から取り除きません。
  • ‘0’
    0を文字列の左に付加することができます。

最小フィールド幅

値を変換した結果の文字数が最小フィールド幅より少ない場合、最小フィールド幅を満たすまで左側に(-フラグがあるときは右側に)空白を詰めることです。

精度

変換指定子がd, i, u, x, Xなら、出力する数字の最小の個数を指定します。
変換指定子がa, A, e, E, f, Fなら、小数点文字の後ろに出力すべき数字の個数を指定します。
変換指定子がg, Gなら、最大の有効桁数を指定します。
変換指定子がsなら、書き込む最大のバイト数を指定します。

長さ修飾子

修飾子説明導入バージョン
hh実引数は char 型C99以降。
h実引数は short 型全バージョン。
l実引数は long 型
または wchar_t 型
または double 型
wchar_t についてはC95以降。
double についてはC99以降。
ll実引数は long long 型C99以降。
j実引数は intmax_t 型C99以降。
z実引数は size_t 型C99以降。
t実引数は ptrdiff_t 型C99以降。
L実引数は long double 型全バージョン。

変換指定子

変換指定説明
%d, %i実引数を符号付き10進表記に変換します。
%u実引数を符号無し10進表記に変換します。
%o実引数を符号無し8進表記に変換します。
%x, %X実引数を符号無し16進表記に変換します。
%xは英字abcdefを、%Xは英字ABCDEFを用います。
%f, %F実引数を小数形式の10進浮動小数点数表記に変換します。
%e, %E実引数を指数形式の10進浮動小数点数表記に変換します。
%g, %G実引数を小数形式または指数形式の10進浮動小数点数表記に変換します。
%a, %A実引数を指数形式の16進浮動小数点数表記に変換します。
%c実引数を文字に変換します。
%s実引数を文字列に変換します。
%pポインタの値に変換します。
%n整数変数に出力した文字数を格納します。
%%‘%’を出力します。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;

    fp = fopen("output.txt", "w");
    if(fp == NULL){
        perror("ファイルのオープンに失敗しました。");
        return -1;
    }

    int num = 100;
    const char *str = "Hello, World!";
    
    // フォーマットを指定してデータを出力
    fprintf(fp, "num = %d\n", num);
    fprintf(fp, "str = %s\n", str);

    fclose(fp);

    return 0;
}

このコードでは、変数numとstrの値をファイルに出力しています。フォーマット文字列では、%dが整数の変換指定子、%sが文字列の変換指定子として機能しています。

int fscanf(FILE *stream, const char *format, …)

引数formatが指す書式文字列に従って、streamが指すストリームから入力を、任意個数の実引数へ読み込みます。
書式文字列には、それに続く任意個数の実引数と同じ数だけの変換指定が含まれる必要があります。
ストリームからの入力が、書式文字列に含まれる変換指定に従って、それに対応する後の実引数が指す変数に代入されます。
変換が一つも行われないまま入力誤りが発生した場合、マクロEOFの値が返されます。
その他の場合、代入された入力項目の個数が返されます。
この個数は、入力中に照合誤りが発生すると、与えられた入力項目の個数より少なくなることもあり、0になることもあります。
変換指定は次のように指定します。

%[*][最大フィールド幅][長さ修飾子]変換指定子

※[]は省略可能であることを示す。

代入抑止文字です。
「*」を指定すると、入力は変換されず、読み飛ばされます。

最大フィールド幅

最大フィールド幅(文字で数えて)を指定する正の10進整数です。
入力から指定した文字数だけ変換されます。

長さ修飾子

修飾子説明導入バージョン
hh実引数は char 型C99以降。
h実引数は short 型全バージョン。
l実引数は long 型
または wchar_t 型
または double 型
wchar_t についてはC95以降。
double についてはC99以降。
ll実引数は long long 型C99以降。
j実引数は intmax_t 型C99以降。
z実引数は size_t 型C99以降。
t実引数は ptrdiff_t 型C99以降。
L実引数は long double 型全バージョン。

変換指定子

変換指定説明
%d入力を符号付き10進整数に変換します。
%i入力を符号付き整数に変換します。
%u入力を符号無し10進整数に変換します。
%o入力を符号無し8進整数に変換します。
%x入力を符号無し16進整数に変換します。
%a, %e, %f, %g入力を浮動小数点数に変換します。
%c入力を文字に変換します。
%s入力を文字列に変換します。
%p入力をポインタの値に変換します。
%n整数変数に入力した文字数を格納します。
%%1つの%と照合します。
%[走査文字の並び]走査文字の並びに含まれる文字のみを入力し、文字列に変換します。
[の直後に^を指定した場合、走査文字の並びに含まれない文字のみを入力し、文字列に変換します。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp;

    fp = fopen("input.txt", "r");
    if(fp == NULL){
        perror("ファイルのオープンに失敗しました。");
        return -1;
    }

    int num;
    char str[100];

    // フォーマットを指定してデータを入力
    fscanf(fp, "num = %d\n", &num);
    fscanf(fp, "str = %s\n", str);

    printf("ファイルからの読み込み:num = %d, str = %s\n", num, str);

    fclose(fp);

    return 0;
}

このプログラムで使用するinput.txt:

num = 100
str = Hello,World!

このコードでは、ファイルから変数numとstrの値を入力しています。フォーマット文字列では、%dが整数のプレースホルダー、%sが文字列のプレースホルダーとして機能しています。

int printf(const char *format, …)

引数formatが指す書式文字列に従って、標準出力へ書き込みます。
stdoutを実引数として付加したfprintf関数と同等です。
成功したときは、書き出された文字数が返されます。出力エラーまたは表現形式エラーが発生したときは、負の値が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    int num = 100;
    const char *str = "Hello, World!";

    // フォーマットを指定してデータを出力
    printf("num = %d\n", num);
    printf("str = %s\n", str);

    return 0;
}

実行結果:

num = 100
str = Hello, World!

int scanf(const char *format, …)

引数formatが指す書式文字列に従って、標準入力を任意個数の実引数へ読み込みます。
stdinを実引数として付加したfscanf関数と同等です。
変換が一つも行われないまま入力誤りが発生した場合、マクロEOFの値が返されます。
その他の場合、代入された入力項目の個数が返されます。この個数は、入力中に照合誤りが発生すると、与えられた入力項目の個数より少なくなることもあり、0になることもあります。

使用例:

#include <stdio.h>

int main(void)
{
    int num;
    char str[100];

    // ユーザーに入力を促す
    printf("数字を入力してください:");
    scanf("%d", &num);
    
    printf("文字列を入力してください:");
    scanf("%s", str);  // 注意: スペースは読み込まれません

    // 入力されたデータを出力
    printf("入力されたデータは、num = %d, str = %s\n", num, str);

    return 0;
}

コンソールへの入力:

100
Hello,World!

実行結果:

入力されたデータは、num = 100, str = Hello,World!

int snprintf(char * restrict s, size_t n, const char * restrict format, …)

引数formatが指す書式文字列に従って、nで指定した書き込む文字数分だけ、sが指す配列へ書き込みます。
生成された出力をストリームではなく実引数sで指定する配列に書き込むことを除いては、fprintf関数と同等です。
書き込む文字数にはNULL文字を含みます。
領域の重なり合うオブジェクト間でコピーが行われるとき、その動作は未定義です。
成功したときは、nが十分に大きい場合に配列に書き込んだはずの文字数が返されます。
ただし、終端NULL文字は含みません。
表現形式エラーが発生したときは、負の値が返されます。
すなわち、返却値が非負かつn未満の場合、そしてその場合に限り、NULL文字で終了している出力が完全に書き込まれています。

使用例:

#include <stdio.h>

int main(void)
{
    int num = 100;
    const char *str = "Hello, World!";
    char buffer[100];

    // フォーマットを指定してデータを文字列に書き込む
    snprintf(buffer, sizeof(buffer), "num = %d, str = %s\n", num, str);

    // 書き込んだ文字列を出力
    printf("%s", buffer);

    return 0;
}

実行結果:

num = 100, str = Hello, World!

int sprintf(char *s, const char *format, …)

引数formatが指す書式文字列に従って、sが指す配列へ書き込みます。
生成された出力をストリームではなく実引数sで指定する配列に書き込むことを除いては、fprintf関数と同等です。
書き込まれた出力文字の列の後にNULL文字を書き込みます。
領域の重なり合うオブジェクト間でコピーが行われるとき、その動作は未定義です。
成功したときは、配列に書き込まれた文字数が返されます。
ただし、NULL文字は文字数に含めません。
表現形式エラーが発生したときは、負の値が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    int num = 100;
    const char *str = "Hello, World!";
    char buffer[100];

    // フォーマットを指定してデータを文字列に書き込む
    sprintf(buffer, "num = %d, str = %s\n", num, str);

    // 書き込んだ文字列を出力
    printf("%s", buffer);

    return 0;
}

実行結果:

num = 100, str = Hello, World!

int sscanf(const char *s, const char *format, …)

引数formatが指す書式文字列に従って、sが指す文字列を、任意個数の実引数へ読み込みます。
入力をストリームではなく実引数sで指定される文字列から得ることを除けば、fscanf関数と同等です。
文字列の終わりに達することが、fscanf関数でファイルの終わりに達することと同等です。
領域の重なり合うオブジェクト間でコピーが行われるとき、その動作は未定義です。
変換が一つも行われないまま入力誤りが発生した場合、マクロEOFの値が返されます。
その他の場合、代入された入力項目の個数が返されます。
この個数は、入力中に照合誤りが発生すると、与えられた入力項目の個数より少なくなることもあり、0になることもあります。

使用例:

#include <stdio.h>

int main(void)
{
    const char *str = "123 Hello,World!";
    int num;
    char buffer[50];

    // フォーマットを指定してデータを読み込む
    sscanf(str, "%d %s", &num, buffer);

    // 読み込んだデータを出力
    printf("num = %d, buffer = %s\n", num, buffer);

    return 0;
}

実行結果:

num = 123, buffer = Hello,World!

int vfprintf(FILE *stream, const char *format, va_list arg)

引数formatが指す書式文字列に従って、可変個数の実引数のリストを、streamが指すストリームへ書き込みます。
可変個数の実引数並びを、argで置き換えたfprintf関数と同等です。
vfprintf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vfprintf関数はva_endマクロを呼び出しません。
成功したときは、書き出された文字数が返されます。
出力エラーまたは表現形式エラーが発生したときは、負の値が返されます。

使用例:

#include <stdio.h>
#include <stdarg.h>

void write_formatted(FILE *file, const char *format, ...)
{
    va_list args;

    // 引数リストを初期化
    va_start(args, format);

    // フォーマットに従ってデータをファイルに書き込む
    vfprintf(file, format, args);

    // 引数リストをクリーンアップ
    va_end(args);
}

int main(void)
{
    FILE *file = fopen("output.txt", "w");
    if(file != NULL){
        write_formatted(file, "%s, %s\n", "Hello", "World!");
        fclose(file);
    }

    return 0;
}

実行結果:(output.txtへの出力結果)

Hello, World!

int vfscanf(FILE * restrict stream, const char * restrict format, va_list arg)

引数formatが指す書式文字列に従って、streamが指すストリームから入力を、可変個数の実引数のリストへ読み込みます。
可変個数の実引数並びをargで置き換えたfscanf関数と同等です。
vfscanf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vfscanf関数はva_endマクロを呼び出しません。
変換が一つも行われないまま入力誤りが発生した場合、マクロEOFの値が返されます。
その他の場合、代入された入力項目の個数が返されます。
この個数は、入力中に照合誤りが発生すると、与えられた入力項目の個数より少なくなることもあり、0になることもあります。

使用例:

#include <stdio.h>
#include <stdarg.h>

void read_from_file(const char* filename, const char* format, ...)
{
    FILE *file = fopen(filename, "r");
    if(file == NULL){
        perror("ファイルオープンに失敗しました。");
        return;
    }

    va_list args;
    va_start(args, format);
    vfscanf(file, format, args);
    va_end(args);

    fclose(file);
}

int main(void)
{
    int myInt;
    float myFloat;
    read_from_file("input.txt", "%d %f", &myInt, &myFloat);

    printf("読み込んだ値:%d, %f\n", myInt, myFloat);

    return 0;
}

このプログラムで使用するinput.txt:

123 45.67

実行結果:

読み込んだ値:123, 45.669998

int vprintf(const char *format, va_list arg)

引数formatが指す書式文字列に従って、可変個数の実引数のリストを、標準出力へ書き込みます。
可変個数の実引数並びをargで置き換えたprintf関数と同等です。
vprintf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vprintf関数はva_endマクロを呼び出しません。
成功したときは、書き出された文字数が返されます。
出力エラーまたは表現形式エラーが発生したときは、負の値が返されます。

使用例:

#include <stdio.h>
#include <stdarg.h>

void error_message(const char* format, ...)
{
    va_list args;
    va_start(args, format);

    fprintf(stderr, "Error: ");
    vfprintf(stderr, format, args);
    fprintf(stderr, "\n");

    va_end(args);
}

int main(void)
{
    int error_code = 404;
    const char *error_detail = "リソースが見つかりません。";

    error_message("エラーが発生しました。エラーコード:%d、詳細:%s", error_code, error_detail);

    return 0;
}

実行結果:

Error: エラーが発生しました。エラーコード:404、詳細:リソースが見つかりません。

int vscanf(const char * restrict format, va_list arg)

引数formatが指す書式文字列に従って、標準入力を、可変個数の実引数のリストへ読み込みます。
可変個数の実引数並びをargで置き換えたscanf関数と同等です。
vscanf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vscanf関数はva_endマクロを呼び出しません。
変換が一つも行われないまま入力誤りが発生した場合、マクロEOFの値が返されます。
その他の場合、代入された入力項目の個数が返されます。
この個数は、入力中に照合誤りが発生すると、与えられた入力項目の個数より少なくなることもあり、0になることもあります。

使用例:

#include <stdio.h>
#include <stdarg.h>

void read_from_stdin(const char* format, ...)
{
    va_list args;
    va_start(args, format);
    vscanf(format, args);
    va_end(args);
}

int main(void)
{
    int myInt;
    float myFloat;
    printf("整数と浮動小数点をスペースで区切って入力してください。: ");
    read_from_stdin("%d %f", &myInt, &myFloat);

    printf("読み込んだ値:int=%d, float=%f\n", myInt, myFloat);

    return 0;
}

コンソールへの入力:

1234 56.78

実行結果:

読み込んだ値:int=1234, float=56.779999

int vsnprintf(char * restrict s, size_t n, const char * restrict format, va_list arg)

引数formatが指す書式文字列に従って、可変個数の実引数のリストを、nで指定した書き込む文字数分だけ、sが指す配列へ書き込みます。
可変個数の実引数並びをargで置き換えたsnprintf関数と同等です。
vsnprintf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vsnprintf関数はva_endマクロを呼び出しません。
領域の重なり合うオブジェクト間でコピーが行われるとき、その動作は未定義です。
成功したときは、nが十分に大きい場合に配列に書き込んだはずの文字数が返されます。
ただし、終端NULL文字は含みません。
表現形式エラーが発生した場合、負の値が返されます。
すなわち、返却値が非負かつn未満の場合、そしてその場合に限り、NULL文字で終了している出力が完全に書き込まれています。

使用例:

#include <stdio.h>
#include <stdarg.h>

#define MAX_ERROR_MESSAGE_SIZE 256

void generate_error_message(char* buffer, const char* format, ...)
{
    va_list args;
    va_start(args, format);

    vsnprintf(buffer, MAX_ERROR_MESSAGE_SIZE, format, args);

    va_end(args);
}

int main(void)
{
    char error_message[MAX_ERROR_MESSAGE_SIZE];

    int error_code = 404;
    const char *error_detail = "リソースが見つかりません。";

    generate_error_message(error_message, "エラーが発生しました。エラーコード:%d、詳細:%s", error_code, error_detail);

    printf("%s\n", error_message);
    return 0;
}

実行結果:

エラーが発生しました。エラーコード:404、詳細:リソースが見つかりません。

int vsprintf(char *s, const char *format, va_list arg)

引数formatが指す書式文字列に従って、可変個数の実引数のリストを、sが指す配列へ書き込みます。
可変個数の実引数並びをargで置き換えたsprintf関数と同等です。
vsprintf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vsprintf関数はva_endマクロを呼び出しません。
領域の重なり合うオブジェクト間でコピーが行われるとき、その動作は未定義です。
成功したときは、配列に書き込まれた文字数が返されます。
ただし、NULL文字は文字数に含みません。
表現形式エラーが発生した場合、負の値が返されます。

使用例:

#include <stdio.h>
#include <stdarg.h>

#define MAX_ERROR_MESSAGE_SIZE 256

void generate_error_message(char* buffer, const char* format, ...)
{
    va_list args;
    va_start(args, format);

    vsprintf(buffer, format, args);

    va_end(args);
}

int main(void)
{
    char error_message[MAX_ERROR_MESSAGE_SIZE];

    int error_code = 404;
    const char* error_detail = "リソースが見つかりません。";

    generate_error_message(error_message, "エラーが発生しました。エラーコード:%d、詳細:%s", error_code, error_detail);

    printf("%s\n", error_message);
    return 0;
}

実行結果:

エラーが発生しました。エラーコード:404、詳細:リソースが見つかりません。

int vsscanf(const char * restrict s, const char * restrict format, va_list arg)

引数formatが指す書式文字列に従って、sが指す文字列を、可変個数の実引数のリストへ読み込みます。
可変個数の実引数並びをargで置き換えたsscanf関数と同等です。
vsscanf関数の呼び出し前に、va_startマクロでargを初期化する必要があります。
vsscanf関数はva_endマクロを呼び出しません。
変換が一つも行われないまま入力誤りが発生した場合、マクロEOFの値が返されます。
その他の場合、代入された入力項目の個数が返されます。
この個数は、入力中に照合誤りが発生すると、与えられた入力項目の個数より少なくなることもあり、0になることもあります。

使用例:

#include <stdio.h>
#include <stdarg.h>

void read_from_string(const char* str, const char* format, ...)
{
    va_list args;
    va_start(args, format);
    vsscanf(str, format, args);
    va_end(args);
}

int main(void)
{
    int myInt;
    float myFloat;
    const char *input = "123 4.56";
    read_from_string(input, "%d %f", &myInt, &myFloat);

    printf("読み込んだ値:int=%d、float=%f\n", myInt, myFloat);
    return 0;
}

実行結果:

読み込んだ値:int=123、float=4.560000
スポンサーリンク

文字入出力関数

int fgetc(FILE *stream)

引数streamが指す入力ストリームから1文字取り込み、その値が返されます。
その文字はunsigned char型として取り込まれ、そしてint型に変換され、ファイル位置表示子を進めます。
ファイル終了表示子がセットされている場合、またはファイルの終わりに達している場合、ファイル終了表示子がセットされ、EOFが返されます。
読み取りエラーが発生した場合、エラー表示子がセットされ、EOFが返されます。
その他の場合は、次の文字が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp = fopen("input.txt", "r");
    if(fp == NULL){
        printf("ファイルオープンに失敗しました。\n");
        return 1;
    }

    int ch;
    while((ch = fgetc(fp)) != EOF){
        putchar(ch);
    }

    fclose(fp);

    return 0;
}

このプログラムで使用するinput.txt:

Hello, world!
これは、テキストファイルのサンプルです。
複数行のテキストが含まれています。

実行結果:

Hello, world!
これは、テキストファイルのサンプルです。
複数行のテキストが含まれています。

char *fgets(char *s, int n, FILE *stream)

引数streamが指すストリームから、文字の列を読み取り、sが指す配列に格納します。
読み取る文字の列は改行またはファイルの終わりまでで、読み取る文字数の最大値はn-1です。
最後にNULL文字を付けます。
成功した場合は、sが返されます。
ファイルの終わりを検出し、かつ配列に1文字も読み取っていなかった場合、または読み取りエラーが発生した場合は、NULLポインタが返されます。

使用例:

#include <stdio.h>

#define BUFFER_SIZE 256

int main(void)
{
    FILE *fp = fopen("input.txt", "r");
    if(fp == NULL){
        printf("ファイルオープンに失敗しました。\n");
        return 1;
    }

    char buffer[BUFFER_SIZE];
    while(fgets(buffer, BUFFER_SIZE, fp) != NULL){
        printf("%s", buffer);
    }

    fclose(fp);

    return 0;
}

このプログラムで使用するinput.txt:

Hello, world!
これは、テキストファイルのサンプルです。
複数行のテキストが含まれています。

実行結果:

Hello, world!
これは、テキストファイルのサンプルです。
複数行のテキストが含まれています。

int fputc(int c, FILE *stream)

引数streamが指す出力ストリームにcで指定された文字を書き込みます。
その文字は、int型からunsigned char型に変換され、ファイル位置表示子を進めます。
成功したときは、書き込んだ文字が返されます。
書き込みエラーが発生した場合は、エラー表示子がセットされ、EOFが返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp = fopen("file.txt", "w");
    if(fp == NULL){
        printf("ファイルオープンに失敗しました。\n");
        return 1;
    }

    const char *text = "Hello, world!";
    while(*text != '\0'){
        fputc(*text++, fp);
    }

    fclose(fp);

    return 0;
}

実行結果:(file.txtへの出力結果)

Hello, world!

int fputs(const char *s, FILE *stream)

引数streamが指すストリームにsが指す文字列を書き込みます。
終端NULL文字の書き込みは行いません。
書き込みエラーが発生した場合は、EOFが返されます。
その他の場合は、非負の値が返されます。

使用例:

#include <stdio.h>

int main(void)
{
    FILE *fp = fopen("file.txt", "w");
    if(fp == NULL){
        printf("ファイルオープンに失敗しました。\n");
        return 1;
    }

    const char *lines[] = {
        "Hello, world!",
        "これは、テキストファイルのサンプルです。",
        "複数行のテキストが含まれています。"
    };
    
    int num_lines = sizeof(lines) / sizeof(lines[0]);

    for(int i=0; i<num_lines; i++){
        if((fputs(lines[i], fp)==EOF) || (fputc('\n', fp)==EOF)){
            printf("ファイルへの書き込みに失敗しました。\n");
            break;
        }
    }

    fclose(fp);

    return 0;
}

実行結果:(file.txtへの出力結果)

Hello, world!
これは、テキストファイルのサンプルです。
複数行のテキストが含まれています。

int getc(FILE *stream)

引数streamが指す入力ストリームから1文字取り込み、その値が返されます。
fgetc関数と同等です。
ファイルの終わりに達している場合、ファイル終