『新・明解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);
}

コメント

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

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

 


書籍情報



Copyright (C) 2016 "HYOGOKURUMI" All Rights Reserved./「来未炳吾・平極ルミ・HYOGOKURUMI」の発達障害考察を主とした全ての発信は、相互不干渉など特別な約束をした者達を除き、どなたでもご活用できます。ただし著作権は放棄しておりません。あしからずご了承ください。詳細は著作権に関するガイドラインをご一読ください。/「HYOGOKURUMI.site」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。