C 言語でのファイルリダイレクトの使用
この記事では、C 言語でファイルリダイレクトを使用する方法をいくつか説明します。
標準入力をリダイレクトするために <
演算子を使用する
ファイルリダイレクトは一般的に UNIX ベースのシステムでは I/O
リダイレクトとして知られており、標準入力がどこから来るのか、標準出力がどこに行くのかを再定義することができます。演算子 <
は、標準入力がどこから来るかを変更するために使用されます。この方法は、ファイルの内容からユーザの入力を取り出してプログラムバッファに格納するのに便利です。この場合、改行文字が見つかるまでファイルの内容を読み込むために fgets
関数を利用します。改行文字が読み込まれると、それもまた与えられたバッファに格納され、その後に文字列終端のヌルバイトが格納されます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#define SIZE 1000
int main(int argc, char *argv[]) {
char buf[SIZE];
printf("Write input text: ");
fgets(buf, SIZE, stdin);
printf("%s\n", buf);
exit(EXIT_SUCCESS);
}
サンプルコマンド:
./program < input.txt
出力:
The first line from the input.txt file
先ほどのサンプルコードでは、ハードコードされた値を持つバッファを割り当てました。しかし、ユーザから提供された入力ファイルを格納するためには、より多くのメモリが必要となる場合があり、シナリオに合わせて適応的な方法を実装する必要があります。そのためには、malloc
を用いて動的メモリを確保し、ファイルの 1 行目を格納するのに必要な最大数としてファイルサイズの合計を渡す。この方法では、与えられたファイルが大きすぎて、最初の行が短い場合、メモリを浪費しすぎてしまう可能性があります。しかし、malloc
が失敗せず、システムメモリが枯渇しない限り、コードが最も長い行を読み込めることは保証されています。
注意してほしいのは、stat
システムコールを使ってファイルサイズを取得していますが、これには入力ファイルのパス名が必要で、コマンドライン引数として明示的に指定しないと取得できないということです。しかし、fgets
が初期化されていないメモリ領域に書き込もうとしたり、プログラムが失敗して終了したりしないようにするためには、すべての関数呼び出しが正常に戻るかどうかをチェックする必要があることに注意してください。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
char *buffer = NULL;
const char *filename = NULL;
struct stat sb;
if (argc != 2) {
printf("Usage: ./program filename < filename\n");
exit(EXIT_FAILURE);
}
filename = argv[1];
if (stat(filename, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
buffer = malloc(sb.st_size);
if (!buffer) {
perror("malloc");
exit(EXIT_FAILURE);
}
printf("Write input text: ");
if (fgets(buffer, sb.st_size, stdin) == NULL) {
perror("fgets");
exit(EXIT_FAILURE);
}
printf("%s\n", buffer);
exit(EXIT_SUCCESS);
}
サンプルコマンド:
./program input.txt < input.txt
出力:
The first line from the input.txt file