Cの練習1

いくつか練習になりそうなテーマを考えたのでコーディングしてみる。

フィボナッチ数列

再帰を理解していればわりと簡単。実際にプログラムをループさせたいときってだいたいforかwhileでなかなか再帰を使う機会がないのに、参考書ではやけに目にする。

#include <stdio.h>

int fib(int);

int main() {
    int n;
    scanf("%d", &n); //フィボナッチ数列のn番目の値を求める
    if (n <= 0) {
        printf("invalid value\n");
        main();
    }
    int result = fib(n);
    printf("%d", result);
    return 0;
}

int fib(int x) {
    int tmp;
    switch(x) {
        case 1:
            tmp = 1;
            break;
        case 2:
            tmp = 1;
            break;
        default:
            tmp = fib(x-2) + fib(x-1);
    }
    return tmp;
}
素因数分解
  • for文・while

こっちはなかなか大変だった。慣れてないのもあるかもしれないが、リストを使わないで実装するとなると難しい。(隙あらばリストを使ってたので)
変数とかifの条件分岐はもう少し減らせそうだ。
詰まったらネットで検索しつつ調べていくと、べき乗の演算子が存在しないらしい。今回は自分で実装したけど、n乗の計算をしたい時はライブラリの関数を使うそうな。

C言語/演算子と式 - Wikibooks

を見ると「**」にはまだ何も割り当てられていないのに何の理由で実装されなかったんだろうか。

#include <stdio.h>

int try_div(int, int);
int my_pow(int, int);

int main() {
    //このプログラムは不完全で、素数mを入力すると「m = 」としか出力されないし
    //最後に余計な乗算記号がついてしまう
    int n;
    scanf("%d", &n);
    if (n < 1) {
        printf("invalid value\n");
        main();
    }
    printf("%d = ", n);
    int num; //素数の底
    for (num = 2; num != n; num++){
        if (n % num == 0) {
            int pw = try_div(n, num);
            if (pw != 0) {printf("%d^%d * ", num, pw);}
        }
    }
    return 0;
}

int try_div(int n, int num) {
    int tmp = 2;
    int sup = 1; //素数の冪数
    //最初にnumが素数か確かめる
    while (tmp < num) {
        if (num%tmp == 0) {
            return 0;//numが素数ではなかった
        }
        tmp++;
    }
    //この行に到達しているならnumは素数
    for (; n%my_pow(num, sup) == 0; sup++) {}
    return sup - 1;
}

int my_pow(int base, int exponent) {
    //mathライブラリのpowと違ってfloatを引数に取れない・exponent < 1だと動かない
    int x = 1;
    for (; exponent > 0; exponent--) {
        x *= base;
    }
    return x;
}

次はパスカルの三角形とバブルソートとかにしよう。 パスカルの三角形なんかは2次元配列を使うので慣れるにはいいかもしれない。