標準入出力
標準ストリームを指定する
より厳密に、ファイルの入出力を管理してみましょう
今回は、標準入出力というファイルとは切っても切れない大切な内容を説明します
じつは、私たちは無意識のうちに標準入出力を使ってきました
たとえば、標準出力とは文字列などの出力先を言います
メモリに格納した文字列なども一種の「ファイル」として考えることができます
次の章でやりますが、これをディスクに保存することもできますし、画面に出力することもできます
この画面、すなわちディスプレイが標準出力になります
逆に、キーボードからの入力が標準入力となります
しかし、これは必ずしもそうであるとは限りません
たとえば、MS-DOS上で標準出力をテキストファイルに出力するようにかえることができます(リダイレクトといいます)
FILE構造体で、これらの標準入出力ストリームが定義されています
- FILE *stdin : 標準入力
- FILE *stdout : 標準出力
- FILE *stderr : 標準エラー出力
たとえば、fputc()関数などでこれを利用することができます
int fputc(int 書き込む文字 , FILE *ストリーム);
fputc()関数は、ストリームに対して指定文字を書き込みます
つまり、このストリームを標準出力にすることによって画面に出力できるというわけです
#include <stdio.h>
#include <stdlib.h>
int main() {
char fileName[124];
int getf;
FILE *fp;
printf("ファイル名を入力してください>");
scanf("%s" , fileName);
fp = fopen(fileName , "r");
if (fp == NULL) {
printf("ファイルが開けませんでした");
exit (1);
}
while(1) {
getf = fgetc(fp);
if(!feof(fp)) fputc(getf , stdout);
else break;
}
fclose(fp);
return 0;
}
fputc(getf , stdout); という文に注目してください
これは、getfをstdoutに、つまり標準出力に書き込んでいるのです
getfはint型ですが、この関数は第一引数のintをunsigned charにキャストして出力します
これだけでは、標準入出力についてハッキリしないと思うので
この場でハッキリさせたいと思います
次のプログラムを見てください
#include <stdio.h>
int main() {
char str[] = "Kitty on your lap";
int count ;
for (count = 0 ; str[count] != 0 ; count++) {
fputc(str[count] , stdout);
}
return 0;
}
普通に実行すれば、Kitty on your lap と画面に表示されて終了します
しかし、このファイル名が test.c としてコマンドプロンプトで次のように入力してください
test > a.txt
今度はなにも画面に文字が出ないでプログラムが終了してしまいます
しかも、実行ファイル test と同じディレクトリに a.txt というファイルが生成されているはずです
a.txtファイルを開いてみると、予想どうりそのファイルに Kitty on your lap と書き込まれています
なぜかというと標準出力が変わったためです
このように、OS側で標準出力を変更することができることを知ってください
では、アプリケーションで重大なエラーが起きたことをユーザーに知らせたいとします
しかし、ユーザーは作業の簡易化のために標準出力をリダイレクトしていたらエラー報告ができないのです
そこで用意されているのが標準エラー出力です
これを使用することで、エラーが発生した時に標準出力以外を使うことができます
#include <stdio.h>
int main() {
char str[] = "Kitty on your lap\n";
char er[] = "エラーです : 猫耳を愛しましょう";
int count ;
for (count = 0 ; str[count] != 0 ; count++) {
fputc(str[count] , stdout);
}
for (count = 0 ; er[count] != 0 ; count++){
fputc(er[count] , stderr);
}
return 0;
}
普通に実行すると、標準出力、標準エラー出力の両方ともディスプレイに出力されます
しかし、リダイレクトすると標準エラー出力だけがディスプレイに出力されるはずです
fputc()関数のような、FILE構造体の書き込み先を指定する関数などでは、このような方法も有効です
fputc()関数に対してfputs()関数も存在します
int fputs( const char *文字列, FILE *ストリーム );
fputc()関数と違うのは、文字ではなく文字列を指定できることです
やはり、関連付けられているストリームに文字列を書き込みます
エラーが生じるとEOFを返し、成功した場合は正数を返します
文字列の末尾にあるヌル文字は書き込まれないという特徴があります
#include <stdio.h>
int main() {
char str[] = "Kitty on your lap";
fputs(str , stdout);
return 0;
}
なんだか、ファイルに関係のない事をやっているような気がしますが
これらは全てファイル操作に使われる関数です
このことを覚えておけば、すぐに実用できるのでもう少しだけ我慢してください
fputs()関数があるということはfgets()関数もあります
char *fgets(char *文字列 , int サイズ , FILE ストリーム);
文字列は、読み込んだ文字列を保存するための文字列バッファのポインタ
サイズは読み出す長さを、文字列で指定したバッファのサイズ以下で指定します
ストリームは、読み出すストリームを指定します
戻り値は、成功した時は読み込んだ文字列へのポインタが、エラーかファイルの終了に達した時はNULLを返します
この関数も、通常はファイルを対象に使用されますが
今回は標準入力を使用します。標準入力はデフォルトでキーボードです
#include <stdio.h>
int main() {
char str[256];
printf("入力してください>");
fgets(str , 256 , stdin);
fputs(str , stdout);
return 0;
}
こうしてみると、コンソール入出力とファイル操作関数はほとんど同じことができてしまいますね
じっさいにそのとおりで、このようにファイル入出力関数をコンソールに使用することができるのです
相手がファイルかコンソールかの違いだけなのです
注意してほしいのが、stdin , stdout , stderr は内容の変更ができません
これらのポインタは定数のため、新しい値を代入することはできないのです
int fputc( int c, FILE *stream );
ストリームに書き込みます
ヘッダ - stdio.h
c - 書き込む文字を指定します
stream - 書き込むFILE構造体へのポインタを指定します
戻り値 - エラーが発生すると EOF を返します。それ以外は書き込んだ文字を返します
int fputs( const char *string, FILE *stream );
文字列をストリームに書き込みます
ヘッダ - stdio.h
string - 出力する文字列のポインタを指定します
strean - 書き込むFILE構造体のポインタを指定します
戻り値 - 成功すると、負でない値を返します。エラーが発生すると EOF を返します
char *fgets( char *string, int n, FILE *stream );
ストリームから文字列を読み込みます
ヘッダ - stdio.h
string - 読み込んだ文字列を保存する文字列のポインタを指定します
n - 読み出す最大文字数
stream - 読み込むFILE構造体のポインタを指定します
戻り値 - 成功するとstringを返し、エラーが発生するか、ファイルの終端に達すると NULL を返します