Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.07.08;
Скачать: CL | DM;

Вниз

Зависание программы при выходе из метода моего класса   Найти похожие ветки 

 
logslava   (2007-05-09 14:15) [0]

Всех с праздником Победы!

Пишу класс, который выдает в случайном порядке числа от 1 до задаваемого MaxValue. В массиве UsedValues храню те цифры, которые уже были выданы, и при выдаче нового проверяю, чтобы не повторялись выдаваемые значения. В коде ниже оставил самые основные методы. Ошибка почему-то возникает при выходе из процедуры GetNextValue;

Сам класс (урезанный)


type
   TRandomer = class
       constructor Create(lMaxValue: Integer);

   private
       MaxValue: Integer;
       UsedValues: array of Integer;

       function  ValueIsUsed(Value: Integer): Boolean;
       procedure ResetUsedValues;
       
   public
       function  GetNextValue: Integer;
       
   end;
   

implementation

uses Math;

constructor TRandomer.Create(lMaxValue: Integer);
begin
   inherited Create;
   
   Self.MaxValue := lMaxValue;
   Randomize;

   // инициализация массива UsedValues
   SetLength(UsedValues, MaxValue);
   ResetUsedValues;
end;

function TRandomer.ValueIsUsed(Value: Integer): Boolean;
var i: Integer;
begin
   Result := False;

   for i:=1 to MaxValue do begin
       if UsedValues[i] = Value then begin
           Result := True;
           Break;
       end;
   end;
end;

procedure TRandomer.ResetUsedValues;
var i: Integer;
begin
   for i:=1 to MaxValue do begin
       UsedValues[i] := 0;
   end;
end;

function TRandomer.GetNextValue: Integer;
var Res: Integer;         // переменная для формирования результата
   Iteration: Integer;   // сигн. метка выхода из цикла - отражает количество уже отработанных чисел
begin
   Iteration := 0;

   repeat
       Res := RandomRange(1, MaxValue);
       Inc(Iteration);
   until {будет найдено не использ значение или будут пересмотрены все значения}
         (not ValueIsUsed(Res))or(Iteration=MaxValue);

   Result := Res;
end;

end.


Вызывающий код


var Randomer: TRandomer;
    testInt: Integer;
...
Randomer := TRandomer.Create(10);
testInt := Randomer.GetNextValue;

ShowMessage(IntToStr(testInt)); // сюда даже не приходит, зависает на выходе из предыдущей процедуры



Подскажите, пожалста, в чем моя ошибка?


 
{RASkov} ©   (2007-05-09 14:26) [1]

> [0] logslava   (09.05.07 14:15)
> for i:=1 to MaxValue do begin
     if UsedValues[i] = ....

Вот она ошибка...
SetLength(UsedValues, MaxValue);
установит нижнюю границу в 0.., ну а верхнюю сам понимаешь в MaxValue-1.
Т.е. у тебя в цикле просматриваются столько же элементов сколько и их всего в массиве, но индекс идет с +1 к текущему.


 
{RASkov} ©   (2007-05-09 14:27) [2]

> Т.е. у тебя в цикле просматриваются столько же элементов сколько и их всего в массиве, но индекс идет с +1 к текущему.

Криво сказал, но думаю суть понята.... :)


 
logslava   (2007-05-09 14:47) [3]

Конечно! Глупая ошибка! Спасибо огромное, еще раз с празником!


 
default ©   (2007-05-09 15:07) [4]

у тебя очень неэффективный алгоритм

делают обычно так
есть, например, массив чисел 1..N(массив нумеруется тут с единицы)

выбирается первое число через Random(N)+1(это позиция выбираемого числа в массива)
после этого это первое число меняется местами с последним
второе число гененируется как Randim(N-1)+1
далее меняется это второе число местами с предпоследним
третье число генерируется как Random(N-2)+1
потом меняется местами оно с предпредпоследним
и тд


 
Rial ©   (2007-05-09 15:27) [5]

1. >  Self.MaxValue := lMaxValue;
Опасный момент...

2. > for i:=1 to MaxValue do begin
заменить на
for i:=0 to MaxValue - 1 do begin

3. Вызов Randomize в конструкторе класса
вообще можно считать ошибкой в данном случае.
А если такой класс будет не один ?!

4. В методе GetNextValue есть лишняя переменная.

5. Что будешь делать, когда не будет хватать
размеров массива ?

6.
>   for i:=1 to MaxValue do begin
>       UsedValues[i] := 0;
>   end;

Лучше используй ZeroMemory() .

7. А почему конструктор не в public ?


 
{RASkov} ©   (2007-05-09 17:17) [6]

> [5] Rial ©   (09.05.07 15:27)

> 1. >  Self.MaxValue := lMaxValue;
> Опасный момент...

Нисколько.... Self все равно неявно подставиться.

> 7. А почему конструктор не в public ?

конструктор published. Будет доступен...., но у меня впринципе тот же вопрос ;)

> 3. Вызов Randomize в конструкторе класса
> вообще можно считать ошибкой в данном случае.
> А если такой класс будет не один ?!

А что страшного может произойти?


 
Rial ©   (2007-05-09 17:35) [7]

1.
> [6] {RASkov} ©   (09.05.07 17:17)
> Нисколько.... Self все равно неявно подставиться.

Просто с таких мелочей начинаются другие
подобные ошибки. Которые уже действительно ошибки,
а не опасные места.
Например что то вроде этого:
Var
   Form1 : TForm1;
constructor TForm1.Create;
begin
...
Form1.Width:=200;
end;

2.
> А что страшного может произойти?

Генератор случаных чисел нужно инициализировать
один раз за время выполнения программы.
А иначе- последтсвия нетрудно проверить самому.


 
{RASkov} ©   (2007-05-09 17:45) [8]

> [7] Rial ©   (09.05.07 17:35)
> Var
>   Form1 : TForm1;
> constructor TForm1.Create;
> begin
> ...
> Form1.Width:=200;
> end;

Вот здесь согласен...

> Генератор случаных чисел нужно инициализировать
> один раз за время выполнения программы.
> А иначе- последтсвия нетрудно проверить самому.

Вот, чесслово расскажи, что может быть плохого... Нет, я не придираюсь, хочу узнать, так как криминала, с этим связанного, не наблюдал..
Вообще, как говориться - достаточно - одного раза вызывать в программе, но ни как не про ограничение кол-во раз вызовов.


 
{RASkov} ©   (2007-05-09 17:48) [9]

> Просто с таких мелочей начинаются другие
> подобные ошибки. Которые уже действительно ошибки,
> а не опасные места.

Ошибки, в данном случае, нет.... все зависит от программера и его алгоритма программы, а вот тон/стиль программирования - плохой.


 
Rial ©   (2007-05-09 17:54) [10]

> [8] {RASkov} ©   (09.05.07 17:45)

Извини, в данным случае я могу быть и не прав.
Были как то пару раз глюки, связанные
с многочисленной инициализацией.
Сейчас проверил - их нет. Если смогу восстановить
ситуацию полностью - покажу пример. :)
Просто лучше порой перестраховаться.



Страницы: 1 вся ветка

Текущий архив: 2007.07.08;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.019 c
2-1181811128
kukuikar
2007-06-14 12:52
2007.07.08
Как работать с редактором формул MS Word из своей программы


2-1181482114
golik
2007-06-10 17:28
2007.07.08
экспорт в Excel!!!!!!!!!!!!!


2-1181835250
Bullfrog
2007-06-14 19:34
2007.07.08
edit


15-1181381873
ZeroDivide
2007-06-09 13:37
2007.07.08
COM-порт на новом железе


2-1181734221
antid
2007-06-13 15:30
2007.07.08
использование mousedown