5週目

文字の入力
文字変数の入力はscanfを使うか、getcharを使うか、二通りある。
char a;
scanf("%c", &a);
int a;
a = getchar();
どちらも一文字入力を行って、入力した文字を変数aに代入する。
この二つのやり方は、ほとんど同じ。通常の文字(アルファベットや数字)を
入力する場合には、全く同じ。
改行(エンターキーを押したときに入力される文字)等の特殊な文字を入力
するには、getchar()を使う必要がある。scanfを使った場合には、改行文字等は
無視(削除)される。
入力するのに、getcharとscanfを混ぜて使うのは良くない!!!
1
文字の出力
同じ様に、文字を出力するのに、printfを使うか、putcharを使うか、
二通りのやり方がある。
char a;
a = ‘A’;
printf("%c", a);
char a;
a = ‘A’;
putchar(a);
この二つのプログラムは、全く同じことをする。
変数 a はcharとして宣言しているが、intと宣言しても
構わない。
2
繰り返し処理
同じ手順を繰り返す方法について考える。
画面に文字列リテラル "Hello!\n" を 10 回出力するプログラム
main()
{
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
printf("Hello!\n");
}
という具合にソースプログラムに
10 回書くのも手。しかし、、、
プログラミングがとても面倒。
繰り返し回数が固定されている。
もっと柔軟に繰り返し処理をしたい!
C 言語での繰り返し処理
for 文、while 文、do 文
3
繰り返し
• for文
広い範囲の繰り返しに使える
繰り返しを実行する前に一度だけ実行する文、
繰り返しの最後に実行する文を指定することができる。
• while文
ある条件が満たされるまで繰り返す
• do while文
文を実行した後で条件を調べ、繰り返す
4
for 文
繰り返し回数が、文の実行時に決まっている繰り返しを、所定回反復という
所定回反復では何回繰り返したかを数える変数を使う。これを繰り返し変数という。
繰り返し変数はたいていの場合整数型
所定回反復には for 文がよく用いられる。反復=繰り返し(ループ Loop ともいう)
for( 式1; 式2; 式3)文
式1:繰り返し変数の初期化
式2:繰り返しを続けるかどうかの判定。真なら継続、偽なら for文の終了
式3:繰り返し後の、繰り返し変数の演算
文 :繰り返す文の本体
繰り返し変数はプログラマが用意しなければならない
5
for 文の具体例
int i;
整数型の変数 i を繰り返し変数として用いる
for(i=0; i<10; i++)
printf("Hello!\n");
この例では、1) 繰り返し変数 i をゼロに初期化、2) i の値が 10 未満である限り文(printf)を
実行、3) 文の実行後、i の値を 1 増やす。
++ インクリメント演算子
i++ (または ++i) の実行で i の値が
1 増える
繰り返す処理が複数の文からなる場合はブロックを用いて複文にする(下左)。
int i;
int i;
for(i=0; i<10; i++){
printf("Hello!\n");
printf("%d\n", i);
}
左例と右例では
結果がまったく
異なることに注意!
for(i=0; i<10; i++)
printf("Hello!\n");
printf("%d\n", i);
6
for 文処理の流れ
for( 式1; 式2; 式3)文
式1
偽
式2の評価
真
式3
int i;
for(i=0; i<10; i++)
printf("Count = %d \n",i);
文
繰り返し変数 i をゼロに初期化。
0 < 10 は真なので printf を実行、その後、
i の値はインクリメントされて 1 となる。
1 < 10 は真なので printf を実行、その後、
i の値はインクリメントされて 2 となる。
...
10 < 10 は偽なので for文の終了。
繰り返しは i の値が 9 になるまで続く。
7
例1
int i;
for(i=10; i>0; i--)
printf("Count down %d !\n", i);
--:デクリメント演算子
i-- (もしくは --i) の実行で i の値が1減る
実行結果
%./a.out
Count down
Count down
Count down
...
Count down
%
10
9
8
1
・繰り返し変数 i を 10 に初期化。
・10 > 0 は真なので printf を実行。その後、
i をデクリメント。
・9 > 0 は真なので printf を実行。その後、 i
をデクリメント。
...
・i の値が 1 になるまで繰り返す。
・i の値が 0 になったとき、0 > 0 は偽なの で、
for 文の終了。
8
注意
繰り返し変数の初期化(式 1)、繰り返しの判定(式 2)、
繰り返し後の演算(式 3)を正しくプログラムしないと、永久に繰り返しが続く
無限ループに陥る場合がある。正しい繰り返しはプログラマの責任。
int i;
for(i=0; i<10; i--)
printf("Count down %d !\n",i);
繰り返し後の演算がおかしいので無限ループ。
整数の最小値 INT_MIN をデクリメントすると
INT_MAX になるので、実際はいつかは終了する。
int i;
for(i=1; i<10; i++){
printf("%d\n”,i);
i--;
}
繰り返し変数を繰り返し文中で操作すると予期せ
ぬ結果を招くことがあるので、しない。
%./a.out
Count down 0
Count down -1
Count down -2
...
%./a.out
1
1
1
1
...
本当の無限ループ
9
例2
次の 2 つの例はいずれも同じ結果を得る。繰り返し変数の初期化の違い。
int i;
int i;
for(i=0; i<10; i++)
printf("Count = %d \n",i);
for(i=1; i<=10; i++)
printf("Count = %d \n",i-1);
for 文の構文図
for
(
;
式
;
式
)
文
式
10
関連事項
+= 加法代入演算子
i+=2 は i の値を 2 だけ増やす
-= 加法代入演算子
i-=3 は i の値を 3 だけ減らす
*= 乗法代入演算子
i*=2 は i の値を 2 倍する
/= 除法代入演算子
i/=4 は i の値を 4 で割ったもので置き換える
++i と i+=1 と i=i+1 は同じ意味
i*=2 と i=i*2 は同じ意味
--i と i-=1 と i=i-1 は同じ意味
i/=2 と i=i/2 は同じ意味
= は代入演算子
100 以下の正の奇数を表示
i++と++i, i--と--iとはちょっと違う
int i;
int i,j,k;
for(i=1; i<=100; i+=2)
printf("%d\n", i);
i=10;j = ++i;
i=10;k = i++;
iは最初は10
jは11
kは10 ???
最後にはiは11
11
応用 1
キーボードから整数値を 10 個読み込み、それらの合計を計算するプログラム
int sum, data;
sum = 0;
/* 合計を保持する変数を初期化 */
scanf を10回用いて整数を
10個読み込むプログラム。
scanf("%d", &data);
sum += data; /* sum に足していく */
scanf("%d", &data);
sum += data;
scanf("%d", &data);
sum += data;
... /* 同じ手順を10回繰り返す */
プログラムを書くのが大変
読み込む回数を変えるには
ソースプログラムを修正してコ
ンパイルし直さないといけない。
(硬直したプログラム)
printf("合計は %d です\n", sum);
12
プログラム例 1
for 文を用いた前例の繰り返し処理
int sum, data, count;
sum=0; /* 合計を保持する変数を初期化 */
for(count=0; count<10; count++){
scanf("%d", &data);
sum += data; /* sum に足していく */
}
scanf による入力と加算を
複文でひと括りにして
for文で繰り返す
printf("合計は %d です\n", sum);
sum += data; の部分は sum = sum + data; でもよい
入力個数を変えるには for 文の繰り返し条件の部分を変更するだけで良い。
繰り返し条件の 10 を別の変数で置き換えれば、より柔軟なプログラムになる。
13
応用 2
10 回ではなく、加算する回数も入力して決めるプログラム
(何回繰り返すか、プログラム実行時まで不確定な場合)
int sum, data, count, count_MAX;
sum=0; /* 合計を保持する変数を初期化 */
scanf("%d", &count_MAX); /* 加算回数の入力 */
for(count=0; count<count_MAX; count++){
scanf("%d", &data);
sum += data; /* sum に足していく */
}
printf("%d 回の合計は %d です\n", count_MAX, sum);
count_MAX の値として 0 以下の値が入力された場合、for 文は何も実行しないで終了
14
応用 3
for 文も文の一つなので、for 文の繰り返し文として for 文を書ける
(for 文の入れ子、多重ループという)
* を縦横 10 x 10 個表示して四角を埋め尽くすプログラム
% ./a.out
**********
**********
**********
**********
**********
**********
**********
**********
**********
**********
%
printf を用いて * を 10 回続けて出力した後に改行。
これを 10 回繰り返せばよい。(二重ループ)
int i, j;
for(i=0; i<10; i++){
for(j=0; j<10; j++)
printf("*");
printf("\n");
}
横方向に 10 回 * を出力
改行
上の 2 つの手順を 10 回
繰り返す
横方向の繰り返しと縦方向の繰り返しのために繰り返し変数を 2 つ用いる。
15
for 文 追加
for( 初期設定; 判定条件; 繰り返し)文
初期設定等の式は普通は一つだけだが、複数の式
を書きたい場合はコンマ演算子を使う。
文1 , 文2 ;
int i,j;
for(i=0,j=10; i<10; i++,j--)
printf("Count = %d , %d\n",i,j);
あるいは式が必要でないときは空白にする
for( ; ; )
printf(“無限の繰り返し\n”);
16
問題 1
キーボードから入力した数の合計を計算するプログラムを
作成せよ。最初に、何個の数を入力するかその数を入力
するようにする。
%./a.out
いくつ入力しますか? 5
1番目の数は 10
2番目の数は 20
3番目の数は 15
4番目の数は 55
5番目の数は 30
5個の数の合計は130です。
17
問題 2
26以下の入力した数だけアルファベットを出力するプログラムを作れ。
アルファベットは、A,B,… と出力する。
%./a.out
26以下の整数を入力:25
ABCDEFGHIJKLMNOPQRSTUVWXY
%
この色はプログラムによる出力。
ヒント
for 文を使うこと。文字コードを参照。
文字コード(整数)を ‘A' から初めて 1 ずつ加算して表示すれば良い。
表示は、文字コードに対応する文字と空白である。
これを ‘Z' まで繰り返して最後に改行。
18
問題 3
正弦関数(sin)、余弦関数(cos)、正接関数(tan)の値を0°から90°まで、
5°間隔で表示するプログラムを作成せよ。
% ./a.out
角度 正弦関数 余弦関数 正接関数
0, 0.0000, 1.0000, 0.0000
5, 0.0872, 0.9962, 0.0875
10, 0.1736, 0.9848, 0.1763
15, 0.2588, 0.9659, 0.2679
20, 0.3420, 0.9397, 0.3640
25, 0.4226, 0.9063, 0.4663
30, 0.5000, 0.8660, 0.5774
35, 0.5736, 0.8192, 0.7002
40, 0.6428, 0.7660, 0.8391
45, 0.7071, 0.7071, 1.0000
50, 0.7660, 0.6428, 1.1918
55, 0.8192, 0.5736, 1.4281
60, 0.8660, 0.5000, 1.7321
65, 0.9063, 0.4226, 2.1445
70, 0.9397, 0.3420, 2.7475
75, 0.9659, 0.2588, 3.7321
80, 0.9848, 0.1736, 5.6713
85, 0.9962, 0.0872, 11.4301
%
この色はプログラムによる出力
度数dからラジアンrを求めるには
r = d*π/180
で計算される。
円周率 πの値は、M_PIという
名前で定義されている。
int i;
double s;
i = 10;
s = sin(i*M_PI/180);
でsin(10°)の値が求まる。
19
問題 4
下記のような、かけ算の九九の表を表示するプログラムを作れ。
% ./a.out
1*1 = 1, 1*2 = 2, 1*3 = 3, ..., 1*9 = 9
2*1 = 2, 2*2 = 4, 2*3 = 6, ..., 2*9 = 18
3*1 = 3, 3*2 = 6, 3*3 = 9, ..., 3*9 = 27
...
9*1 = 9, 9*2 = 18, 9*3 = 27, ..., 9*9 = 81
%
この色はプログラムによる出力
ヒント:2つの変数(1 から 9 までの整数)の 2 重ループ。
表示部分は、printf("%2d * %2d = %2d, ", i, j, i*j); として桁をそろえる。
i, j は繰り返し変数。
20
問題 5
下のような模様を出力するプログラムをつくれ。
%./a.out
文字は何にする?#
行数は?10
#
##
###
####
#####
######
#######
########
#########
##########
%
空白が10個、# が 1 個 + 改行
空白が9個、# が 2 個 + 改行
空白が8個、# が 3 個 + 改行
ヒント:
1)出力する文字を入力
2)繰り返し処理(横方向と縦方向の反復)
一度に 2 重ループを処理しようとしないで、まず最初に横方
向の繰り返し処理を考える。この部分を縦方向の繰り返し処
理で包んでやる。
この色はプログラムによる出力
21