繰り返し文
loopとは繰り返し文のことである。俗に反復処理と呼ばれていてC言語の根幹をなしている。反復処理にはwhile文、do-while文とfor文がある。
その昔、コンピュータの性能が悪かった時代、また、しっかりした制御構造および反復処理がプログラミング言語に用意されたいなっかた時代、多くの人がgoto文と呼ばれるジャンプを使ってプログラムを書いていた。しかし、1960年代後半goto文によって書かれたプログラムは、他人にとってわけのわからないプログラム(スパゲッティプログラム)になり、諸悪の根源であると言われ始めた。このことより、ソフトウェアも通常の工業製品と同じように生産管理が必要であるという観点から「ソフトウェア工学」が生まれた。このような流れの中から、分かりやすいプログラムを書くための方法論が提案され、その中の1つに「構造化プログラミング」がある。
構造化プログラミングとは、基本的に3つの構造から成り立っている。
1.プログラムは上から下に流れる(順次)
2.制御構造
3.反復処理
構造化定理によると、すべてのアルゴリズムはこの3つの構造だけで記述できることが証明されている。
しかし、日本語の構造のせいなのか、はたまたgoto文世代がプログラミング言語を教えているせいか、日本の学生は構造化プログラミングをマスターするのに多大な時間を必要としているのが現実である。
現在、C言語を学んでいる学生は、上記の1,2,3だけでアルゴリズムを書く練習をして欲しい。
例題5.1
12 + 22 + 32 + 42 + 52 + … + 1002を求めるというプログラムを作成しよう。
考え方
j番目がj2より和はs=s+j2と表せる。これをjが1から100まで行うのに、Cには3種類の繰り返し(loop)が用意されている。while,do while,for の3つである。
次の3つのプログラムはすべて同じ結果を出してくれる。
/*while loop*/ #include <stdio.h> void main(void) { int j=1,s=0; while(j
<=100) { s = s + j*j; j+=1; } printf(“%d”,s); } |
/*do while loop*/ #include <stdio.h> void main(void) { int j=1,s=0; do { s = s + j*j; j+=1; } while(j <=100); printf(“%d”,s); } |
/*for loop*/ #include <stdio.h> void main(void) { int j,s=0; for(j=1;j<=100;j++){ s = s + j*j; } printf(“%d”,s); } |
一般的に、j番目がある関数f(j)で表せるならば、上の式文s = s + j*j;をs=s+f(j)と書き換えればよい。
j++,j+=1,j=j+1は皆同じものを意味する。
例題5.2 次のような形を表示するプログラムを作成せよ。
考え方 <実行例1>
printf(“*”);または、
char aster=’*’;
printf(“%c”,aster);
で1つのアスタリスクを表示することができる。では*****と表示するにはどうすればよいだろうか。 確かにprintf(“*****”);でもできるが、これではアスタリスクを任意の数だけ表示せよとなると、不可能である。そこで、printf(“%c”,aster);を5回実行すると*****が表示できることに気づけばよい。5回実行させるには、例えばforループを用いるとfor(i=1;i<=5;i++)と書けばよいことを知っている。次に、第1回目には、1つのアスタリスク、第2回目は2つのアスタリスクと増やすにはどうすればよいだろうか。i<=5の5の代わりに、jを用いて、for(j=1;j<=5;j++){ for(i=1;i<=j;i++)}と書けば、外側のループが1回終了する間に内側のループがj回実行されることになる。内側のループが終了したら、改行する。ではプログラムを書いてみよう。
<実行例2> 実行例1との違いはアスタリスクを右詰めで表示しているところである。そこで、アスタリスクの前にブランクを挿入するコマンドを追加すればよい。
解答
#include <stdio.h> void main(void) { int i,j; for(j=1;j <= 5;j++) { for(i=1;i<=j;i++) { printf("*”); } printf("\n"); } } |
#include <stdio.h> void main(void) { int i,j,k; for(j=4;j >= 0;j--) {
for(k=1;k<=j;k++)
{
printf(“ “); } for(i=1;i<=5-j;i++) { printf("*”); } printf("\n"); } } |
練習問題5.1 次のプログラムの説明およびプログラムを読んで、設問に答えよ。
「プログラムの説明」
標準入出力よりタイトルと数値データを読み取り、「*」の棒グラフを出力するプログラムである。タイトルはそのままエコーバックする。数値は同数の「*」に変換する。入力データのタイトルと数値データは「,」で区切る。
「設問」 プログラム中の括弧を埋めて、プログラムを完成せよ。
#include <stdio.h>
int echo_line(void); /* 関数*/
void print_stars(int size); /* 関数*/
void main(void)
{
int value;
while( ア ){ /* ファイルの最後まで読む*/
scanf(イ,&value);
print_stars(ウ);
}
}
int echo_line(void)
{
int c;
if(scanf(“%c”,&c) == EOF) return (EOF);
for( ; ; エ) { /* 1文字づつ読み込む*/
if( オ ) return( c );
else putchar ( c );
}
}
void print_stars(int size)
{
int i;
for( i = 1; カ ; i++) putchar( ‘*’ );
putchar( キ );
}
解答 関数echo_line( )は文章の最後を読むと、EOFをmain関数に返す。そこで、文書の最後まで読むにはアにecho_line( ) != EOFが入る。イはvalueを読むための書式なので%dが入る。print_star関数の引数は’*’の個数であるからウにはvalueが入る。区切り文字を判定しつつ1文字づつ読むのでエにはc=getchar( )が入る。区切りの判定なのでオにはc==’,’が入る。print_star関数は、数値分「*」を出力するので、カにはi <=sizeが入る。「*」の出力の後に必要なのは、改行の出力であるのでキには’\n’が入る。
キャッチ getcharが1文字づつ読み込むのに対して、putcharは1文字づつ表示する。 getcharとはget characterの意味で、putchar はput charcterの意味である。 |
例題5.3 整数を読み取って、素因数分解するプログラムを作成せよ。
実行例
考え方 データnを読み取って、2から順に割っていき、ある数mで割れたらn/mを新たなnとおき、商が1になるまで続ける。このとき発生した、mが素因数となる。表示するときに、最後の数字のあとには「,」を付けないようにする。
では、プログラムを書いてみよう。
解答
#include <stdio.h> void main(void) { int m,n; char c = ' '; printf("整数を入力してください。"); scanf("%d",&n); for (m=2;n != 1;m++) { while(n%m == 0) { n = n/m; printf("%c%d",c,m); c = ','; } } } |