第2回
3 判断力を磨きましょう
制御構造の種類
|
制御構造の種類 |
C++言語での構文と内容 |
|
選択(条件分岐) |
if 条件に応じて処理の流れを分岐させる switch ある整数式の値に応じて処理を多重分岐させる |
|
無条件分岐 |
goto 制御の流れを無条件に変更する |
|
繰り返し |
while 条件式が成り立つ間繰り返す do while 一度は実行する while for カウンタ変数を用いて繰り返しを制御する |
|
モジュール化 |
ひとまとまりの処理に名前をつけて再利用できる 関数 ようにするとともに,他の部分で副作用が起こらない ように囲い込む |
関係演算子
|
関係演算子 |
数学上の表現 |
C++での表現 |
意味 |
|
== |
= |
a == b |
aとbが等しい |
|
!= |
≠ |
a != b |
aとbが等しくない |
|
>= |
³ |
a >= b |
aはb以上である |
|
<= |
£ |
a <= b |
aはb以下である |
|
> |
> |
a > b |
aはbより大きい |
|
< |
< |
a < b |
aはbより小さい |
3.1 条件分岐(1)
例題3−1
整数を1個入力してその整数が偶数ならば偶数と出力します.奇数の場合は,何もしません.
▼プログラム
e3-1.cpp
01 // 例題3−1 (日付 学籍番号 氏名)
02
// 整数を1個入力してその整数が偶数ならば偶数と出力する.
03
04
#include
<iostream>
05
using
namespace std;
06
07
int
main()
08
{
09
int c;
10
11
cout << "整数を1個入力してください:";
12
cin >> c;
13
14
if (c % 2 == 0) {
15
cout << c << " は偶数です" << endl;
16
}
17
18
return 0;
19
}
練習問題3−1
例題3−1で,ifの条件部分をif (1 == c % 2)と変えてみましょう.
練習問題3−2
例題3−1で,ifの条件部分をif (c % 2 = 1) と変えてみましょう.
練習問題3−3
例題3−1で,整数dを宣言し,ifの条件部分をif (d
= c % 2) と変えてみましょう.
練習問題3−4
次のプログラムは,整数nが1かどうかチェックするプログラムです.正しく動くでしょうか.正しく動かないとするとなぜでしょうか.
if (n
= 1) {
cout <<
"1です"
<< endl;
}
同様に,次のプログラムは,整数nが0かどうかチェックするプログラムです.正しく動くでしょうか.正しく動かないとするとなぜでしょうか.
if (n
= 0) {
cout <<
"0です"
<< endl;
}
練習問題3−13
2個の整数a,bの値をキーボードから入力して,次の4つの条件式
(1) a == b
(2) a != b
(3) a >= b
(4) a <= b
の評価値を出力するプログラムを作成してみましょう.
練習問題3−14
以下のプログラムをコンパイル(して,もし可能ならば実行)してみてください.
if (n
= a < b) {
cout <<
"aはbより小さい" << endl;
}
cout
<< "nの値は
" << n << " です" <<
endl;
3.2 条件分岐(2)― 条件が成り立たなかった場合
例題3−2
例題3−1を変更して,整数を1個入力してその整数が奇数ならば「奇数です」,偶数ならば「偶数です」と出力するプログラムを作成してみましょう.
▼プログラム
e3-2.cpp
01 // 例題3−2 (日付 学籍番号 氏名)
02
// 整数を1個入力してその整数が奇数ならば奇数,偶数ならば偶数と出力する.
03
04
#include
<iostream>
05
using
namespace std;
06
07
int
main()
08
{
09
int c;
10
11
cout << "整数を1個入力してください:";
12
cin >> c;
13
14
if (c % 2 == 1) {
15
cout << c
<< " は奇数です"
<< endl;
16
} else {
17
cout << c
<< " は偶数です"
<< endl;
18
}
19
20
return 0;
21
}
練習問題3−15
以下のプログラムは,英語の大文字であるかどうかを調べるためのものです.大文字の場合は「大文字です」,それ以外の場合は「大文字ではありません」と出力します.正しく動いているか(a や % を入力して)確認してください.正しく動かないとしたら,正しく動くように修正してみましょう.
#include <iostream>
using namespace
std;
int
main()
{
char ch;
cout
<< "文字を入力してください:";
cin >> ch;
if (ch >= 'A')
if
(ch <= 'Z')
cout << ch << " は大文字です" << endl;
else
cout
<< ch << " は大文字ではありません" << endl;
return 0;
}
練習問題3−18
以下のプログラムを実行して,何が起こっているか考えましょう.
i = 0;
if (i++ > 0) {
cout
<< i << " > 0" << endl;
} else {
cout
<< i << " <= 0" << endl;
}
i++ を ++i に変更するとどうなるでしょう。
練習問題3−20
整数nを読み込んで,その逆数1/nを浮動小数点型で出力するプログラムを書いてみましょう.0が入力されたら,"計算不能です"と表示して終了しなさい.
練習問題3−21
次のプログラムを実行してみましょう.
#include <iostream>
using namespace
std;
int
main()
{
double a = 0.0000001, b = 0.0001;
if (a == b / 1000.0) {
cout << "OK" <<
endl;
} else {
cout
<< "NO" << endl;
}
cout << "a - b / 1000.0 = " << a - b / 1000.0
<< endl;
return 0;
}
注.浮動小数点型の誤差に注意すること.特に,小数点以下は2進数で表現されるので,
例えば,
0.1 = 0×2-1 + 0×2-2 + 0×2-3 + 1×2-4 + …
といった無限小数表現となってしまう.
3.3 条件分岐(3)― 複雑な条件分岐
例題3−3
文字を読み込んで,その文字が英語の文字かそれとも数字かを判定するプログラムを作成してみましょう.
▼プログラム
e3-3.cpp
01 // 例題3−3 (日付 学籍番号 氏名)
02
// 文字を読み込んでその文字が英語文字かそれとも数字かを判定する.
03
04
#include
<iostream>
05
using
namespace std;
06
07
int
main()
08
{
09
char ch;
10
11
cout << "文字を一文字入力してください:";
12
cin >> ch;
13
14
if ((ch >= 'a' && ch
<= 'z') || (ch >= 'A' && ch <= 'Z')) {
15
cout << "英語の文字です." << endl;
16
} else if (ch >= '0' &&
ch <= '9') {
17
cout << "数字です." << endl;
18
} else {
19
cout << "英数字以外の文字です." << endl;
20
}
21
22
return 0;
23
}
《演算子の優先度と結合順序》
|
演算子 |
結合規則 |
|
スコープ解決 :: 関数呼び出しなど () [] -> . 単項 ! ~ ++ -- +
- * & (type) sizeof new delete 乗法 * / % 加法 + - ビットシフト << >> 関係 < <= > >= 等価 == != ビットand & ビットxor ^ ビットor | 論理and && 論理or || 条件 ?: 代入 = += -= *= /= %= >>= <<= &= ^= |= コンマ , |
右から左 右から左 右から左 |
注1. 演算子の優先関係は迷ったら,()を用いて明示するようにしましょう.
注2. 論理演算子&&では,左右のオペランドは必ず評価されるが,論理演算子||では,左オペランドをまず評価してそれが真の場合は右オペランドは評価されない,ことをしっかり覚えておきましょう.
注3. コンマ演算子は2項演算子で,評価値として右オペランドの値を返します.
練習問題3−22
次のプログラムを実行してみて何が起こっているか確認してみましょう.iに0を入力したり,1を入力してみてください.
if (!i == 0) {
cout << i << " は0ではありません."
<< endl;
} else {
cout << i << " は0です."
<< endl;
}
練習問題3−23
次のプログラムを実行するとどうなるでしょうか.
i = j = 0;
if (i = 5 || j = 4) {
cout << i << ", "
<< j << endl;
}
練習問題3−24
次のプログラムを実行するとどうなるでしょうか.
i = j = 4;
if (i == 5, j == 4) {
cout << i << ", "
<< j << endl;
}
練習問題3−25
次のプログラムを実行してみて何が起こっているか確認してみましょう.
i = -1;
j = -2;
if ((i = 5) || (j = 4)) {
cout << i << ", "
<< j << endl;
}
if ((i = 0) || (j = 4)) {
cout << i << ", "
<< j << endl;
}
練習問題3−29
a, bを0, 1(0が偽,1が真)の値を取るブール型の変数とします.このとき,a, bの間の2項論理演算NAND, NOR, XORを表す演算を論理演算子を用いて定義して,a, bの値を入力するとNAND, NOR, XORの値を計算して出力するプログラムを作成してみましょう.
▼出力例
ブール値aを入力してください: 1↵
ブール値bを入力してください: 0↵
a = 1, b = 0
NAND = 1
NOR = 0
XOR = 1
練習問題3−30
小数点以下第3桁で四捨五入して,小数点以下第2位までの浮動小数点に変換するプログラムを作成してみましょう.負の数にも対応できるようにしなさい.特に小数点以下の0がうまく表示できるように注意しましょう.例えば, -3.9951を入力すると-4.00を出力します.但し,#include <iomanip> による書式設定の関数は用いないこと.
3.4 条件分岐(4)
例題3−4
何月かを表す整数を読み込んで,その月が何日あるかを出力するプログラムを作成してみましょう.
▼プログラム
e3-4.cpp
01 // 例題3−4 (日付 学籍番号 氏名)
02
// 何月かを読み込んで,その月が何日であるかを出力するプログラム
03
04
#include
<iostream>
05
using
namespace std;
06
07
int
main()
08
{
09
int month, day;
10
cout << "何月ですか?";
11
cin >> month;
12
13
switch (month) {
14
case 2: day = 28; // うるう年は考えない
15
break;
16
case 4:
17
case 6:
18
case 9:
19
case 11: day = 30; // 小の月
20
break;
21
case 1:
22
case 3:
23
case 5:
24
case 7:
25
case 8:
26
case 10:
27
case 12: day = 31; // 大の月
28
break;
29
default: cout << month << "月はありません" << endl;
30
return
1;
31
}
32
cout << month << "月は" << day <<
"日です." << endl;
33
return 0;
34
}
練習問題3−31
例題3−4のcaseラベルで,定数式である数値リテラルのかわりに,式(たとえば,変数dayや,day - 1といった式)を使ってみるとどうなるでしょう.
練習問題3−35
1〜3の整数を読み込み,それをローマ数字(T, U, V)に変換するプログラムを作成してみましょう.VはIを3回出力するように,“串刺し実行”で実現してみましょう.
3.5 数学関数群
例題3−5
数を入力すると,その平方根を求めるプログラムを作成してみましょう.
▼プログラム
e3-5.cpp
01 // 例題3−5 (日付 学籍番号 氏名)
02
// 数を入力するとその平方根を求める
03
04
#include
<iostream>
05
#include
<cmath>
06
using
namespace std;
07
08
int
main()
09
{
10
double a;
11
cin >> a;
12
cout << a << "の平方根は" << sqrt(a)
<< endl;
13
return 0;
14
}
《よく使われる数学関数》
sin(x) xの単位はラジアン
cos(x)
atan2(y, x) y/xのarctangent
exp(x) 指数関数 ex
log(x) xの自然対数(基数はe)(x > 0)
log10(x) xの常用対数(基数は10)(x > 0)
pow(x, y) xy
sqrt(x)
fabs(x) xの絶対値
ceil(x) x以上の最小の整数値
floor(x) x以下の最大の整数値
3.6 時刻と日付
例題3−6
現在の日付を西暦で,たとえば,2003年9月24日と表示するプログラムを作成してみましょう.
▼プログラム
e3-6.cpp
01 // 例題3−6 (日付 学籍番号 氏名)
02
// 現在の日付,時刻を求めるための機能をチェックする
03
#include
<iostream>
04
#include
<ctime>
05
using
namespace std;
06
07
int
main()
08
{
09
time_t now; // time_t型の変数としてnowを定義する
10
time(&now); // これで,nowに現在時刻が入る
11
tm *np; // tmという型(構造体)へのポインタを設定する
12
np = localtime(&now); // これで日本時間に変換される
13
int year, month, day, hour, minute,
second;
14
15
year = np->tm_year + 1900; // 西暦年がセットされる
16
month = np->tm_mon + 1; // 月の値(0〜11)なので1足す
17
day = np->tm_mday;
// 日の値(1〜31)
18
hour = np->tm_hour; // 現在時刻の時(1〜23)
19
minute = np->tm_min; // 現在時刻の分(1〜59)
20
second = np->tm_sec; // 現在時刻の秒(1〜59)
21
cout << year << "年" << month <<
"月" << day << "日" << endl;
22
return 0;
23
}
練習問題3−38
現在の時刻を,たとえば,13:05と表示するプログラムを作成してみましょう.
練習問題3−39
現在の時刻を,たとえば,1:05 PM と表示するプログラムを作成してみましょう.
練習問題3−40
今日の日付,時間,曜日を次のように表示するプログラムを作成してみましょう.
2003年09月24日 4:05 PM
今日は水曜日です.
《ヒント》例題3−6で,np->tm_wdayを用いると曜日(0〜6で日曜から土曜に対応)が得られます.曜日の名前を配列で用意して表示してみましょう.月日,時刻をそれぞれ2桁表示で頭に0を付加するには,#include
<iomanip> を行い,適当な入出力マニピュレータを調べて使用しなさい。
練習問題3−41
下記のa)〜d)に示した出力を行うように,次に示したコード断片を変更してください.但し,大カッコを挿入する以外の変更を行ってはいけません.また,変更が必要でない場合もありえます.解答は,それぞれ字下げを行って見やすい形で示しなさい.
if (y
== 8)
if (x == 5)
cout <<
"@@@@@" << endl;
else
cout <<
"#####" << endl;
cout <<
"$$$$$" << endl;
cout <<
"&&&&&" << endl;
a) x = 5, y = 8と仮定すると,次のように出力する.
@@@@@
$$$$$
&&&&&
b) x = 5, y = 8と仮定すると,次のように出力する.
@@@@@
c) x = 5, y = 8と仮定すると,次のように出力する.
@@@@@
&&&&&
d) x = 5, y = 7と仮定すると,次のように出力する.
#####
$$$$$
&&&&&
練習問題3−42
伝説によれば,1626年にPeter Minuit氏は24ドルでマンハッタン島を購入したという.彼は果たして良い買い物をしたのであろうか?この問題に答えるため,複利計算プログラムを作成しなさい.そして,元金24ドルからスタートして2003年(377年間)における元利合計を計算してみましょう.具体的に,年利率を5%,6%,7%,8%,9%,10%とした場合の計算結果(億ドルを単位に小数点以下2桁まで)を示しなさい.
《ヒント》数学関数powを用いなさい.その場合,#include <cmath> が必要です.
表示をそろえたり,小数点以下2桁まで示したりするための書式設定には
#include
<iomanip> を行い,適当な入出力マニピュレータを調べて使用しなさい。
▼出力例
年利率(%) 元利合計(億ドル)
5 23.37
6
832.76
7
…