atoi関数を自作してみる

前回の記事でatoi関数という関数が出てきました。

これくらいなら自作できそうだと思ったので作ってみることにしました。

int myatoi(char *str) {
    int num = 0;
    
    while(*str != '\0'){
        num += *str - 48;
        num *= 10;
        str++;
    }
    
    num /= 10;
    
    return num;
}

int main () {
    
    printf("%d\n",myatoi("123"));
    printf("%d\n",myatoi("9"));
    printf("%d\n",myatoi("0"));
    printf("%d\n",myatoi("4500"));
    
    return 0;
}

できました。

文字列の"0"〜"9"の値は文字コード上でが48〜57で、連続してるので48を引けば数値に変換できるということになります。

なので48で引きつつ、元の値を10倍していけば桁が上がっていくので辻褄が合います。

ただしループを抜けた時点では一つ桁が多いので10で割ってあげると数値化の完成ですね。

ただエラーに関しては何も考慮してないので"A"とかの文字列を渡すと変なことになるもしれません。

なので一応48から57までの数値以外の文字列が渡されたらそこで終了するように変更してみました。

int myatoi(char *str) {
    int num = 0;
    
    while(*str != '\0'){
        if ( *str < 48 || *str > 57 ) {
            break;
        }
        num += *str - 48;
        num *= 10;
        str++;
    }
    
    num /= 10;
    
    return num;
}

と、ここまで書いててatoiの仕様を改めて確認したところ+や-といった符号もちゃんと変換してくれるということだったのでそれにも対応してみました。

int myatoi(char *str) {
    int num = 0;
    int type = 0;
    
    // 先頭に+付いてたら無視する
    if ( *str == '+' ) {
        str++;
    }
    // 先頭に-付いてたらtypeフラグを立てておく
    else if ( *str == '-' ) {
        type = 1;
        str++;
    }
    
    while(*str != '\0'){
        // 0〜9以外の文字列ならそこで終了
        if ( *str < 48 || *str > 57 ) {
            break;
        }
        num += *str - 48;
        num *= 10;
        str++;
    }
    
    num /= 10;
    
    // -符号が付いていたら0から引くことで負の値に変換する
    if ( type ) {
        num = 0 - num;
    }
    
    return num;
}

int main () {
    
    printf("%d\n",myatoi("123"));
    printf("%d\n",myatoi("9"));
    printf("%d\n",myatoi("0"));
    printf("%d\n",myatoi("4500"));
    printf("%d\n",myatoi("43a"));
    printf("%d\n",myatoi("+50"));
    printf("%d\n",myatoi("-943"));
    
    return 0;
}
$ main
123
9
0
4500
43
50
-943

理解を深めるためにコメントも入れてみました。

うまく変換できてるようですね。

書き方は色々あると思うので他にどんな変換方法があるのか知りたいところです。