На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Выдает сообщение об ошибках как исправить?
    У меня есть массив где присутствует 20 элементов. У некоторых значения empty. Я создаю новый массив куда заносятся элементы из старого массива за исключением empty.

    Допустим новый массив будет называться tmpItem. Формирования нового массива будет срабатывать при нажатии кнопки Button1, чтобы вывести результат и посмотреть содержимое tmpItem я использую Memo1 и Button2.

    Код работает записываются и выводятся данные как надо, но я столкнулась с такой проблемой как ошибки. Вот что происходит при записи и чтении массива.
    Button1 – запись массива tmpItem.
    Цитата
    Access violation at address 00403EA8 in module 'Project2.exe'. White of address 00406ACB.

    Button2 – чтение массива tmpItem.
    Цитата
    Access violation at address 00403E88 in module 'Project2.exe'. Read of address 00000046

    Как исправить?

    Вот мой код:
    ExpandedWrap disabled
      unit Unit1;
       
      interface
       
      uses
        Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
        Dialogs, StdCtrls;
       
      type
        TForm1 = class(TForm)
          Button1: TButton;
          Button2: TButton;
          Memo1: TMemo;
          procedure Button1Click(Sender: TObject);
          procedure Button2Click(Sender: TObject);
        private
          { Private declarations }
        public
          { Public declarations }
        end;
       
      var
       
        Form1: TForm1;
        Item1: Array[0..19] of String = ('Thread','empty','Stick','Doorknob','Loupe','empty','Ring',
        'Crown','Vase','empty','Book','empty','Salver','empty','Handbell','Cigarcase','Lantern','Card','Candy',
        'Whisk');
        tmpItem:Array of String;
      implementation
       
      {$R *.dfm}
       
      procedure TForm1.Button1Click(Sender: TObject);
      var i,j,k,jj:Integer;
      begin
      j:=0;
      for i:=0 to Length(Item1) do
      begin
       if Item1[i]<>'empty' then
       begin
        j:=j+1;
       
       end;
      end;
      setLength(tmpItem, j-1);
       
      //ShowMessage(IntToStr(Length(Item1)));
      //ShowMessage(IntToStr(Length(tmpItem)));
       
      jj:=0;
      for k:=0 to Length(Item1) do
      begin
        if Item1[k]<>'empty' then
        begin
          tmpItem[jj]:=Item1[k];
          jj:=jj+1;
        end;
       
      end;
       
       
       
      end;
       
      procedure TForm1.Button2Click(Sender: TObject);
      var i:Integer;
      begin
      Memo1.Clear;
      for i:=0 to Length(tmpItem) do
      begin
        Memo1.Lines.Add(tmpItem[i])
      end;
      end;
       
      end.
      Потому что Length(tmpItem) возвращает не последний индекс массива, а его длину. У тебя в цикле в последней итерации происходит выход за пределы массива со всеми вытекающими
      Используй high(tmpItem) для получения максимального индекса массива. Кроме того, нахрена два цикла, приучайся сразу писать нормальный код, за плохой, будут бить по рукам.

      ExpandedWrap disabled
        procedure TForm1.Button1Click(Sender: TObject);
        var i,j:Integer;
        begin
          j:=1;
          for i:=low(Item1) to high(Item1) do
            if Item1[i]<>'empty' then begin
              setLength(tmpItem, j);
              tmpItem[j-1]:=Item1[i];
              inc(j);
            end;
        end;
         
        procedure TForm1.Button2Click(Sender: TObject);
        var i:Integer;
        begin
          Memo1.Clear;
          for i:=low(tmpItem) to high(tmpItem) do Memo1.Lines.Add(tmpItem[i]);
        end;
      Сообщение отредактировано: Gonarh -
        Gonarh, здравствуйте я тут сделала перемешивание объектов основного массива и добавление первых пяти случайных элементов во второй массив. У меня опять получилось два цикла. Подскажите можно как-нибудь также записать в один цикл перемешивание и добавление как в предыдущем примере.
        ExpandedWrap disabled
          unit Unit1;
           
          interface
           
          uses
            Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
            Dialogs, StdCtrls, Math;
           
          type
            TForm1 = class(TForm)
              Button1: TButton;
              Memo1: TMemo;
              procedure Button1Click(Sender: TObject);
              procedure FormCreate(Sender: TObject);
            private
              { Private declarations }
            public
              { Public declarations }
            end;
           
          var
            Form1: TForm1;
            slot1:Array of String;
            Item1: Array[0..19] of String = ('Thread','Goblet','Stick','Doorknob','Loupe','Statuette','Ring',
            'Crown','Vase','Gripsack','Book','Glove','Salver','Brush','Handbell','Cigarcase','Lantern','Card','Candy',
            'Whisk');
            
            arr:Array of String;
          implementation
           
          {$R *.dfm}
             //Шпаргалка
          // до ближайшего большего целого:
          //A := Ceil(15.15); // A = 16
          //В := Ceil(15.95); // В = 16
           
          // до ближайшего меньшего целого:
          //A := Floor(15.15); // A = 15
          //В := Floor(15.95); // В = 15
           
          // по математическим правилам до ближайшего целого:
          //A := Round(15.15); // A = 15
          //B := Round(15.95); // B = 16
          //C := Round(15.5); // C = 16
          //D := Round(15.4999); // D = 15
           
          // отбрасывание дробной части
          //A := Trunc(15.15); // A = 15
          //В := Trunc(15.95); // В = 15
           
           
          procedure TForm1.Button1Click(Sender: TObject);
          var
           i, j,k: Integer;
            s: string;
          begin
            SetLength(slot1, 5);
            
            Memo1.Clear;
            for i := High(Item1) downto 0 do
            begin
              j := Random(i + 1);
              s := Item1[i];
              Item1[i] := Item1[j];
              Item1[j] := s;
              
            end;
           
            for k:=0 to High(slot1) do
            begin
               slot1[k]:=Item1[k];
               Memo1.Lines.Add(slot1[k])
            end;
          end;
           
          procedure TForm1.FormCreate(Sender: TObject);
          begin
          Randomize;
          end;
           
          end.
          Нет там перемешивания, есть перезатирание. Второй массив участвует только в выводе, а третий вообще не используется.
            ExpandedWrap disabled
              procedure TForm1.Button1Click(Sender: TObject);
              var
                i,j: Integer;
                e1,e2: Integer; //for each index
                s: string; //bufstr
              begin
                SetLength(slot1, 5);
               
                j:=1;
               
                Memo1.Clear;
               
                for i := High(Item1) downto 0 do
                begin
                e1:=random(High(Item1)+1);  //random number in group 0..19
                e2:=random(High(Item1)+1);  //random number in group 0..19
               
                  s := Item1[e1];
                  Item1[e1] := Item1[e2];
                  Item1[e2] := s;
               
                 if j in [1..5] then
                              begin
                 slot1[j-1]:=Item1[i];  //Get current Item
                 Memo1.Lines.Add( intTostr(j)+') '+Item1[i])  //Add to memo1 "to see it"
                              end;
                 inc(j);
                end;
               
               
              end;


            May be like this ...

            ExpandedWrap disabled
              procedure TForm1.Button1Click(Sender: TObject);
              var
               i, j,k: Integer;
                s: string;
              begin
                SetLength(slot1, 5);
               
                Memo1.Clear;
                k:=-1;
                for i := High(Item1) downto 0 do
                begin
                  j := Random(i + 1);
                  s := Item1[i];
                  Item1[i] := Item1[j];
                  Item1[j] := s;
                  inc(k);
                  slot1[k]:=Item1[k];
                  Memo1.Lines.Add(slot1[k]);
                  if k = 4  then break
                end;
               
              end;

            :D
            Сообщение отредактировано: RusSun -
              Цитата Gonarh
              Кроме того, нахрена два цикла, приучайся сразу писать нормальный код, за плохой, будут бить по рукам.
              ExpandedWrap disabled
                procedure TForm1.Button1Click(Sender: TObject);
                var
                  i,j:Integer;
                begin
                // Циклическое изменение длины массива тоже не лучший вариант кода, порождающий не нужное
                // большое количество копирований элементов массива в массив большей длины
                  SetLength(tmpItem, Length(Item1)); // Предполагаем, что нет в Item1 элементов empty
                  j:=Low(tmpItem); // Для простоты работы с индексами стоит использовать Low и High
                  for i:=Low(Item1) to High(Item1) do
                    if Item1[i]<>'empty' then
                    begin
                      tmpItem[j] := Item1[i];
                      inc(j);
                    end;
                // Теперь уменьшим массив до нужного размера. Эта операция не должна породить операцию копирования
                // Усечение блока до меньшего размера не требует копирования элементов в новый блок
                // Даже если в реализации Delphi копирование элементов и будет, то они не будут выполняться циклически
                  SetLength(tmpItem, j - Low(tmpItem) + 1);
                // Немного математики: x: array [-5 .. 4] of ee;
                //  e0 e1 e2 e3 e4 e5 e6 e7 e8 e9
                //  -5 -4 -3 -2 -1  0  1  2  3  4
                //  Low(x)                      j -> 4 - (-5) + 1 = 10
                end;

              Цитата RusSun
              May be like this ...
              ExpandedWrap disabled
                  for i := High(Item1) downto 0 do
                  begin
                    j := Random(i + 1);
                    s := Item1[i];
                    Item1[i] := Item1[j];
                    Item1[j] := s;
                    inc(k);
                    slot1[k]:=Item1[k]; // Необходимо добавить первые 5, а если при i = 4 функция Random(i + 1) вернет значение 2
                    Memo1.Lines.Add(slot1[k]);
                    if k = 4  then break
                  end;
                end;

              Katerina1993: Для выбора 5 случайных достаточно сделать так
              ExpandedWrap disabled
                procedure TForm1.Button1Click(Sender: TObject);
                var
                  i, j: Integer;
                begin
                  Memo1.Clear;
                  SetLength(slot1, 5);
                  j := Length(Item1);
                  for i := Low(Slot1) to High(Slot1) do
                  begin
                    Slot1[i] := Item1[Random(j - Low(Item1)) + Low(Item1)];
                    Memo1.Lines.Add(Slot[i]);
                  end;
                end;
              Для выбора 5 случайных без повторений
              ExpandedWrap disabled
                procedure TForm1.Button1Click(Sender: TObject);
                var
                  i, j, k, l, m: Integer;
                begin
                  Memo1.Clear;
                  SetLength(slot1, 5);
                  j := Length(Item1);
                // Это преобразование нужно для того случая, когда Low(Item1) <> Low(Slot1)
                // Оно добавлено для демонстрации и в конечном итоге может быть убрано
                // Но! Массив Item1 вы задаете константно и индексы в нем могут отличаться от
                // индексов в динамическом массиве, хотя индексы в динамическом массиве
                // всегда находятся в диапазоне [0 .. Length - 1].
                // В общем виде переход от диапазона индексов [A .. B] к диапазону [C .. D]
                // показан в этом примере. Т.к. у динамического массива Low(Slot1) = 0, то
                // как минимум это значение можно убрать.
                  l := Low(Item1) + Low(Slot1);
                  m := Low(Item1) - Low(Slot1);
                  for i := Low(Slot1) to High(Slot1) do
                  begin
                    k := Random(j - i - l) + l; // Выбор значения из диапазона [Low(Item1) + i .. Length(Item1) - 1]
                    Slot1[i] := Item1[i + k]; // Переставляем это значение в начало массива Item1[i] и сохраняем его в Slot1[i]
                    Item1[i + k + m] := Item1[i + m]; // На следующем проходе цикла это значение не будет затронуто
                    Item1[i + m] := Slot1[i];
                    Memo1.Lines.Add(Slot[i]); // Его сразу можно добавить в Memo1
                  end;
                end;
              Сообщение отредактировано: macomics -
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0422 ]   [ 17 queries used ]   [ Generated: 25.04.24, 07:43 GMT ]