C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Преобразование числа в прописную строку
laifik
  Отправлено: 03.11.2003, 13:11


Дежурный стрелочник

Группа: Участник
Сообщений: 70



Подскажите, пожалуйста, как преобразовать число
42 500 459 в строку с прописными буквами (сорок два миллиона пятьсот тысяч четыреста пятьдесят девять)? sad.gif
Nimble
Отправлено: 03.11.2003, 16:40


Дежурный стрелочник

Группа: Участник
Сообщений: 34



В инете полно и лучших реализаций этого алгоритма, но этот я писал сам, когда столкнулся с такой же проблеммой. Правда писал на Делфях, но думаю переделать на Билдер вообще не проблемма.

CODE

function Tdm.NumToStr(i: Integer; isTsnd: Boolean): AnsiString;
var
s, d, e: Integer;
begin
s:=(i mod 1000) div 100;
d:=(i mod 100) div 10;
if (d>=2) then
e:=i mod 10
else
e:=i mod 20;

case s of
1: Result:='Сто ';
2: Result:='Двести ';
3: Result:='Триста ';
4: Result:='Четыреста ';
5: Result:='Пятьсот ';
6: Result:='Шестьсот ';
7: Result:='Семьсот ';
8: Result:='Восемьсот ';
9: Result:='Девятьсот ';
end;

case d of
1: if (e=0) or (e=10) then Result:=Result+'Десять ';
2: Result:=Result+'Двадцать ';
3: Result:=Result+'Тридцать ';
4: Result:=Result+'Сорок ';
5: Result:=Result+'Пятьдесят ';
6: Result:=Result+'Шестьдесят ';
7: Result:=Result+'Семдесят ';
8: Result:=Result+'Восемдесят ';
9: Result:=Result+'Девяносто ';
end;

case e of
1: if isTsnd then Result:=Result+'Одна '
else Result:=Result+'Один ';
2: if isTsnd then Result:=Result+'Две '
else Result:=Result+'Два ';
3: Result:=Result+'Три ';
4: Result:=Result+'Четыре ';
5: Result:=Result+'Пять ';
6: Result:=Result+'Шесть ';
7: Result:=Result+'Семь ';
8: Result:=Result+'Восемь ';
9: Result:=Result+'Девять ';
11: Result:=Result+'Одинадцать ';
12: Result:=Result+'Двенадцать ';
13: Result:=Result+'Тринадцать ';
14: Result:=Result+'Четырнадцать ';
15: Result:=Result+'Пятнадцать ';
16: Result:=Result+'Шестнадцать ';
17: Result:=Result+'Семнадцать ';
18: Result:=Result+'Восемнадцать ';
19: Result:=Result+'Девятнадцать ';
end;
end;

//==============================================================================

function Tdm.ToMoney(Value: Real; Fractional, Rub: Boolean): AnsiString;
var
iInt, md, ml, ts, ed, kp, i: Int64;

begin
iInt:=Trunc(Int(Value));

md:=(iInt mod 1000000000000) div 1000000000;
ml:=(iInt mod 1000000000) div 1000000;
ts:=(iInt mod 1000000) div 1000;
ed:=(iInt mod 1000);
kp:=Round(Frac(Value)*100+0.001);

if (iInt=0) then
if Rub then Result:='Ноль Рублей '
else Result:='Ноль Долларов ';

if (ed<>0) then
begin
if ((ed mod 100)>10) and ((ed mod 100)<20) then i:=ed mod 20
else i:=ed mod 10;
case i of
1: if Rub then Result:=NumToStr(ed, false)+'Рубль '
else Result:=NumToStr(ed, false)+'Доллар ';
2, 3, 4: if Rub then Result:=NumToStr(ed, false)+'Рубля '
else Result:=NumToStr(ed, false)+'Доллара ';
else if Rub then Result:=NumToStr(ed, false)+'Рублей '
else Result:=NumToStr(ed, false)+'Долларов ';
end;
end;

if ts<>0 then
begin
if ((ts mod 100)>10) and ((ts mod 100)<20) then i:=ts mod 20
else i:=ts mod 10;
case i of
1: Result:=NumToStr(ts, true)+'Тысяча '+Result;
2, 3, 4: Result:=NumToStr(ts, true)+'Тысячи '+Result;
else Result:=NumToStr(ts, true)+'Тысяч '+Result;
end;
if (ed=0) then
if Rub then Result:=Result+'Рублей '
else Result:=Result+'Долларов ';
end;

if ml<>0 then
begin
if ((ml mod 100)>10) and ((ml mod 100)<20) then i:=ml mod 20
else i:=ml mod 10;
case i of
1: Result:=NumToStr(ml, false)+'Миллион '+Result;
2, 3, 4: Result:=NumToStr(ml, false)+'Миллиона '+Result;
else Result:=NumToStr(ml, false)+'Миллионов '+Result;
end;
if (ed=0) and (ts=0) then
if Rub then Result:=Result+'Рублей '
else Result:=Result+'Долларов ';
end;

if md<>0 then
begin
if ((md mod 100)>10) and ((md mod 100)<20) then i:=md mod 20
else i:=md mod 10;
case i of
1: Result:=NumToStr(md, false)+'Миллиард '+Result;
2, 3, 4: Result:=NumToStr(md, false)+'Миллиарда '+Result;
else Result:=NumToStr(md, false)+'Миллиардов '+Result;
end;
if (ed=0) and (ts=0) and (ml=0) then
if Rub then Result:=Result+'Рублей '
else Result:=Result+'Долларов ';
end;

if Fractional then
begin
if kp=0 then
begin
if Rub then Result:=Result+'Ноль Копеек.'
else Result:=Result+'Ноль Центов.'
end
else
begin
if ((kp mod 100)>10) and ((kp mod 100)<20) then i:=kp mod 20
else i:=kp mod 10;
if Rub then
case i of
1: Result:=Result+NumToStr(kp, true)+'Копейка.';
2, 3, 4: Result:=Result+NumToStr(kp, true)+'Копейки.';
else Result:=Result+NumToStr(kp, true)+'Копеек.';
end
else
case i of
1: Result:=Result+NumToStr(kp, false)+'Цент.';
2, 3, 4: Result:=Result+NumToStr(kp, false)+'Цента.';
else Result:=Result+NumToStr(kp, false)+'Центов.';
end
end;
end;

Result:=TrimRight(Result);
end;

//==============================================================================

function Tdm.ToNumber(Value: Real): AnsiString;
var
iInt, md, ml, ts, ed: Int64;

begin
iInt:=Trunc(Int(Value));

md:=(iInt mod 1000000000000) div 1000000000;
ml:=(iInt mod 1000000000) div 1000000;
ts:=(iInt mod 1000000) div 1000;
ed:=(iInt mod 1000);

Result:=TrimRight(NumToStr(md, false)+NumToStr(ml, false)+
NumToStr(ts, true)+NumToStr(ed, false));
end;

//==============================================================================


Может не самый лучший алгоритм но 100% рабочий smile.gif

Отредактировано Nimble — 03/11/2003, 17:44
Nimble
Отправлено: 03.11.2003, 22:14


Дежурный стрелочник

Группа: Участник
Сообщений: 34



В принципе вот вариант попроще, без всяких рублей, копеек и т.д. Просто преобразование числа (целого) в строку на Билдере

CODE

AnsiString NumToStr_999(int i, bool rp)
{
 int s=(i%1000)/100, d=(i%100)/10, e;

 if (d<2)
   e=i%20;
 else
   e=i%10;

 AnsiString One="Один ", Two="Два ";

 if (rp)
 {
   One="Одна ";
   Two="Две ";
 }

 AnsiString sstr[10]={"", "Сто ", "Двести ", "Триста ", "Четыреста ",
   "Пятьсот ", "Щестьсот ", "Семьсот ", "Восемьсот ", "Девятьсот "},
   dstr[10]={"", "", "Двадцать ", "Тридцать ", "Сорок ", "Пятьдесят ",
   "Щестьдесят ", "Семьдесят ", "Восемьдесят ", "Девяносто "},
   estr[20]={"", One, Two, "Три ", "Четыре ", "Пять ", "Щесть ",
   "Семь ", "Восемь ", "Девять ", "Десять ", "Одинадцать ", "Двенадцать ",
   "Тринадцать ", "Четырнадцать ", "Пятнадцать ", "Шестнадцать ",
   "Семнадцать ", "Восемнадцать ", "Девятнадцать "};

 return sstr[s]+dstr[d]+estr[e];
}
//---------------------------------------------------------------------------

AnsiString NumToStr(double Value)
{
 AnsiString pstr[5][3]={{"Триллион ", "Триллиона ", "Триллионов "},
   {"Миллиард ", "Миллиарда ", "Миллиардов "}, {"Миллион ", "Миллиона ",
   "Миллионов "}, {"Тысяча ", "Тысячи ", "Тысяч "}, {"", "", ""}}, res;

 __int64 iValue=floorl(Value), n=1000000000000000;

 for (int i=0; i<5; i++)
 {
   int m=(iValue%n)/(n/1000), t=2;
   n/=1000;

   if (!(m%100>10&&m%100<20))
     switch (m%10)
     {
       case 1: t=0;
         break;
       case 2:
       case 3:
       case 4: t=1;
     }

   if (m!=0)
     res=res+NumToStr_999(m, i==3)+pstr[i][t];
 }

 return TrimRight(res);
}
//---------------------------------------------------------------------------


Надеюсь пригодится smile.gif
** laifik
Отправлено: 04.11.2003, 10:25


Не зарегистрирован







Мне придется еще Вас немного помучить. Внимательно просмотрела код. Но не поняла, в каком месте цепляется поле с числом. И как это будет выглядеть, если прописать событие по кнопке — при нажатии на нее число преобразуется в строковую переменную и выводится в Edit. Извините, что многого хочу, но трудно разбираться в куске чужого кода, тем долее, что он не совсем простой. sad.gif
Nimble
Отправлено: 04.11.2003, 10:34


Дежурный стрелочник

Группа: Участник
Сообщений: 34



Да ничего страшного smile.gif На то он и форум smile.gif
Две процедуры которые я написал вставляешь в исходники (думаю разберешся куда).
Затем число содержащееся в переменной i нужно перевести в строку и результат поместить в Edit1. Делаем так:
CODE

Edit1->Text=NumToStr(i);

Вот и всё smile.gif

Да еще, для функции floorl требуется включить в исходник math.h
Ну эт так на всякий случай smile.gif

Отредактировано Nimble — 04/11/2003, 11:45
** laifik
Отправлено: 04.11.2003, 10:54


Не зарегистрирован







Спасибо большое. Мне уже все ясно. Я когда вопрос отправила, меня озарило, что это же ФУНКЦИЯ, и понятно, как ее цеплять.
Вопрос считаю закрытым. Еще раз спасибо, Вы мне очень помогли.
Полезная вещь- форум! smile.gif

Вернуться в Вопросы программирования в C++Builder