#stdio.h

stdio.h は C 言語の標準 I/O ライブラリで、ファイルの読み書きに使用されるほか、コンソールの入出力にも使用されます。

標準入出力関数

コンソールの入出力には以下の関数が使用されます。

  • printf(): コンソールへの出力。詳細については、「基本構文」の章を参照してください。
  • scanf(): コンソールから入力を読み取ります。詳細については、「I/O 関数」の章を参照してください。
  • getchar(): コンソールから文字を読み取ります。詳細については、「I/O 関数」の章を参照してください。
  • putchar(): コンソールに文字を書き込みます。詳細については、「I/O 関数」の章を参照してください。 -gets(): コンソールから入力行全体を読み取ります (廃止)。詳細については、「I/O 関数」の章を参照してください。
  • Puts(): コンソールに文字列を書き込みます。詳細については、「I/O 関数」の章を参照してください。

ファイル操作関数

ファイル操作には次の関数が使用されます。詳細については、「ファイル操作」の章を参照してください。

  • fopen(): ファイルを開きます。
  • fclose(): ファイルを閉じます。
  • freopen(): 新しいファイルを開き、すでに開いているファイル ポインタを関連付けます。
  • fprintf(): ファイルに出力します。
  • fscanf(): ファイルからデータを読み取ります。
  • getc(): ファイルから文字を読み取ります。
  • fgetc(): ファイルから文字を読み取ります。
  • putc(): ファイルに文字を書き込みます。
  • fputc(): ファイルに文字を書き込みます。
  • fgets(): ファイルから行全体を読み取ります。
  • fputs(): 文字列をファイルに書き込みます。
  • fread(): ファイルからバイナリ データを読み取ります。
  • fwrite(): バイナリ データをファイルに書き込みます。
  • fseek(): ファイルの内部ポインタを指定された場所に移動します。
  • ftell(): ファイルの内部ポインタの現在位置を取得します。
  • rewind(): ファイル内部ポインタをファイルの先頭にリセットします。
  • fgetpos(): ファイルの内部ポインタの現在位置を取得します。
  • fsetpos(): ファイルの内部ポインタの現在位置を設定します。
  • feof(): ファイルの内部ポインタがファイルの終わりを指しているかどうかを判断します。
  • ferror(): ファイル エラー インジケーターのステータスを返します。
  • clearerr(): ファイル エラー インジケーターをリセットします。 -remove(): ファイルを削除します。
  • rename(): ファイルの名前を変更し、ファイルを移動します。

文字列操作関数

次の関数は文字列の操作に使用されます。詳細については、「文字列の操作」の章を参照してください。

  • sscanf(): 文字列からデータを読み取ります。詳細については、「I/O 関数」の章を参照してください。
  • sprintf(): 文字列に出力します。
  • snprintf(): 出力文字列の数を指定して、文字列に出力するより安全なバージョン。

##tmpfile()

tmpfile() 関数は、手動で閉じない限り、プログラムの実行中にのみ存在する一時ファイルを作成します。そのプロトタイプは次のとおりです。

ファイル* tmpfile(void);

tmpfile() は、この関数によって作成された一時ファイルにアクセスするために使用できるファイル ポインタを返します。作成に失敗した場合は、ヌルポインタ NULL が返されます。

ファイル* tempptr;
tempptr = tmpfile();

close() メソッドを呼び出して一時ファイルを閉じた後、ファイルは自動的に削除されます。

tmpfile() には 2 つの欠点があります。 1 つは一時ファイルのファイル名が分からないこと、もう 1 つはファイルを永続化できないことです。

tmpnam()

tmpname() 関数は、一時ファイルが他のファイルと同じ名前にならないように、一時ファイルの名前を生成します。そのプロトタイプは次のとおりです。

char* tmpname(char* s);

そのパラメータは文字列変数です。tmpnam() は一時ファイルのファイル名をこの変数にコピーし、文字列変数へのポインタを返します。ファイル名の生成に失敗した場合、tmpnam() はヌルポインタ NULL を返します。

文字ファイル名[L_tmpnam];

if (tmpnam(ファイル名) != NULL)
  // /tmp/filew9PMuZ などのファイル名を出力します
  printf("%s\n", ファイル名);
それ以外
  printf("何かが間違っています!\n");

上記の例では、「L_tmpnam」は「stdio.h」内に定義されているマクロで、一時ファイルのファイル名の長さを指定します。

tmpname() のパラメータはヌルポインタ NULL にすることもでき、これはファイル名文字列へのポインタも返します。

char* ファイル名;
ファイル名 = tmpnam(NULL);

上記の例では、変数 filenametmpnam() によって生成されたファイル名です。

この関数は、後で fopen() を使用して開いて使用できるファイル名を生成するだけです。

fflush()

ffflush() はバッファ領域をクリアするために使用されます。ファイル ポインタをパラメータとして受け取り、バッファ領域の内容をファイルに書き込みます。

fflush(fp);

バッファの内容を保存する必要がない場合は、ヌル ポインタ NULL を渡すことができます。

fflush(NULL);

クリアが成功した場合、fflush() は 0 を返し、それ以外の場合は EOF を返します。

ffflush() は通常、出力バッファをクリアするためにのみ使用されることに注意してください (ファイルへの書き込みなど)。入力バッファをクリアするためにこれを使用した場合 (ファイルの読み取りなど)、それは未定義の動作になります。

fflush() の使用法の 1 つは、Enter キーを待たずにバッファに出力を強制することです。ほとんどのシステムはライン キャッシュです。つまり、Enter キーが入力されるまで (またはバッファがいっぱいになるか、ファイルが最後まで読み取られるまで) fflush() が待機できないまで、バッファの内容は出力されません。 Enter キーを押すとすぐに出力されます。

for (int i = 9; i >= 0; i--) {
  printf("\r%d", i);
  fflush(標準出力);
  スリープ(1);
}

上の例はカウントダウン効果で、「\r」は Enter キーです。これは、各サイクルが現在の行の先頭に戻ることを意味します。これは、前のサイクルの出力を削除するのと同じです。 fflush(stdout) は、キャッシュを直ちにディスプレイに出力することを意味します。この行は必須です。そうでない場合、前の行の出力には Enter キーがないため、キャッシュ出力はトリガーされず、何も表示されません。プログラムが終了して再度出力されるまで待機します。

setvbuf()

setvbuf() 関数は、特定のバイト ストリームをキャッシュする方法を定義するために使用されます。 4 つのパラメータを受け入れることができます。

int setvbuf(FILE* ストリーム、char* バッファ、int モード、size_t サイズ)

最初のパラメータ stream はファイル ストリームです。

2 番目のパラメータ buffer はバッファ領域のアドレスです。

3 番目のパラメータ mode は、stdio.h で定義されている次の 3 つのマクロのいずれかを指定します。

  • _IOFBF: バッファーがいっぱいです。キャッシュが空の場合はストリームからデータが読み取られ、キャッシュがいっぱいの場合はデータがストリームに書き込まれます。通常、これがデフォルト設定です。
  • _IOLBF: ラインキャッシュ。データ行がストリームから読み取られるか、データ行がストリームに書き込まれるたびに、キャッシュは行単位で読み書きされます。
  • _IONBF: キャッシュなし。バッファは使用されず、デバイスは直接読み書きされます。

4 番目のパラメータ size はバッファ領域のサイズを指定します。キャッシュが大きいほどパフォーマンスが向上し、キャッシュが小さいほどスペースが節約されます。 stdio.h は、システムのデフォルトのバッファ サイズを表すマクロ BUFSIZ を提供します。

その重要性は、fopen() 関数がファイルを開くときに設定されたデフォルトのバッファを使用するのではなく、ファイルを開く前にユーザーが独自のファイル バッファを定義できることです。

文字バッファ[N];

setvbuf(ストリーム、バッファ、_IOFBF、N);

上記の例では、ファイルストリームstreamのバッファ領域をアドレスbufferから開始し、サイズをN、モードを_IOFBFに設定しています。

setvbuf() の 2 番目のパラメータにはヌル ポインタ NULL を指定できます。この場合、 setvbuf() 自体がバッファ領域を作成します。

ファイルストリームに対して操作を実行する前に、setvbuf() を呼び出す必要があることに注意してください。

呼び出しが成功した場合、setvbuf() の戻り値は 0 になり、それ以外の場合は 0 以外の値を返します。

次の例では、キャッシュ領域を行キャッシュに調整します。

ファイル*fp;
char lineBuf[1024];

fp = fopen("somefile.txt", "r");
setvbuf(fp, lineBuf, _IOLBF, 1024);

setbuf()

setbuf()setvbuf() の初期バージョンであり、後者の簡易版とみなすことができます。また、特定のバイト ストリームのバッファ領域を定義するために使用されます。

void setbuf(FILE* ストリーム, char* バッファ);

最初のパラメータ stream はファイル ストリーム、2 番目のパラメータ buffer はバッファ領域のアドレスです。

これはいつでも setvbuf() として書き換えることができます。

文字バッファ[BUFSIZ];

setbuf(ストリーム、バッファ);

// と同等
setvbuf(ストリーム、バッファ、_IOFBF、BUFSIZ);

上の例では、BUFSIZstdio.h で定義されたマクロであり、システムのデフォルトのバッファ サイズを表します。

setbuf() 関数には戻り値がありません。

setbuf() の 2 番目のパラメータが NULL に設定されている場合、それはキャッシュがないことを意味します。

setbuf(stdout, NULL);

// と同等
setvbuf(stdout, NULL, _IONBF, 0);

ungetc()

ungetc() は、キャッシュから読み取られた最後の文字をキャッシュに戻し、次のキャッシュ読み取り操作はこの文字から開始されます。一部の操作では、次の文字が何であるかを知り、それをどのように処理するかを決定する必要があります。この場合、この関数は非常に役立ちます。

そのプロトタイプは次のとおりです。

int ungetc(int c, FILE *stream);

最初のパラメータは文字変数で、2 番目のパラメータは開いているファイル ストリームです。戻り値は、キャッシュに戻された文字です。操作が失敗した場合は、EOF が返されます。

int ch = fgetc(fp);

if (isdigital(ch)) {
  ch = fgetc(fp);
}

ungetc(ch, fp);

上の例では、読み取られた文字が数字でない場合、その文字はキャッシュに戻されます。

##エラー()

perror() は、標準エラー出力のエラー メッセージの前にカスタム文字列を追加するために使用されます。

void perror(const char *s);

この関数のパラメータは、エラー メッセージの前に追加された文字列です。戻り値はありません。

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

int main(void) {
  int x = -1;

  エラー番号 = 0;
  float y = sqrt(x);
  if (errno != 0) {
    perror("sqrt エラー");
    終了(EXIT_FAILURE);
  }
}

上の例では、「-1」の平方根を求めるとエラーが発生します。ヘッダー ファイル errno.h はマクロ errno を提供します。このマクロは、前のステップでエラーが発生するたびにゼロ以外の値に設定されます。 perror() は、エラー メッセージの前に sqrt error のカスタム文字列を追加するために使用されます。

上記のプログラムを実行すると、次のエラー メッセージが表示されます。

$ gcc test.c -lm
$ ./a.out
sqrt エラー: 数値引数が定義域外です

可変パラメータ操作関数

(1) 出力機能

以下は printf() のバリアント関数で、関数の可変パラメータリスト (va_list) を指定された形式で出力するために使用されます。

  • vprintf(): 指定された形式に従ってコンソールに出力します。デフォルトはモニターです。
  • vfprintf(): 指定された形式に従ってファイルに出力します。
  • vsprintf(): 指定された形式に従って文字列に出力します。
  • vsnprintf(): 指定された形式に従って安全なバージョンの文字列に出力します。

これらのプロトタイプは次のとおりです。これらは、最後のパラメータが可変パラメータ オブジェクトであることを除いて、対応する printf() 一連の関数と基本的に同じです。

#include <stdio.h>
#include <stdarg.h>
    
int vprintf(
  const char * 形式を制限します。
  va_list 引数
);

int vfprintf(
  FILE * ストリームを制限、
  const char * 形式を制限します。
  va_list 引数
);
    
int vsprintf(
  char * を制限し、
  const char * 形式を制限します。
  va_list 引数
);
    
int vsnprintf(
  char * を制限し、
  サイズ_t n、
  const char * 形式を制限します。
  va_list 引数
);

戻り値は出力された文字数です。エラーが発生した場合は負の値が返されます。

vsprintf()vsnprintf() の最初のパラメータを NULL にすると、書き込まれる文字数を確認できます。

以下に例を示します。

int logger(char *format, ...) {
  va_list va;
  va_start(va, フォーマット);
  int 結果 = vprintf(format, va);
  va_end(va);

  printf("\n");

  結果を返します。
}

// 出力 x = 12 および y = 3.20
logger("x = %d および y = %.2f", x, y);

(2) 入力機能

以下は scanf() のバリアント関数で、指定された形式で可変引数リスト (va_list) を入力するために使用されます。

  • vscanf(): 指定された形式に従ってコンソール (デフォルトはキーボード) から読み取ります。
  • vfscanf(): 指定された形式に従ってファイルから読み取ります。
  • vsscanf(): 指定された形式に従って文字列から読み取ります。

それらのプロトタイプは次のとおりで、最後のパラメーターが可変パラメーター オブジェクトであることを除いて、対応する scanf() 関数と基本的に同じです。

#include <stdio.h>
#include <stdarg.h>
    
int vscanf(
  const char * 形式を制限します。
  va_list 引数
);
    
int vfscanf(
  FILE * ストリームを制限、
  const char * 形式を制限します。
  va_list 引数
);
    
int vsscanf(
  const char * を制限し、
  const char * 形式を制限します。
  va_list 引数
);

正常に読み取られたアイテムの数を返します。ファイルの終わりまたはエラーが発生した場合は EOF を返します。

以下に例を示します。

int error_check_scanf(int Expected_count, char *format, ...) {
  va_list va;

  va_start(va, フォーマット);
  int カウント = vscanf(format, va);
  va_end(va);

  アサート(カウント == 期待カウント);

  戻り数;
}

error_check_scanf(3, "%d, %d/%f", &a, &b, &c);

作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0