![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Переполнение стека
Defort © (2006-11-30 17:20:00)У меня снова проблема. В процедуре вычисления вычислимых полей у меня происходит переполнение стека. Код выглядит так:
k:=DaysBetween(datemust, datelast);
for i:=1 to k do //ê - êîëè÷åñòâî äíåé ìåæäó äàòîé ôàêòè÷åñêîé äàòû îïëàòû è äàòû îïëàòû ïî ãðàôèêó
DataModule1.ADOTable3DSDesigner3.Value{ïåíè}:=ADOTable3DSDes igner2.AsCurrency{ñóììà ïëàòåæà}+ADOTable3DSDesigner2.AsCurrency{ñóììà ïëàòåæà}*ADOTable1DSDesigner4.AsCurrency{ 4;îýôôèöèåíò ïåíè}; // Ôîðìèðîâàíèå ïîëÿ "Ïåíè": çà êàæäûé äåíü ïðñòîÿ äîáàâëÿåòñÿ ïåíè
DataModule1.ADOTable3DSDesigner5.Value{îñòàòîê ;}:=ADOTable3DSDesigner2.AsCurrency{ñóììà ïëàòåæà}+ADOTable3DSDesigner3.AsCurrency{ïåíè}-ADOTable3DSDesigner7.AsCurrency{ïîñòóïèë î îïëàòû}; // Ôîðìèðîâàíèå ïîëÿ "Îñòàòîê"
if (ADOTable3DSDesigner2.AsCurrency+ADOTable3DSDesigner3.AsCurrency)=ADOTable3DSDesigner5.AsCurrency then
ADOTable3DSDesigner4.Value:=true; //ïîãàøåí: äà
Переполнение происходит на строке
DataModule1.ADOTable3DSDesigner5.Value{îñòàòî ;ê}:=ADOTable3DSDesigner2.AsCurrency{ñóììà ïëàòåæà}+ADOTable3DSDesigner3.AsCurrency{ïåíè}-ADOTable3DSDesigner7.AsCurrency{ïîñòóïèë î îïëàòû}; // Ôîðìèðîâàíèå ïîëÿ "Îñòàòîê"
Не подскажете, в чем ошибка?
Anatoly Podgoretsky (2006-12-02 20:27:00) [1]> Defort (02.12.2006 20:08:17) [17]
Пипол за углом водку пьет, а здесь программисты
Defort (2006-12-02 20:08:00) [2]Пипол! Чево молчите все? (
Defort (2006-12-02 16:13:00) [3]
> Приведи свои попытки, тогда поверю.
>
Ок. Ниже код
procedure TDataModule1.ADOTable3CalcFields(DataSet: TDataSet);
var datelast, datemust: TDateTime;
i, k: word; //счетчик
peni, ending{остаток}: real;
begin
datelast:=DataModule1.ADOTable3DSDesigner8.AsDateTime;
datemust:=DataModule1.ADOTable3DSDesigner.AsDateTime;
if datelast=NULL then datelast:=now;
k:=DaysBetween(datelast, datemust);
for i:=1 to k do //к - количество дней между датой фактической даты оплаты и даты оплаты по графику
peni{пени}:=ADOTable3DSDesigner2.AsCurrency{сумма платежа}+ADOTable3DSDesigner2.AsCurrency{сумма платежа}*ADOTable1DSDesigner4.AsCurrency{коэффициент пени}; // Формирование поля "Пени": за каждый день прстоя добавляется пени
DataModule1.ADOTable3DSDesigner3.Value:=peni;
ending{остаток}:=ADOTable3DSDesigner2.AsCurrency{сумма платежа}+peni-ADOTable3DSDesigner7.AsCurrency{поступило оплаты}; // Формирование поля "Остаток"
DataModule1.ADOTable3DSDesigner5.Value:=ending;
if (ADOTable3DSDesigner2.AsCurrency+peni)=ending then
ADOTable3DSDesigner4.Value:=true; //погашен: да
end;
Я трассировал, у меня процедура выполняется по кругу. (это ведб и есть рекурсия).
Да, и еще проблема: в цикл for программа не входит. видимо я снова перемудрил что то с датами. Может ктонить прочекатЬ?
ЮЮ (2006-12-02 08:56:00) [4]Вычислимое поле в этом обработчике можно использовать только слева в операторе присваивания. Любое другое использование приведет к необходимости его вычисления и рекурсивному вазовы этого же обработчика
DataModule1. ADOTable3DSDesigner3. Value{пени}:=ADOTable3DSDesigner2.AsCurre ncy{сумма платежа}+ADOTable3DSDesigner2.AsCurrency{сумма платежа}*ADOTable1DSDesigner4.AsCurrency{коэффициент пени}; // Формирование поля "Пени": за каждый день прстоя добавляется пени
peni:=DataModule1. ADOTable3DSDesigner3.AsCurrency;
DataModule1. ADOTable3DSDesigner5.Value{остаток}:=ADOTable3DSDesigner2.AsCurrency {сумма платежа}+peni-ADOTable3DSDesigner7.AsCurrency{поступило оплаты}; // Формирование поля "Остаток"
if (ADOTable3DSDesigner2.AsCurrency+peni)= ADOTable3DSDesigner5.AsCurrencythen
ADOTable3DSDesigner4.Value:=true; //погашен: да
сначала посчитай peni, а потом присваивай полю
аналогично с плем ADOTable3DSDesigner5.AsCurrency
ЮЮ (2006-12-02 08:47:00) [5]
> вот исходный код:
Исходный код, по определению, приведет к переполнению стека. См.[10]
> Посчет использования промежуточных переменных - я это пытался
> делать. Только толку не слишком.
Пока имеем от тебя только то, что имеем, а именно, код, по определению, приводящий к переполнению стека. Приведи свои попытки, тогда поверю.
Defort (2006-12-01 20:16:00) [6]2Пипл
Посчет копирования понял, вот исходный код:
k:=DaysBetween(datemust, datelast);
for i:=1 to k do //к - количество дней между датой фактической даты оплаты и даты оплаты по графику
DataModule1.ADOTable3DSDesigner3.Value{пени}:=ADOTable3DSDesigner2.AsCurre ncy{сумма платежа}+ADOTable3DSDesigner2.AsCurrency{сумма платежа}*ADOTable1DSDesigner4.AsCurrency{коэффициент пени}; // Формирование поля "Пени": за каждый день прстоя добавляется пени
peni:=DataModule1.ADOTable3DSDesigner3.AsCurrency;
DataModule1.ADOTable3DSDesigner5.Value{остаток}:=ADOTable3DSDesigner2.AsCurrency {сумма платежа}+peni-ADOTable3DSDesigner7.AsCurrency{поступило оплаты}; // Формирование поля "Остаток"
if (ADOTable3DSDesigner2.AsCurrency+peni)=ADOTable3DSDesigner5.AsCurrency then
ADOTable3DSDesigner4.Value:=true; //погашен: да
Посчет использования промежуточных переменных - я это пытался делать. Только толку не слишком. Если честно я и сам в этих дизайнерах запутался - может что и пропустил.
Desdechado (2006-12-01 11:03:00) [7]Gydvin © (01.12.06 08:56) [11]
Все гораздо проще - перед Ctrl-C переключиться на русскую раскладку клавы.
Gydvin (2006-12-01 08:56:00) [8][0] сохраняешь проект, юниту открываешь блокнотом, и отуда уже копируешь, тогда кАменты отображаются нормально
ЮЮ (2006-12-01 05:25:00) [9]
DataModule1.ADOTable3DSDesigner5.Value :=
ADOTable3DSDesigner2.AsCurrency + ADOTable3DSDesigner3.AsCurrency - ADOTable3DSDesigner7.AsCurrency;
исходя из этого иожно предположить, что Designer5 вычислимое поле
тогда использование его в выражении приводит к очередному вызову обработчика
if (ADOTable3DSDesigner2.AsCurrency+ADOTable3DSDesigner3.AsCurrency) = ADOTable3DSDesigner5.AsCurrencythen
ADOTable3DSDesigner4.Value:=true;
Решение:
1) заменить на
if ADOTable3DSDesigner7.AsCurrency = 0 then //если Designer7 не вычислимое :)
2) вычисления хранить в промежуточных переменных:
s :=ADOTable3DSDesigner2.AsCurrency + ADOTable3DSDesigner3.AsCurrency - ADOTable3DSDesigner7.AsCurrency;
DataModule1.ADOTable3DSDesigner5.Value := s;
if (ADOTable3DSDesigner2.AsCurrency+ADOTable3DSDesigner3.AsCurrency) = sthen
Anatoly Podgoretsky (2006-12-01 00:43:00) [10]> Defort (30.11.2006 23:02:08) [8]
> //e - eiee?anoai aiae ia?ao aaoe oaeoe?aneie aaou iieaou e aau iieaou ii a?aoeeo
Что за муа?
Defort (2006-11-30 23:02:00) [11]Попытался избавиться от рекурсии, заменив в длинном выражении всчитываемою ранее значение отдельной переменной, но все равно трабла сохранилась(
for i:=1 to k do //ê - êîëè÷åñòâî äíåé ìåæäó äàòîé ôàêòè÷åñêîé äàòû îïëàòû è äàòû îïëàòû ïî ãðàôèêó
DataModule1.ADOTable3DSDesigner3.Value{ïåíè}:=ADOTable3DSDes igner2.AsCurrency{ñóììà ïëàòåæà}+ADOTable3DSDesigner2.AsCurrency{ñóììà ïëàòåæà}*ADOTable1DSDesigner4.AsCurrency{ 4;îýôôèöèåíò ïåíè}; // Ôîðìèðîâàíèå ïîëÿ "Ïåíè": çà êàæäûé äåíü ïðñòîÿ äîáàâëÿåòñÿ ïåíè
peni:=DataModule1.ADOTable3DSDesigner3.AsCurrency;
DataModule1.ADOTable3DSDesigner5.Value{îñòàòîê ;}:=ADOTable3DSDesigner2.AsCurrency{ñóììà ïëàòåæà}+peni-ADOTable3DSDesigner7.AsCurrency{ïîñòóïèë î îïëàòû}; // Ôîðìèðîâàíèå ïîëÿ "Îñòàòîê"
if (ADOTable3DSDesigner2.AsCurrency+peni)=ADOTable3DSDesigner5.AsCurrency then
ADOTable3DSDesigner4.Value:=true; //ïîãàøåí: äà
Defort (2006-11-30 21:27:00) [12]
> Поставь точку останова на свое строке и протрассируй.
Делал. Там реально рекурсия. Но блин, по другому я не знаю как сделать. Я в раздумьях!
Джо (2006-11-30 21:23:00) [13]Поставь точку останова на свое строке и протрассируй.
Defort (2006-11-30 21:08:00) [14]
> Твой код читать невозможно, о чем ты говоришь? :)
Читать невозможно толька камменты ;) для этого я отпостил второй пост!
Джо (2006-11-30 21:04:00) [15]> [3] Defort © (30.11.06 21:02)
> Кстати может быть (( А на примере моего кода непонятно,
> как это исправить?
Твой код читать невозможно, о чем ты говоришь? :)
Defort (2006-11-30 21:02:00) [16]Кстати может быть (( А на примере моего кода непонятно, как это исправить?
Desdechado (2006-11-30 17:26:00) [17]наверняка в рекурсию ввалился
вычисление одногополя ведет к вычислению другого, а от него снова вычисляется первое
Defort (2006-11-30 17:23:00) [18]Что то комменты там криво отображаются, поэтому пишу что делает код:
к - количество дней между фактической датой платежа и датой по графику
Для каждого просроченного дня добавляется пени, равное сумме платежа*коэффициент пени
после этого идет формирования поля остаток: сумма платежа+сумма пени-заплачено - тут и происходит переполнение