苦学楽学塾 ホームページ
最終更新日:2025年1月2日
C言語で多用される関数、printf(),fputs(),fgets(),malloc(),free(),exit()について説明します。まず、標準入出力、標準エラー出力について、説明しておきます。
C言語のファイル関係の関数で、頭文字が'f'である入出力関数では、fopen()関数が返す、ファイル・ポインタというものを使ってファイルの読み書きを行います。C言語では、キーボードからの入力を標準入力と言い、標準入力に対応するファイル・ポインタをstdinという変数(実際はマクロです)で表し、ファイルから読み込むのと同じイメージでキーボードから入力します。また、画面への出力もファイルへの出力と同様のイメージで扱い、これを標準出力と言い、標準出力に対応するファイル・ポインタをstdoutという変数で表します。また、エラー・メッセージなどを出力するための標準エラー出力(通常は画面に出力します)が用意されていて、対応するファイル・ポインタをstderrという変数で表します。stdin,stdout,stderrは、<stdio.h>で定義されています。
CYGWIN(元々LINUX,UNIXの機能ですが)には、リダイレクトという機能があり、標準入出力をファイルに切り替えることができます。標準入力、標準出力、標準エラー出力に対応するファイル・ディスクリプタ(open()という関数が返す値です)は、0,1,2に割り当てられており、実行ファイルの画面出力を、1> test.txtとする('1'と'>'との間に空白、TABを入れないでください)ことにより、test.txt(ファイル名は任意です)に切り替えることができます。例えば、"ls-l"コマンドの出力をファイルtest.txtに切り替えるのであれば、
ls -l 1> test.txt
とすれば、コマンドの出力は画面ではなく、test.txtに対して行われ、エディタなどで詳しくチェックすることができます。この1は省略可能で、
ls -l > test.txt
でもOKです。C言語プログラムのコンパイル・エラー出力が画面でダーっと流れて困るのであれば、標準エラー出力をリダイレクトして、
gcc -c test.c 2> test.log
とすれば('2'と'>'との間に空白、TABを入れないでください)、エラー出力がtest.logに入り、エディタでtest.logを開いてゆっくりとエラー・メッセージを確認することができます。
1.printf()
C言語で最もよく使われる、書式付きで画面に情報出力してくれる関数です。<stdio.h>をincludeしてください。
printf("Hello!\n");
とすると、画面に、
Hello!
と表示します。printf()の引数文字列末尾の'¥n'は、文字としては改行文字を示し、最後に改行せよ、という指示をしています。文字列変数str1の内容を表示するのであれば、
str1 = "abcde";
printf("文字列:%s\n", str1);
とすると、画面に、
文字列:abcde
と表示します。printf()の第1引数の文字列の中に'%s'が出てきますが、これは、第2引数str1の内容を文字列として%sの位置に表示せよ、という指示をしています。整数変数の内容を表示するのであれば、
int x1;
x1 = 7357891;
printf("x1:%d\n", x1);
とすると、画面に、
x1:7357891
と表示します。printf()の第1引数の文字列の中に'%d'が出てきますが、これは、第2引数の内容を整数データとして%dの位置に10進数として表示せよ、という指示をしています。第1引数の文字列の中に、この'%'による指定を複数個入れることができます。その順番に従って、表示を行う変数を、第2引数、第3引数、・・・という具合に並べます。1番目の'%'に対応するのが第2引数、2番目の'%'に対応するのが第3引数という具合になります。'%'の後に続く書式指定文字には、以下のようなものがあります。
%c 対応する変数はchar型で、文字として表示します。
%d 対応する変数はchar型,short型,int型で、符号付き整数として表示します。
%i 対応する変数はchar型,short型,int型で、符号付き整数として表示します。
%s 対応する変数はchar *型で、指定位置からnull文字までを文字列として表示します。対応する変数の値が0の場合は"(null)"と表示します。
%u 対応する変数はunsigned char型,unsigned short,unsigned int型で、符号なし整数として表示します。
%o 対応する変数は%d,%uと同じで、8進数整数で表示します。
%x 対応する変数は%d,%uと同じで、16進数整数として'a'~'f'を用いて表示します。
%X 対応する変数は%d,%uと同じで、16進数整数として'A'~'F'を用いて表示します。
%f 対応する変数はfloat型で、実数として表示します。
%e 対応する変数はfloat型,double型で、実数を仮数・指数を用いて表示します。
%ld 対応する変数はlong型で、符号付き整数して表示します。
%lu 対応する変数はunsigned long型で、符号なし整数として表示します。
%lx 対応する変数はlong型,unsigned long型,あるいは64bit CPUにおけるポインタで、16進数整数として'a'~'f'を用いて表示します。
%lX 対応する変数はlong型,unsigned long型,あるいは64bit CPUにおけるポインタで、16進数整数として'A'~'F'を用いて表示します。
%lf 対応する変数はdouble型で、実数として表示します。
'%'のすぐ後に指定するフラグには以下のようなものがあります。省略可能です。
- 左詰めで表示します。これがないときは右詰めの表示になります。
+ プラスの数の場合、'+'を付けます。これがないときはプラスの数でも'+'は付きません。
0 数値の表示の頭の方を0で埋めます。これがないと空白で埋められます。
# '%#x','%#X'とすると、16進表示の前に'0x','0X'を付けて表示します。'%#e','%#f'とすると、小数点が不要な場合でも小数点を付けます。
フラグの後ろに表示桁数が来ます。'%4d'とすると4桁で整数を表示します。'%5s'とすると文字列表示に5文字分の桁をとります。桁数指定が必要な桁数に不足する場合、または表示桁数の指定がないときは、必要な桁数をとって表示します。余る桁は、フラグ指定する場合を除き空白で埋められます。
小数点が付く表示の場合、表示桁数8桁、小数点以下3桁(小数第4位を四捨五入)で表示する場合には、'%8.3f'とします。表示桁数に不足する場合は、小数点以下の桁数を確保した上で、必要な桁数が取られます。余る桁は、フラグ指定する場合を除き空白で埋められます。文字列表示で小数点をつけて、'%.3s'とすると、文字列の最初の3文字を表示します。
実は、以上については、文字コードがshift-JISであることを前提に記述しています。文字コードをUTF-8にしておくと、思うように動かないかも知れません。printf()が期待通りの動作をしない場合、CYGWIN画面で右クリックし、出てきたメニューで[Options...],[Text]と選択し、Localeのところで、"ja-JP","SJIS (Japanese)"を選択してください。
2.fputs()
ファイルに文字列を出力する関数です。第1引数に文字列の先頭を指すポインタ、第2引数にファイル・ポインタをとります。<stdio.h>をincludeしてください。事前に、
FILE *fp1;
char buffer[256];
fp1 = fopen("test.txt", "w");
としておいて、256バイトのbufferを確保し、ファイルtest.txtを書き込みオープンしておき、bufferに出力データを書き込んで、
strcpy(buffer, "テスト・データです。\n");
ここでfputs()関数を呼び出し、
fputs(buffer, fp1);
fclose(fp1);
とすると、test.txtというファイルが生成され、test.txtの内容が、"テスト・データです。"になります。最後に'¥n'がついているので、ファイルの末尾に改行が入ります。fp1はファイル・ポインタと呼ばれ、ファイルに関する情報を保持している構造体を指すポインタになっています。
このファイル・ポインタを標準出力stdoutにすると、ファイルではなく、画面に出力するようになります。
fputs(buffer, stdout);
とすると、画面に、
テスト・データです。
と表示されます。stdoutに対するfputs()は、
strcpy(buffer, "テスト・データです。");
puts(buffer);
としても同様に画面に表示する結果が得られます。puts()関数は最後に改行してくれることに注意してください。
3.fgets()
ファイルから文字列を入力する関数です。第1引数に読み込む領域の先頭を指すポインタ、第2引数に読み込む文字数+1(文字列末尾の0を含めるためです。全角文字は、2文字分とることに注意してください),第3引数にファイル・ポインタをとります。<stdio.h>をincludeしてください。事前に、
FILE *fp1;
char buffer[256];
fp1 = fopen("test.txt", "r");
としておいて、256バイトのbufferを確保し、"テスト・データです。¥n"と書かれているファイルtest.txtを読み込みオープンしておき、fgets()関数を呼び出し、
fgets(buffer, 32, fp1);
fclose(fp1);
fputs(buffer, stdout);
とすると、bufferにtest.txtの内容が読み込まれ、画面に、
テスト・データです。
と表示されます。上記では、fgets()の第2引数を余裕を持たせて32としていますが、31文字以内の文字列であれば読み込むことができます。
ファイル・ポインタを標準入力stdinとすると、入力はキーボードからになります。
fputs("何か入力してください。", stdout);
fgets(buffer, 8, stdin);
puts(buffer);
とすると、入力された文字列が画面にオウム返しで表示されます。キーボードから何文字入力しても、7文字で打ち切られてしまうことに注意してください。ですが、7文字までは入力できてしまうので、bufferの大きさは8バイト以上でなければなりません。C言語には、gets()という、標準入力からメモリ領域に入力する関数がありますが、引数に指定するメモリ領域の大きさを上回る入力を行うと深刻な悪影響を生じます。gets()関数の代わりに、fgets(buffer, 8, stdin)とすれば、bufferの大きさを遥かに越えるようなデータを入力しても、先頭の7文字で打ち切ってしまうので、悪影響を生じません。
4.malloc()
引数(size_t型と定義されているのですが、int型でOKです)で指定されるサイズのメモリ領域を確保し、その先頭アドレス(void *型なので、代入する場合には、代入先の型にキャストします)を返す関数です。<malloc.h>をincludeしてください。莫大なメモリを要求した場合など、メモリ領域が確保できない場合、nullが返ります。そのメモリ領域を使い終わったら、free()関数を用いて解放することが原則です。1024バイトの文字列領域を確保する場合、char *stringとして、
string = (char *)malloc(1024);
とします。実際には、管理領域も含めて1024バイトを越えるメモリが消費されます。
5.free()
malloc()関数で確保したメモリ領域のアドレスを引数に設定しメモリ領域を解放します。<malloc.h>をincludeしてください。メモリ領域の解放だけなので簡単そうに見えますが、注意深く操作する必要があります。例えば、2次元配列のメモリ領域を、以下のようにmalloc()関数で確保し何らかのデータを入れ、free()関数で解放しようとすると、
matrix = (float **)malloc(sizeof(float *) * 5);
for (j1 = 0; j1 < 5; j1++) {
matrix[j1] = (float *)malloc(sizeof(float) * 5);
}
pf1 = matrix[2];
f1 = 0.1;
for (j1 = 0; j1 < 5; j1++) {
for(j2 = 0; j2 < 5; j2++) {
matrix[j1][j2] = f1;
f1 += 0.1;
}
}
free(matrix);
for (j1 = 0; j1 < 5; j1++) {
free(matrix[j1]);
}
動作させているシステムによっても異なると思いますが、Aborted(コアダンプ)と言われて強制停止してしまいます。上記では、matrix[0][0]~matrix[0][4]のメモリ領域のアドレスをmatrix[0]に確保するのですが、先にmatrixを解放してしまうと、matrix[0]に保持されているアドレスのメモリ領域を解放しようとするときには、既に、matrix[0]の内容は消失しており、障害を起こして強制停止してしまうのです。上記の例では、
for (j1 = 0; j1 < 5; j1++) {
free(matrix[j1]);
}
free(matrix);
として、まず、matrix[0]~matrix[4]に保持されているアドレスについてメモリの解放を行った後に、matrixを解放しなければなりません。
6.exit()
C言語のプログラムを強制停止させます。引数に終了ステータスを意味する整数値をとることができます。<stdlib.h>をincludeしてください。本ウェブサイトでは省略しますが、スクリプト言語(「シェルスクリプト」で検索してください)で、終了ステータスを受け取って、動作を変える、といったことができます。プログラムの最後、あるいはデバグ時に問題となる箇所の最後に入れておいて、そこで動作を止めてしまうのに使います。
【広告】 ここから広告です。ご覧の皆さまのご支援ご理解を賜りたく、よろしくお願いいたします。
【広告】 広告はここまでです。