|
|
5. ループ文
ループ文は繰り返し文とも呼ばれます。C言語では while 文 do-while 文 および for 文の3種類のループ文があります。今回はその3つを紹介したいと思います。
while 文
早速、実際のコードで見ていきます。
while.c
このコーナーでは、すべてのソースファイルはあなたのホームフォルダの「learn-c」フォルダに保存することにしています。ターミナルを起動するとまずあなたのホームフォルダからはじまります。コマントラインで
cd learn-c
と入力して learn-c フォルダに移動します。
gcc while.c -o while
と入力して while という名前の実行ファイルを作成します
./while
と入力してプログラム while を実行しください。まず最初に、
[ 使い方: 加算=数字 終了=Q ]
と表示されます。数字を足していきたい時は数字を、このプログラムを終了したいときには q もしくは Q を入力して色々と試してください。
コード説明
1行目〜4行目は複数行コメントを利用してファイル名とクレジット名を書いています。
6行目・7行目はそれぞれの関数のためのヘッダファイルを読み込んでいます。fgets( )関数は今回はじめて出てきました。詳しくは後ほど説明いたします。
10行目で合計が加算されていく整数型 int の変数 sum を宣言して同時に 0 で初期化しています
11行目で文字列を格納するための文字型 char の配列をを宣言しています。C言語では文字列はこのように文字型charの配列として表すことになっています。配列については第4回で簡単に説明しましたが、次回の第6回「データ型」で再度説明する予定にしています。
12行目でこのプログラムの簡単な使い方を画面に表示しています。加算する場合には数字を、終了する場合にはqかQを入力します。
13行目が while 文です。while ( 条件式 ) の条件式が true の間は { から } のブロック文で囲まれた実行式を繰り返し実行します。最後の } に出会うとまた最初の条件式に戻って条件が true かどうかを確認します、 true ならまたブロック分を実行します。ここで使われている条件式( 1 )は常にtrueと評価されます。ぷろぐらみんぐで無限ループを作る常套手段の1つとなっています。
14行目 fgets ( ss, 100, sdtin ); は stdin(標準入力先、すなわちキーボードから)変数 ss に100文字以内の文字を読み込むという関数です。詳しいことは後述します。
15行目 配列変数 ss の最初の項目(最初が0番目になります)が文字 q か Q かを確かめています。 || という記号は 条件1 ||(あるいは) 条件2 が true(真)ならという意味になります。もし入力された文字の1文字目が q か Q なら「お疲れ様でした」と表示して 17行目の break; 式を実行します。break は現在のループ文を強制的に抜け出すという意味になります。while 文を抜け出した制御は main( )関数の return 文に出会うか最後の } に出会ってプログラムは終了します。もし文字列の最初が q や Q でなければ 19行目が実行されて atoi( )関数を使って文字列ssを整数に変換して合計sumにその数値を加算します。そして20行目で加算された合計の数値をターミナルに表示しています。
このようにして while( )関数を使って終了を表す q か Q が入力するまでこのプログラムは終了いたしません。多くのプログラムでこれと同様の手段を使ってユーザーが望むまでプログラムが終了しないようにしています。
練習問題
上記のサンプルプログラムを c もしくは C を入力すると合計sumがクリアされて0に戻るプログラムを作ってみましょう。
fgets( )関数
char *fgets (char *ss, int n, FILE *stream);
第一引数のchar *ssはssという文字配列のアドレス(ポインター)を表しています。第2引数の整数値で変数ssに読み込める最大の文字数を表しています。第3引数ではどこから文字列を読み込むのかを指定しています。そして戻り値として文字列を格納したss変数のアドレス(ポインター)を返しています。このサンプルコードでの実際の使われ方はコード説明の14行目のところで説明しています。なおこのように文字列は通常ポインターとして扱われます。ポインターについては第3回変数の最後で簡単な説明をしています。
なおC言語にはコンソール(ターミナル)やファイルから文字列を読む込むための多くの関数が用意されています。しかし色々な使い勝手を考えてこの learn C では fgets を使っていくことにしました。C言語における文字の扱いについて説明をすると多数のページが必要になってきます。この learn C はあくまでも Objective-C言語へのステップアップのために必要になる基本的な C言語のみの説明に終始するつもりです。
do - while 文
前項の while.c では while( 1 ) で無理にループ文がはじまるようにしました。しかし条件がどうであれ取りあえず1度はループ文を実行してもらいたい場合があります。前項の while.c も実はこのタイプだと考えられます。そのような場合のために do - while 文というループ文が用意されています。
do-while.c
コード説明
12行目までは先ほどの while.c と同じです。13行目の do 文で、21行目の while まで必ず1度は実行されることになります。15行目の if 文もさきほどの while.c の場合と同じですが break 文はなくなっています。このループを続けるか終了させるかは21行目の while ( 条件式 )に任せているからです。17行目では else 文を使うことによって if 文の条件に合わなかった場合にのみ合計 sum に入力された数値が加算されてるようにしています。while.c の場合には 15行目の if 文の条件式に合った場合には break 文で強制的にループを抜け出していましたが、今回はループの最後まで実行されます。文字ではじまる文字列は atoi( )関数によって0と評価されます。もしここで else を記述していなければ18行目が実行されて sum に0が加算され「合計は○○です.」と表示されてしまいます。
21行目でこのループ do-while を続けるかどうかの判定をしています。while ( 条件式 ); のなかで Not演算子の != を使って入力された文字が q か Q でない場合 に条件式が true となりループが再び始まるように指定しています。また21行目では否定の != だけでなく論理演算子の論理積の && も使っています。前項の while.c では論理和と呼ばれる || を使っていましたが、&& は AでもありBでもある場合にのみ true になります。それに対して || では Aの場合かBの場合に true になります。今回は Not演算子を使っているので || では q ではないが Q である場合はループが継続されてしまうことになります。
for 文
ループ文のなかでも while文とdo-while文はおもに繰り返しの回数が予測できない場合に使われます。それに対して for文 はループ回数を指定する形で使われます。
for.c
for文の( 条件式 )は以下のように3つの部分に分かれます。
for ( 開始の数値 ; 終了の数値 ; 1回ループする毎に増加もしくは減少するステップ数 )
サンプルの for.c では4行目で宣言された変数 i に 5行目のfor文の第一条件(開始の数値)で1を代入しています。そして第2条件でループの終了の条件を変数 i が100かそれ以下までと指定しています。i < 100 で 100 未満(100は含まれない)を表し i = 100 で i が 100 を表します。i <= 100 では 100を含むそれ以下の数値を表します。
サンプルコードの第3条件で書かれている i++ とは i の数値を1つ増加するという記号です。1つ増加する ++ をインクリメントと呼び、1つ減少させる - - をデクリメントと呼びます。この第3番目の条件は1回ループが終るごとに実行されます。
このサンプルコードを実行すると以下のように表示されます。
ここである回のループだけをとばす continue という文の使用法を説明するために、開始年(西暦)と終了年(西暦)を入力してもらい、その間の「うるう年」だけを表示するプログラムを書いてみましょう。
「うるう年」とは4で割り切れる年ですが、ちょうど100で割り切れる年(1900年や2100年)は「うるう年」には含まれません。ただし400で割り切れる年は「うるう年」になります。
では早速はじめてみましょう
uruu.c
このサンプルコードを実行すると以下のようになります。
コード説明
19行目までは今までに登場してきた構文ばかりなので新たに説明することは特にありません。少し難しいのは次の20行目です。( ) が3つネスト(入れ子状態)になっています。
まず1番内側の( )で ( i % 4 == 0 && i % 100 != 0 ) となっています。算術演算子の % は左辺を右辺で割った場合の割り切れなかった余りの数を返します。i % 4 の結果が 0 と == (等しい) なら i は4で割り切れたことになります、そして && (なおかつ) i % 1 00 が != 0 ( i を 100 で割ったあまりが 0 ではない、つまり100では割り切れなかった場合 ) i は「うるう年」になります。わかりやすいようにここまでを1つの( )で区切っています。
次に2番目の( )の右辺に || i % 400 == 0 と書いて、|| (あるいは) i が 400 で割り切れた場合は「うるう年」になることを表しています。
そして上記の2重の ( ( ) ) をまとめて ! not演算子で否定しています。つまり20行目の意味は「もし i がうるう年でなければ」という意味になります。
21行目の continue は if 文の条件が真(true)の場合に実行されます。continue はその回のループはそこで中止して次のループの最初に戻るという意味になります。したがって「うるう年でなければ23行目の printf 文は実行されず次のループの最初に戻ります。
お疲れさまでした。これで第5回「ループ文」は終ります。
learn C using Terminal は次回「データ型」が最終回になる予定です。最終回ではプリミティブ型(基本型)と呼ばれる単純なスカラー値を扱うデータ型、そのデータの集合を形造る配列や列挙型、そしてポインターなどの説明をしようと思っています。
なかでも構造体と呼ばれるユーザーが色々なデータ型を組み合わせて自由に作れるデータ型をオブジェクト指向の足がかりとして重点的に説明したいと思います。
なお、learn C using Terminal の続きとして learn ObjC 2.0 using Terminal を予定しています。
|
|
|