文字列から整数に変換するプログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
lighthouse
記事: 2
登録日時: 11年前

文字列から整数に変換するプログラムについて

#1

投稿記事 by lighthouse » 11年前

はじめまして、C言語の勉強をしています。

例えば”136854329876000”のように文字列(文字数は特に制限なし,unsigned char,NULL終端)として与えられたを数字を
整数に変換していき、unsigned long の最大値:4294967295の何倍か?、また余りがいくらか?を計算したいと考えています。

unsigned long times;  /*unsigned longの最大値の何倍か*/
unsigned long remain; /*余り*/

例①:文字列”65536”の場合

 times = 0;
 remain = 65536

例②:文字列”6442450946”の場合

 times = 1;
 remain = 2147483651

のような感じで算出したいのですが、どのように計算すれば良いのかがわからず困っています。
ご教授いただけないでしょうか?

1の位から順に数値に変換していって....と考えたのですが
オーバーフローしてしまう場合にどのように処理を続ければ良いものかと悩んでおります…

void testcode(unsigned char *ptr)
{
unsigned long tmp=0, number=0;
unsigned long total;
unsigned long i;
unsigned long count=0;
unsigned str_len;
unsigned char *ptr2;

str_len = strlen((char*)ptr);
ptr2 = ptr+(str_len -1); /*1の位のポインタに移動*/

for(tmp = 0; ('0' <= *ptr2) && (*ptr2 <= '9') ; ptr2--)
{ /*1の位から順に数値に変換していく*/
  number = (*ptr2-'0');
for(i=0; i<count; i++)
{
number *= 10;
}
tmp += number;

if(seisuu <= tmp)
{
seisuu += number;
count++;

   if(count==str_len){
break;
}
} else {
/*overflow*/
    :
    :
}
}
 :
 :
}

説明が分かり憎いようでしたら申し訳ありませんが、
どうぞ宜しくお願い致します。

box
記事: 2002
登録日時: 14年前

Re: 文字列から整数に変換するプログラムについて

#2

投稿記事 by box » 11年前

lighthouse さんが書きました: 例えば”136854329876000”のように文字列(文字数は特に制限なし,unsigned char,NULL終端)として与えられたを数字を
整数に変換していき、unsigned long の最大値:4294967295の何倍か?、また余りがいくらか?を計算したいと考えています。
問題のサイズを小さくしてみてはどうでしょうか。
例えば、整数123456を1024で割ったときの商(120)とあまり(576)をどのように求めていくか、等々。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

box
記事: 2002
登録日時: 14年前

Re: 文字列から整数に変換するプログラムについて

#3

投稿記事 by box » 11年前

unsigned logの最大値の場合に適用できるかどうかはわかりませんが、
123456 ÷ 1024 = 120 ... 576
は、例えばこんな風に求めることができます。
割られる数(123456)の左端から一桁ずつ整数を作り、
1234になった時点で初めて0以外の商が立ちます。
1234 ÷ 1024 = 1 ... 210
次にとなりの'5'を加味して割り算すると、割られる数(12345)が前(1234)の10倍+5なので、
商とあまりもそうなります。
12345 ÷ 1024 = 10 ... (2100 + 5)
ここで、あまりの2105は割る数(1024)より大きいので、その一部を商へ繰り込むことができます。
2105 ÷ 1024 = 2 ... 57
より、
12345 ÷ 1024 = 10 ... (2100 + 5)
は、正しくは
12345 ÷ 1024 = 12 ... 57
となりの'6'を加味して割り算すると、割られる数(123456)が前(12345)の10倍+6なので、
商とあまりもそうなります。
123456 ÷ 1024 = 120 ... (570 + 6)
576は1024に満たないので、商へ繰り込むことはできません。
よって、
123456 ÷ 1024 = 120 ... 576
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

白い時空
記事: 18
登録日時: 14年前
住所: 埼玉県さいたま市

Re: 文字列から整数に変換するプログラムについて

#4

投稿記事 by 白い時空 » 11年前

そもそも、この問題は入力がunsigned longの数値範囲に収まらないので、直接数値に変換するのは望ましく無いと思うのですが‥。

文字列のまま数値計算を行うのが正しいかもしれません。
この問題の場合は引き算と大小比較の関数を作ればなんとかなると思います。

かずま

Re: 文字列から整数に変換するプログラムについて

#5

投稿記事 by かずま » 11年前

lighthouse さんが書きました:1の位から順に数値に変換していって....と考えたのですが
割り算は上の桁からするものです。
小学校の算数で筆算、習いましたよね。

コード:

#include <stdio.h>

unsigned long div(const char *x, char *q)
{
    unsigned long long a = 0;
    const unsigned long b = 4294967295ul;
    int c, f = 0;
    while (*x) {
        a = a * 10 + *x++ - '0';
        c = a / b;
        if (f || c) *q++ = c + '0', f = 1;
        a %= b;
    }
    if (!f) *q++ = '0';
    *q = '\0';
    return a;
}

void proc(const char *x)
{
    char q[1000];
    unsigned long r = div(x, q);
    printf("\n%s\ntimes = %s\nremain = %lu\n", x, q, r);
}

int main(void)
{
    proc("65536");
    proc("6442450946");
    proc("123456789012345678901234567890");
    return 0;
}
実行結果

コード:


65536
times = 0
remain = 65536

6442450946
times = 1
remain = 2147483651

123456789012345678901234567890
times = 28744523655877030118
remain = 2694577080

lighthouse
記事: 2
登録日時: 11年前

Re: 文字列から整数に変換するプログラムについて

#6

投稿記事 by lighthouse » 11年前

皆さん、夜遅くにも関わらず素早い返信ありがとうございました。

ご教授いただいたコードを参考に、コーディングの勉強を進めて行けそうです。

また行き詰まった時には、お世話になるかと思いますが宜しくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る