このドキュメントは http://icrus.org/c_language_beginers_course/ 上にあります.
プログラムが少しずつ高度になってくると,必ずといって良いほどif~else文の入れや,goto文,複雑な論理演算子の組み合わせが登場してきます.ここではやや複雑なプログラム例を見て,それらについて説明します.
01: #include <stdio.h>
02: #include <stdlib.h>
03: #include <process.h>
04: #include <ctype.h>
05: #define FILENAME "a:\\tmp.c"
06:
07: void main(void){
08: FILE *fp;
09: int c, chk;
10:
11: if( (fp=fopen( FILENAME, "rt" ))==NULL ){
12: printf( "file open error:%s\n", FILENAME );
13: exit(1);
14: }
15:
16: chk = 1;
17: while( (c=fgetc(fp))!=EOF ){
18: if( c=='\'' ){
19: if( chk==0 )
20: putchar( ' ' );
21: chk = 1;
22: do{
23: c = fgetc( fp );
24: if( c=='\\' ){
25: c = fgetc( fp );
26: if( c=='\'' )
27: c = fgetc( fp );
28: }
29: if( c==EOF )
30: goto file_end;
31: }while( c!='\'' );
32: }else if( c=='\"' ){
33: if( chk==0 )
34: putchar( ' ' );
35: chk = 1;
36: do{
37: c = fgetc( fp );
38: if( c=='\\' ){
39: c = fgetc( fp );
40: if( c=='\"' )
41: c = fgetc( fp );
42: }
43: if( c==EOF )
44: goto file_end;
45: }while( c!='\"' );
46: }else if( isalpha(c) || isdigit(c) || c=='_' || c=='.' ){
47: chk = 0;
48: putchar( c );
49: }else{
50: if( chk==0 ){
51: putchar( ' ' );
52: }
53: chk = 1;
54: }
55: }
56:
57: file_end:
58: if( fclose( fp )==EOF ){
59: printf( "file close error:%s\n", FILENAME );
60: exit(1);
61: }
62: putchar( '\n' );
63: putchar( '\n' );
64: getch();
65: }
04行目 → 関数isalpha()などを使うために必要なインクルードファイルです.
05行目 → 入力するファイル名をマクロ定義してください.
17~56行 → ファイルの終わりまで,1文字づつ読み込むwhileループです.whileブロックの中は4ブロックからなるif~else文の入れ子になっています.
30,44行 → 条件が成立(関数fgetc()の戻り値がEOF)したとき,57行目のラベルfile_end:以降に制御が飛びます.
22~31行 → do~while文です.ブロックの最後に判定を行って,真ならdoブロックの先頭に戻ります.
46行目 → 関数isalpha(c)は,変数cがアルファベットの真.関数isdigit(c)は変数cが数字のとき真.これらの関数を使うために4行目のインクルードファイルctype.hが必要です.
コンパイル・実行すると次のよう表示されます.
include stdio.h include stdlib.h include
process.h include ctype.h define FILENAME void main void FILE
fp int c chk if fp fopen FILENAME NULL printf FILENAME exit 1
chk 1 while c fgetc fp EOF if c if chk 0 putchar chk 1 do c fgetc
fp if c c fgetc fp if c c fgetc fp if c EOF goto file_end while
c else if c if chk 0 putchar chk 1 do c fgetc fp if c c fgetc
fp if c c fgetc fp if c EOF goto file_end while c else if isalpha
c isdigit c c c chk 0 putchar c else if chk 0 putchar chk 1 file_end
if fclose fp EOF printf FILENAME exit 1 putchar putchar getch
リターンキーを押すとプログラムは終了します.
プログラム例17-1のソースファイルを入力として,識別子と数値を現れる順に出力しています.1対の"",1対の''で囲まれた文字列は出力しません.
このプログラムは,①17~31行,②32~45行,③46~48行,④49~54行の4つのブロックからなるif~else文の入れ子になっています.基本的なif~else文の入れ子は次のようなものです.いくつでも連ねることができます.
if(条件式1){
文1;
:
}else if(条件式2){
文2;
:
}else if(条件式3){
文3;
:
}else{
文4;
:
}
制御は次のようになります.
(1)条件式1が真のとき文1を実行.残りの文2~4はスッキップして実行しない.
(2)条件式1が偽のとき条件式2を評価して真のとき文2を実行する.残り文3~4実行しない.
(3)条件式2が偽のとき条件式3を評価して真のとき文3を実行する.文4は実行しない.
(4)最後に条件式1~3が偽のときは文4を実行する.
プログラム例17-1では,次の処理をしています.
①文字「'」の処理
②文字「"」の処理
③アルファベット,数字,文字「_」,文字「.」の処理
④その他の文字の処理
①ブロックでは,chk==0のときあったとき,区切りの空白文字を出力します.文字「'」を読み込むまでファイルを空読みします.変数chkに1を代入します.
②ブロックでは,chk==0のときあったとき,区切りの空白文字を出力します.文字「"」を読み込むまでファイルを空読みします.変数chkに1を代入します.
③ブロックでは,変数chkに0を代入します.変数cを出力します.
④ブロックでは,chk==0のときあったとき,区切りの空白文字を出力します.変数chkに1を代入します.
その他,①②ブロックでは,「'\''」(文字「'」)や「"\""」(文字列の中の文字「"」)にも対応するようになっています.
30行目から57行目へ,44行目から57行目へgoto文があります.基本的にはgoto文は次のようになります.条件文などと組み合わせて,強制的にラベル:以降の文へ制御を移します.C言語には,多くの優れた制御構造がありますので,goto文はエラー処理など,2重ループを抜けるときだけに使用すべきです.むやみに使用するとわかりにくいプログラムになってしまいます.
goto ラベル;
:
ラベル:
文;
46行目を見て下さい.
条件式( isalpha(c) || isdigit(c) || c=='_'
|| c=='.' )
条件式のあいだに演算子「||」があります.これは論理和「or」の意味で使われます.この条件式は「関数isalpha(c)が真,またはisdigit(c)が真,またはc=='_'が真,またはc=='.'が真」のとき真となります.論理演算子についてまとめるとつぎのようになります.
演算子 働き 意味
if(条件式1){
文1;
:
}else if(条件式2){
文2;
:
}else if(条件式3){
文3;
:
}else{
文4;
:
}
(1)制御は次のようになります.
①条件式1が真のとき文1を実行.残りの文2~4はスッキップして実行しない.
②条件式1が偽のとき条件式2を評価して真のとき文2を実行する.残り文3~4実行しない.
③条件式2が偽のとき条件式3を評価して真のとき文3を実行する.文4は実行しない.
④最後に条件式1~3が偽のときは文4を実行する.
(2)ブロックをいくつ連ねても構いません.
goto ラベル;
:
ラベル:
文;
①条件文などと組み合わせて,強制的にラベル:以降の文へ制御を移します.
②C言語には,多くの優れた制御構造がありますので,goto文はエラー処理など,2重ループを抜けるときだけに使用すべきです.むやみに使用するとわかりにくいプログラムになってしまいます.
演算子 働き 意味
優先順位
このドキュメントは http://icrus.org/c_language_beginers_course/ 上にあります.
2017,1 ssatoh@ 足立工科大学 工学部 情報通信工学科