はじめまして、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*/
:
:
}
}
:
:
}
説明が分かり憎いようでしたら申し訳ありませんが、
どうぞ宜しくお願い致します。
文字列から整数に変換するプログラムについて
Re: 文字列から整数に変換するプログラムについて
問題のサイズを小さくしてみてはどうでしょうか。lighthouse さんが書きました: 例えば”136854329876000”のように文字列(文字数は特に制限なし,unsigned char,NULL終端)として与えられたを数字を
整数に変換していき、unsigned long の最大値:4294967295の何倍か?、また余りがいくらか?を計算したいと考えています。
例えば、整数123456を1024で割ったときの商(120)とあまり(576)をどのように求めていくか、等々。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
Re: 文字列から整数に変換するプログラムについて
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
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
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
Re: 文字列から整数に変換するプログラムについて
そもそも、この問題は入力がunsigned longの数値範囲に収まらないので、直接数値に変換するのは望ましく無いと思うのですが‥。
文字列のまま数値計算を行うのが正しいかもしれません。
この問題の場合は引き算と大小比較の関数を作ればなんとかなると思います。
文字列のまま数値計算を行うのが正しいかもしれません。
この問題の場合は引き算と大小比較の関数を作ればなんとかなると思います。
Re: 文字列から整数に変換するプログラムについて
割り算は上の桁からするものです。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;
}
-
- 記事: 2
- 登録日時: 11年前
Re: 文字列から整数に変換するプログラムについて
皆さん、夜遅くにも関わらず素早い返信ありがとうございました。
ご教授いただいたコードを参考に、コーディングの勉強を進めて行けそうです。
また行き詰まった時には、お世話になるかと思いますが宜しくお願いします。
ご教授いただいたコードを参考に、コーディングの勉強を進めて行けそうです。
また行き詰まった時には、お世話になるかと思いますが宜しくお願いします。