『新・明解C言語 入門編 第2版』演習問題解答例 11ー12

演習11ー12

問: atoi関数、atol関数、atoll関数、atof関数と同じ仕様の関数を作成せよ。

// Ex1112.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <stdio.h>
#include <limits.h>

#define CHARSIZE 128


long long null_bullets(int n)
{
    long long s_bullet = 1;

    if (n > 1) {
        while (n != 1) {
            s_bullet = s_bullet * 10;
            n--;
        }
    }

    return s_bullet;
}

double olignal_atoX(char* ati)
{

    int len1 = strlen(ati);
    int hyphen_c = 0;
    int decimal_c = 0;
    int digit_f = 0;
    int digit_b = 0;
    int digit_s1 = 0;
    int digit_s2 = 0;
    long long isum = 0;
    int tmp_msb = 0;
    long long tmp = 0;
    double dsum = 0;

    // ハイフンチェック
    if (ati[0] == '-') {
        hyphen_c = 1;       //ハイフンがあれば1にする
        *ati++;             //ハイフンがあれば取る
    }
    
    // 改めて小数点チェック()
    int len2 = strlen(ati);
    
    // 小数点チェック
    for (int i = 0; i < len2; i++) {
        if (ati[i] == '.') {
            decimal_c = 1;          //小数点があれば1にする
            digit_f = i;            //小数点があった桁(前から)を保全
            digit_b++;              //総桁数を保全
        }
        else {
            digit_b++;
        }
        digit_s1 = digit_b - digit_f;    //小数点があった桁(後ろから)を保全
    }

    // 小数点より右側の値を左1桁にずらして小数点を潰す
    if (decimal_c == 1) {                   //小数点があれば実行
        digit_s2 = digit_f;              //小数点の位置を保全
        digit_b = digit_b - digit_s2;        //小数点から右側の桁数を取得
        for (int i = 0; i < digit_b; i++) {
            ati[digit_s2] = ati[digit_s2 + 1];
            digit_s2++;
        }
    }
    
    //ここまででハイフンと小数点が取り除かれている。
    //ハイフンの有無と小数点の位置は保全されている。

    //改めて桁数チェック
    int len3 = strlen(ati);
    int cnt = len3;
    
    //文字列を整数に変換
    for (int i = 0; i < len3; i++) {
        tmp_msb = *ati - '0';                             //最上桁のみ取得
        isum = isum + (tmp_msb * null_bullets(cnt--));    //最上桁を持ってヌルバレットへ旅立つ
        *ati++;                                           //次の桁へ
    }
    //ここまでで文字列を数値に変換できた

    // ハイフン付きだった場合、自分で自分を引いて、自分の分身に更に惹かれて同じ値のマイナスをつくる。
    if (hyphen_c == 1) {
        tmp = isum;
        isum = isum - isum;
        isum = isum - tmp;
    }

    //小数点付きだった場合、値を保全した桁数×ゼロバレットで割って小数点をつける
    if (decimal_c == 1) {
        dsum = isum;
        dsum = (dsum / null_bullets(digit_s1));
        
        return dsum;
    }

    return isum;
}

int main(void)
{
    char str[CHARSIZE]       = { 0 };
    char str_atoi[CHARSIZE]  = { 0 };
    char str_atol[CHARSIZE]  = { 0 };
    char str_atoll[CHARSIZE] = { 0 };
    char str_atof[CHARSIZE]  = { 0 };

    //printf("int             : %d 〜 %d\n", INT_MIN, INT_MAX);
    //printf("long            : %ld 〜 %ld\n", LONG_MIN, LONG_MAX);
    //printf("long long       : %lld 〜 %lld\n", LLONG_MIN, LLONG_MAX);
    //printf("double          : %lf 〜 %lf\n", DBL_MIN, DBL_MAX);

    //putchar('\n');

    printf("文字列を入力せよ:");
    scanf("%s", str, 128);
    
    for (int i = 0; i < CHARSIZE; i++) {
        str_atoi[i] = str[i];
    }

    for (int i = 0; i < CHARSIZE; i++) {
        str_atol[i] = str[i];
    }

    for (int i = 0; i < CHARSIZE; i++) {
        str_atoll[i] = str[i];
    }

    for (int i = 0; i < CHARSIZE; i++) {
        str_atof[i] = str[i];
    }


    printf("[atoi]\n");
    printf("atoi(str_atoi)          = %d\n", atoi(str_atoi));
    printf("olignal_atoi(str_atoi)) = %d\n", (int)olignal_atoX(str_atoi));

    putchar('\n');

    printf("[atol]\n");
    printf("atol(str_atol))        = %ld\n", atol(str_atol));
    printf("olignal_atoi(str_atol) = %ld\n", (long)olignal_atoX(str_atol));

    putchar('\n');

    printf("[atoll]\n");
    printf("atoll(str_atoll)        = %lld\n", atoll(str_atoll));
    printf("olignal_atoi(str_atoll) = %lld\n", (long long)olignal_atoX(str_atoll));

    putchar('\n');
    
    printf("[atof]\n");
    printf("atof(str_atof)          = %lf\n", atof(str_atof));
    printf("olignal_atoi(str_atof)  = %lf\n", (double)olignal_atoX(str_atof));
    
    return(0);
}

コメント

 これは今までやった中で一番やりがいがあった問題。楽しかった!
 全章の基本的なことを総動員しなければ書けないコードなのでぜひ自力でやってほしい。

 ちなみに私のコードは全く最適ではなく、動きの視覚化を優先したものなので、どう手をつけていいかわからない方のみ参考にしてください。

 


書籍情報


コメント

タイトルとURLをコピーしました