2009年10月21日水曜日

第17回 関数① 基礎

お題:
関数定義を行い、関数呼び出しによって3つの値の平均値を求めよ
①3つの数を入力させる
②関数呼び出しにより平均値を表示する

プログラム実行例:

image

必須事項:
・関数定義をし、平均値を返す
・関数呼びだしを行う

予備知識:関数定義と関数呼び出し
image 
関数定義と関数呼び出しを使ったプログラムの例です。
C言語のプログラムは
int main () {}
のmain関数が核となります。これがないと動きません。
関数定義は、プログラム例の
int kansu () {}
の部分です。ここでは関数kansu()を定義しています。
kansuはこちらが勝手に決めた名前で、自分で決められます。
return();
は、関数kansu()が吐き出す値です。イメージとしては
()に数字をつっこむ → 関数kansu()が計算 → 答えを吐き出す
といった感じです。
このように関数を利用する事を関数呼び出しといいます。
このプログラム例では、9行目でkansu()を使ってますが、kansu(2,3)の2,3は
3行目のkansu(int x , int y)のx,yに代入され、
return();の()内の計算結果の答えが吐き出されます。

関数は一つ答えを吐き出すのが基本です。
答えが一つ、つまり
return();が1つに定まれば、関数定義の中でif文で条件分けすることで
複数のreturn();を書く事が出来ます。

解答は10月24日夜に掲載します。それまでにプログラムを作成し、
・プログラム文
・その実行ファイル
をメールに添付して以下のアドレスに送ってください。 チェックして返信します。

解答、質問はこちらまで
cosmo-cleaner@za.pial.jp

2009年10月15日木曜日

第16回 配列② 配列の初期値と文字列 順序変え

お題:
恒星とその直径のデータを用いて、小さい星順に並び変える。
①用意してある恒星とその直系のデータを用いて並び替えをする
②1位から8位まで表示する

プログラム実行例:
image

必須事項:
・このページに用意してあるプログラムの一部を組み込む事
・並び変えるプログラムを作る事

ヒント:
・以下のプログラムの一部をコピー&ペーストして使ってください
char a[8][10]={"mercury","venus","earth","mars","jupiter","saturn","uranus","neptune"};
int  b[8]={4879,12103,12756,6794,142984,120536,51118,49572};

・配列の初期値は上のプログラムのようにして宣言する事が出来ます。
・数値の単位はkmです。
・並び変える方法はいろいろあります。
・順位を記憶するのための配列を作ると便利です。

重要:
上のプログラムについて、
charは文字型といい、intの文字版だと思ってください。charで宣言すると文字を変数に代入する事が出来ます。
この場合、a[8][10]はタテ8行、横10列の文字を入れる表を作ったと考えてください。1つの枠に1文字入ります。つまり、

m e r c u r y      
v e n u s          
e a r t h          
m a r s            
j u p i t e r      
s a t u r n        
u r a n u s        
n e p t u n e      

といった感じです。
ここからが重要で、この文字列をprintfで表示するには以下のように記述します。

printf(“ %s ”, a[i]);

iは行を表しています。例えばa[0]なら%sの所に「mercury」が表示されます。

解答は10月17日夜に掲載します。それまでにプログラムを作成し、
・プログラム文
・その実行ファイル
をメールに添付して以下のアドレスに送ってください。 チェックして返信します。

解答、質問はこちらまで
cosmo-cleaner@za.pial.jp

---------------------------------------------------------------

解答例

1

2

3


4


5
6

7
8
9
10
11
12
13
14

15
16
17
18
19
20
21

22

#include <stdio.h>

int main () {

    char a[8][10]={"mercury","venus","earth","mars","jupiter","saturn","uranus","neptune"};
    int  b[8]={4879,12103,12756,6794,142984,120536,51118,49572};
    int  c[8];
    int i,j,k;

    for (i=0;i<=7;i++){
        k=1;
        for(j=0;j<=7;j++){
           if(b[j] < b[i])
                k++;
        }
        c[i]=k;
    }

    for(k=1;k<=8;k++){
        for(i=0;i<=7;i++){
            if(c[i]==k) {
                printf("%d %s %dkm \n",k,a[i],b[i]);
            }
        }
    }

}

実行例は上と同じです。

解説

今回使った変数とその役割

a[8][10]
b[8]
c[8]
i
j
k
文字を格納する行列 8行10列で8項目10文字まで記憶
恒星の直径データ
恒星の順位データ
カウントアップ用
カウントアップ用
順位決定用

配列の初期値は3,4行目のように書くことが出来ます。
初期値は配列の枠の数だけ入れる必要はありません。例えば、

image

このように枠100個の配列に対し、”1,2,3”しか初期値を入力しなかったとしても、問題なくプログラムが通ります。結果は以下のようになり、

image

a[0]から順に代入され、あとは”0”となります。

7行目のfor文は恒星の直径が小さい順に順位をつけています。
7行目のfor文:比較する恒星(1つ)
9行目のfor文:8つの恒星を順に大きさ比べ

となってます。ここで、7行目で選んだ恒星を親恒星、9行目の恒星を子恒星とします。
赤いif文が肝で、親恒星が子恒星より大きかった時、kが1増えます。
つまり、親恒星の大きさが全体の3番目に小さい時、親恒星より小さい恒星は2つしかありません。よって、kの初期値は1ですから、9行目のfor文でkは2増え、kは3となります。
kは自動的に順位を表す事になります。
青い命令でc[]に順位データを代入します。

15行目からのfor文は配列c[]の順位データに基づいて並べ替えしながら、直系の小さい順に表示しています。
15行目のfor文:表示する順位を決定
16行目のfor文:配列c[]を全部調べる
となっています。
紫色のif文が肝で、15行目のfor文で決定した順位kと合致するc[i]があった時、printfで表示します。
a[i],b[i],c[i]は同じ星の情報なので、iさえ分かればそれに関する情報が全部表示できます。配列の利点です。

答えられる範囲で質問いつでも受け付けます。
cosmo-cleaner@za.pial.jp

2009年10月8日木曜日

第15回 配列① FizzBuzz

お題:
FizzBuzzプログラムを作る。
①数を1からカウントしていく
②カウントする上限を尋ねる
③3の倍数の時、「Fizz」と表示
④5の倍数の時、「Buzz」と表示
⑤3と5の倍数の時、「FizzBuzz」と表示

プログラム実行例:

image

必須事項:
・配列を利用する事

ヒント:
・まず、配列をたくさん用意して、3の倍数、5の倍数、3と5の倍数、それ以外に分類します
・実行例は改行しましたが、あってもなくてもいいです
・配列に関しては第11回の予備知識を参考にしてください

解答は10月10日に掲載します。それまでにプログラムを作成し、
・プログラム文
・その実行ファイル
をメールに添付して以下のアドレスに送ってください。

解答、質問はこちらまで
cosmo-cleaner@za.pial.jp

---------------------------------------------------------------

解答例

1

2
3

4
5

6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

#include <stdio.h>

int main () {
    int a[1000],i,n,k;

    puts("いくつまでfizzbuzzを行いますか?");
    printf("n=");    scanf("%d",&n);

    for(i=0;i<=n;i++){
        a[i]=0;
    }
    for(i=1;3*i<=n;i++){
        a[3*i]=1;
    }
    for(i=1;5*i<=n;i++){
        a[5*i]=2;
    }
    for(i=1;3*5*i<=n;i++){
        a[3*5*i]=3;
    }

    k=1;
    for(i=1;i<=n;i++){
        if(a[i] == 0 )
            printf("%d ",i);
        else if (a[i] == 1)
            printf("fizz ");
        else if (a[i] == 2)
            printf("buzz ");
        else if (a[i] == 3)
            printf("fizzbuzz ");

       if (i == 10*k) {
            printf("\n");
            k++;
        }
    }
}

実行例は上と同じです。

解説

今回使った変数とその役割

a[1000]
i
n
k
数字の属性を記憶する変数
カウントアップする数字そのもの、または倍数処理に利用
カウントアップする数字の上限
数字が10個並んだら改行するための変数

このプログラムは、数字と配列を対応させて、配列に数字の属性を印していきます。
例えば、数字の7なら配列a[7]に7の属性を印します。

この印付けを行っているのが6から17行目の命令です。
まず、a[0]からa[n]までの配列に0をとりあえず入れていきます
次に、3の倍数の配列に1を入れていきます。
次に、5の倍数の配列に2を入れていきます。
最後に、3と5の倍数の配列に3を入れていきます。
つまり、
0の印が付いた数字はただの数、
1の印が付いた数字は3の倍数、
2の印が付いた数字は5の倍数、
3の印が付いた数字は3と5の倍数、
という事になります。
印をどんどん上書きしていきます。

赤いif文で数字ごとの印を判別してfizz,buzz,fizzbuzzを表示させています。
青いif文は改行用です。iをカウントアップして10の倍数に至った時に、改行を入れます。見やすくするために入れました。

答えられる範囲で質問いつでも受け付けます。
cosmo-cleaner@za.pial.jp