【C言語講座】第5回 同じ作業を何度も繰り返す
閉じる
閉じる

新しい記事を投稿しました。シェアして読者に伝えましょう

×

【C言語講座】第5回 同じ作業を何度も繰り返す

2015-09-29 00:50
  • 2
0.今回扱う内容

今回は一貫して「繰り返し」について扱います。
だんだん分岐やループが入って頭がこんがらがると思いますが、一つ一つ丁寧にゆっくり読み解いていけば難しくありません。

ゆっくり行きましょうね。休み休み。

1.インクリメントと複合代入演算子 ~ 「1増やす」の3通りの書き方
2.while文による繰り返し ~ 条件が成り立つ限り、無限に繰り返す
3.for文による繰り返し ~ 回数がわかるとき使うと便利!
4.無限ループとbreak文 ~ ループをかちぬくぞ!
5.繰り返しの入れ子 ~ 二つの変数を同時に動かす


1.インクリメントと複合代入演算子 ~ 「1増やす」の3通りの書き方

今回「繰り返し」について扱うにあたって、「変数の更新」という話をしなくてはなりません。

今まで変数に入れてきたのは、「3や5など、プログラマーが予め入力した数字」か「他の変数の中身(および、それを計算したもの)」ばかりでした。

しかし、実際のプログラミングでは、「変数を1増やす」とか「変数を1減らす」、あるいは「変数に3を掛ける」といった場面が多く出てきます。

たとえば、ゲームの例で言うと、「キャラクターを右に進める」ということは、「キャラクターの場所の変数を少し増やす」ということにあたります。

ここでは、そんな「変数の更新」のやり方を学びます。まずはコード例から。

最初は宣言。「int a = 3;」なので、int型(整数)の変数『a』の場所をとって、3を入れています。

次に、「a = a + 5;」という文があります。
「『a=a+5』だったら式が成り立たないじゃん!」と思った方は、「『=』は『代入』を表す記号」というのを思い出しましょう。「等しい」は「==」でした。
つまり、「a」の棚から中身を取り出して、それに5を足して、また「a」の棚に戻す、ということです。

aに3を入れて、それを取り出して5を足して戻し、printfでaを表示させているので、結果はもちろん……

となります。

次は、「複合代入演算子」という話。
たとえば、「a += 5;」なら「変数『a』の中身に5を足して、『a』に戻す」という意味になります。つまり、「a = a + 5;」と同じですね。
複合代入演算子には、四則演算の演算子と対応した5種類があります。

  • 「a += 5;」 ……変数「a」の中身に5を足して、「a」に戻す
  • 「a -= 5;」……変数「a」の中身から5を引いて、「a」に戻す
  • 「a *= 5;」……変数「a」の中身に5を掛けて、「a」に戻す
  • 「a /= 5;」……変数「a」の中身を5で割って、「a」に戻す
  • 「a %= 5;」……変数「a」の中身を5で割った余りを「a」に戻す
  • 他にも種類はありますが普通の人は使わないと思います

なお、「/=」の場合も「整数÷整数」は整数になります。

最後に、「インクリメント」の話。
プログラミングでは「1増やす」という場面が特に多く出てきます。
「1増やす」は複合代入演算子を使って「a += 1;」と書けますが、これを更に簡単にした書き方があります。
「a++;」と書けば、「『a』を1増やす」の意味になります。
この「++」を「インクリメント演算子」と呼び、「1増やす」ことを「インクリメントする」と言います。

その逆に、「1減らす」は「a--;」と書けます。こちらは「デクリメント」と呼ばれます。

以上をまとめると、「『a』を1増やす」は

  • a = a + 1; (通常の代入)
  • a += 1; (複合代入演算子)
  • a++; (インクリメント演算子)

の3通りで書けます。

ここで練習。次のコードの実行結果を予想してみましょう。

さて、予想はできましたか? 結果を先に出してしまうと面白くないので、まずは読み解いていきましょう。

宣言の時点では、aに1が入っています。
そして、「a = a + 2;」で、aの中身に2を足してaに戻すので、aの中身は3になります。
次に、「a *=3;」でaの中身に3を掛けるので、aの中身は9になります。
最後に「a++;」でインクリメントしてからprintfで表示するので……

結果は次の通り。


2.while文による繰り返し ~ 条件が成り立つ限り、無限に繰り返す

この章からは「繰り返し」について扱いますが、その前に一つ学んでおかなくてはならない事があります。
それは、「無限ループ」についてです。
繰り返し、という分野の都合上、コードを少し間違えると、動作を無限に繰り返してしまう可能性があります。
そんな時は、Ctrl+Cで強制的にプログラムの実行を止めることができます(Visual Studioの場合)。
まあ、右上の×ボタンで終了してもそんなに問題は無いんですが、そうすると実行結果が画面に残らなくなるので、無限ループが発生してしまった原因がわからなくなってしまいます。

この「最終手段」を頭に入れた上で、先に進みましょう。まずはコード例。

さあ、読んでいきましょう。
「int i=1;」はいつも通り「宣言」、つまり「int型(整数)の変数『i』の場所を取る」のでした。それと同時に、「i」に1を入れています。

次が問題です。でも、if文と形だけは似ています。
if文は、

if (条件) {
やりたいこと
}

なのに対し、この「while文」は、

while (条件) {
やりたいこと
}

になっています。
タイトル通り、while文は「条件が成り立つ限り、中身を繰り返す」文です。
フローチャートに直すと以下のようになります。

つまり、

  • int型の変数「i」を宣言し、1を入れる
  • 条件「iは10以下?」→ iは1なので成立
  • printfで「i回目」、つまり「1回目」と表示し、改行
  • iをインクリメントし、iは2となる
  • 条件「iは10以下?」→ iは2なので成立
  • ……(iが10になるまで省略)
  • printfで「i回目」、つまり「10回目」と表示し、改行
  • iをインクリメントし、iは11となる
  • 条件「iは10以下?」→ iは11なので不成立
  • return 0;(終了

という流れになります。難しいですか?

実行結果は次の通り。

つまり、このプログラムは「1回目」から「10回目」までを順に表示するプログラムでした。

ちなみに、ループで動かす変数はi,j,k,……などと名前をつけるのが一般的なので、ここでもそれに従いました。


3.for文による繰り返し ~ 回数がわかるとき使うと便利!

前章ではwhile文による繰り返しを学びました。
ただ、前章の例では「繰り返す回数」が事前にわかっていました。
このような場合、便利な書き方があります。

まずはコード例。

見慣れない箇所は

for (i = 1; i <= 10; i++){

です。ここで扱う「for文」は、

for (初期設定; 継続条件; 繰り返し式) {
やりたいこと
}

という構造を持ち、実際に実行すると、

という順番に実行されます。さっきのwhile文と同じですね。

また、if文と同様に、for文も中身が1行なら省略した書き方があります。

for (i = 1; i <= 10; i++) printf("%d回目\n",i);

となります。

実行結果は前章と同じなので省略します。

ところで、while文の書き方でもfor文の書き方でも必ず最初に「変数の初期化」を行っています。「初期化なんかしなくても最初に入ってる数字はある決められた数になってるんじゃないの?」とお思いの方のために、こんなコードを実行してみます。

実行しようとするとまずエラーが出て怒られます。
それでも「無視」を押して実行させると、

という感じで、でたらめな数が表示されます。

これは、「変数は棚」のイメージがあれば簡単な話。
変数の棚は他のプログラムも使うので、変数を宣言した段階、つまり場所をとった段階では、前のプログラムが使った状態のまま放置されているのです。ごちゃごちゃなまま。
というわけで、新しく変数を宣言するときは、必ず初期化を行いましょう。
ただし、後々何か数字を入れるのがわかっている場合はその限りではありません。


4.無限ループとbreak文 ~ ループをかちぬくぞ!

ここでは、「無限ループ」について学びます。
先ほど「無限ループは実行が止まらなくなって怖い」という話をしましたが、無限ループもうまく使えば便利です。

では、コード例。

while文の条件に「1」と書かれています。
実は、プログラムの内部では「条件成立」は「1」、「条件不成立」は「0」として扱われています。
つまり、「while (1){」と書けば条件が常に成立するので、ループが無限に続くことになります。

ではどうやってループを抜けだすのか?
その答えが「if (a > 1000) break;」です。

break;」はループを抜けだす、という命令です。
なお、ループが入れ子になっている場合は一番内側のループだけを抜け出します。

つまり、「if (a > 1000) break;」で、「もしaが1000より大きければ、ループを抜けだす」という意味になります。

また、aは1からスタートし、ループを回るごとに「a *= 2;」でaが2倍になっていくので、1,2,4,8,16,32,……,512,1024,……と大きくなっていきます。
aが1000より大きくなったらループを抜けるので、aが1024になった時点でループを抜けることになります。

結果を見てみましょう。

aが1024になった直後、printfを通る前にループを抜けるので、1024という数字は表示されません

これなら、whileの条件に「a > 1000;」と書いても同じだと思う人も居ると思います。確かに結果は同じになりますが、もっと複雑なコードになると、こちらの書き方が見やすい場合がよくあります。
また、break文は、whileの条件とは別に、例外的にループを抜けなくてはならない場合にも用いられるので、覚えておきましょう。


5.繰り返しの入れ子 ~ 二つの変数を同時に動かす

ここでは、「入れ子」について学びます。
if文を入れ子にできる(ネストできる)のは既に学んだ通りですが、forやwhileもネストできます。それではコード例。

ちなみにこれは、第1回の「インデント」の例で出したプログラムとほぼ同じものです。
ついにここまでたどり着きましたね。

ちょっと新しい事項が多いかもしれません。

まず、宣言ではiとj、2つの変数を用意しています。

そして、iを変数としたループの中にjを変数としたループが入っています。

また、printfに「%3d」という見慣れない変数文字列が入っています。
これは、元の数字がどうあれ必ず3桁に揃えて表示する、という変数文字列です。
たとえば、「3」を表示するときも「 3」と表示され、縦が揃って見栄えが良くなります。
実行結果を見れば多分意味はわかると思います。

流れは次のようになります。

forの部分をちょっと簡略化して書きました。意味はわかりますかね?
ハンバーガーみたいなイメージで、上と下で挟まれた部分を繰り返します。

実行結果は次の通り。

小学校でよくある九九の表が表示されました。

プログラムの実行順序を追っていくと次のようになります。

  • int型の変数「i」,「j」を用意する
  • iに1を入れる
  • 条件「iは10より小?」→ iは1なので成立
  • jに1を入れる
  • 条件「jは10より小?」→ jは1なので成立
  • 「i*j」、つまり「 1」を表示
  • jをインクリメント(jは2になる)
  • 条件「jは10より小?」→ jは2なので成立
  • 「i*j」、つまり「 2」を表示
  • ……
  • jをインクリメント(jは10になる)
  • 条件「jは10より小?」→ jは10なので不成立
  • printfで改行
  • iをインクリメント(iは2になる)
  • 条件「iは10より小?」→ iは2なので成立
  • jに1を入れる
  • 条件「jは10より小?」→ jは1なので成立
  • 「i*j」、つまり「 2」を表示
  • ……
  • iをインクリメント(iは10になる)
  • 条件「iは10より小?」→ iは10なので不成立
  • 終了

となります。つまり、1の段を表示して改行、2の段を表示して改行、……と進みます。

ちょっと難しいですかね? 繰り返し眺めていればそのうち理解できると思います。頑張りましょう。


ここまで来ればプログラミングの基礎は身についたと思います。

とはいえ、まだまだ実際に思い通りのプログラミングをするには知識が足りません。

次回からは基礎を抜けてちょっと難しい話を扱います。

とりあえず次回は基礎脱出記念として、今まで「おまじない」とか「当然書くべきもの」とみなしてきた「#include」だとか、「return 0;」とかの本当の意味を扱う予定です。


広告
×
この記事を読んでC++の基礎について知ることができました。ありがとうございました!
34ヶ月前
×
とてもわかりやすかったです!
更新が途絶えていますがもう投稿されないのでしょうか?
26ヶ月前
コメントを書く
コメントをするには、
ログインして下さい。