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

Вниз

Динамический массив типа Record   Найти похожие ветки 

 
Pavelkq   (2004-07-01 13:01) [0]

Здравствуйте! Есть задача создать массив кривой структуры:
1. Первое поле содержит всего одно число типа longint.
2.Второе поле это динамический массив такого типа:
2.1. Тип string
2.2. Тип longint
2.3. Тип динамический массив типа string
2.4. Тип динамический массив типа LingInt
 Делаю все, как по часам:

// Создание структуры индексной таблицы (2)
       Type
         TIndex=record
           Lema : string[50];// Пункт 2.1.
           ColLem: LongInt;  // Пункт 2.2.
           Word : array of string[50];// Пункт 2.3.
           Index : array of LongInt;  // Пункт 2.4.
         end;
// Создание массива индекса с полем для пункта 1.
       Type TBase=Record
               Sum:LongInt; // Вот он, пункт 1.
               SIndex:array of TIndex;// Пункт 2 целиком.
          end;
// Назначаем переменную Base вышеуказанного типа.
       var Base:TBase;

 Все компилируется отлично!
Далее начинаю работать с этой таблицей.
Base.Sum:=KakoyToInteger;
SetLength(Base.SIndex,Base.Sum);
...
WordI:=0;// Тип Integer
...
WordI:=WordI+1;
SetLength(Base.SIndex[N].Word,WordI);
SetLength(Base.SIndex[N].Index,WordI);
Base.SIndex[LemI].Word[N]:=Words;
Base.SIndex[LemI].Index[N]:=Int;
...

И вот при WordI=4 на выполнении SetLength(Base.SIndex[N].Index,WordI); вылетает непонятная ошибка и код в CPU.
Может быть реализовать эту структуру в другом типе. Например в баз данных?


 
Digitman ©   (2004-07-01 13:06) [1]


> непонятная ошибка


кому непонятная ? тебе непонятная ? что конкретно непонятно в ней ? буквы незнакомые или что ?


 
©   (2004-07-01 13:34) [2]

Вот анализирую я алгоритмы и так много любителей
создавать сложные структуры.
Зачем!

Зачем такой сложный тип.
Ведь все можно сделать гораздо проще и без Type
Ведь сам черт голову сломает при работе с ним.
Так много любителей работать с дин.памятью и другими вещами
усложняющими строение программы(не относится к данной ветке).


 
Ega23 ©   (2004-07-01 13:36) [3]

И вообще нахрена нужен такой рекорд? Лучше класс создай, с ним проще будет.


 
©   (2004-07-01 13:49) [4]

>Лучше класс создай, с ним проще будет.

Вот это верно.


 
Pavelkq   (2004-07-01 13:53) [5]

Ну... она просто непонятная. Вот:
Project Project1.exe faulted with message: "access violation at 0x00401c79: write of address 0x00000001". Process Stoped. Use Step or Run to continue.
 ... и еще окошко CPU.


 
©   (2004-07-01 13:55) [6]

Покажи рабочий  код без вяких ....

Пример в обработчике кнопки


 
Sandman25 ©   (2004-07-01 13:56) [7]

Это потому что KakoyToInteger=4.


 
romeo   (2004-07-01 14:08) [8]


> И вот при WordI=4 на выполнении SetLength(Base.SIndex[N].Index,WordI);
> вылетает непонятная ошибка

Видимо у тебя нет члена массива Base.SIndex[N].Index с индексом "N"


 
Sandman25 ©   (2004-07-01 14:12) [9]

[8] romeo   (01.07.04 14:08)

Точнее, автор "забыл" что динамические массивы индексируются, начиная с 0


 
Pavelkq   (2004-07-01 14:12) [10]

Только не смейтись, я в Дельфях всего месяц:

unit Word3_;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, FileCtrl, ExtCtrls, ComObj, ComCtrls, SndKey32,
 ActnList, WordItemCounter;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   ProgressBar1: TProgressBar;
   Button2: TButton;
   OpenDialog1: TOpenDialog;
   Label1: TLabel;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure FormActivate(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

// * * * CONST * * * //
const  MAX_WORD_LEN=32; //максимальная длина входного слова
const  MAX_PARA_COUNT=200; //максимальное количество слов в парадигме

// * * * (1.0) Структура определяющая одно слово и его грамматические характеристики   * * *  //
     type TWstr=record
       anword: array[0..MAX_WORD_LEN-1] of char; //словоформа , для совместимости с С++ используется PChar
       cid:byte;     //постоянная грамматическая характеристика
       vid:byte;    //переменная грамматическая характеристика
       virt:char;  //потенциальность словоформы обозначается знаком ~
       para:byte; //внутренняя системная переменная - явно не используется
       end;

// * * * (1.1) Общая структура используемая для добавления или считывания парадигмы или слова * * *//
     type TWs=record
       inlex:array[0..MAX_PARA_COUNT-1] of TWstr;
       count:integer;  //количество
       end;
     pTWs=^TWs; //pointer

// * * * (2.0) Cтруктура определяющая идентификатор UIN 1-го слова * * *//
     type Tid=record
       lnk:longword; //Уникальный идентификатор леммы (максимально 20 бит)
       en:byte;    // Идентификатор окончания (8 бит) Лемма всегда имеет ed:=0
       end;

// * * * (2.1) Общая структура идентификаторов * * *//
     type Tids=record
       ids:array[0..MAX_PARA_COUNT-1] of Tid;
       count:integer;
       end;
       pTids=^Tids; //pointer
       pInt=^integer;

//Массив переменных типа TMember, который мы будем
//использовать для хранения нашего индекса
    type TempIndex=record
       Word : string[50];
       Lema : string[50];
       Index : Integer;
    end;
    var  Indexes : array of TempIndex;
    i1,i2: longword;
    Path: string;
 {
//***********************************************************
// Создание структуры индексной таблицы                   //*
       Type                                              //*
         TIndex=record                                   //*
           Lema : string[50];// лема                     //*
           ColLem: LongInt;  // количество одинаковых лем /*
           Word : array of string[50];// само слово      //*
           Index : array of LongInt;  // его адрес       //*
         end;                                            //*
// Создание массива индекса с полем для количества слов   //*
       Type TBase=Record                                 //*
               Sum:LongInt; // общее кол. слов в файле   //*
               SIndex:array of TIndex;// строки таблицы  //*
          end;                                           //*
// Назначаем грандиозной таблицей переменную Base         //*
       var Base:TBase;                                   //*
//***********************************************************
}
var
 Form1: TForm1;
 function InitMcr: Integer; stdcall; external "MCR.DLL" name "InitMcr";
 function LoadMcr(const path:PChar): Integer; stdcall; external "MCR.DLL" name "LoadMcr";
 function SaveMcr(const path:PChar): Integer; stdcall; external "MCR.DLL" name "SaveMcr";
 function FindWID(const s:PChar; p:pTids): Integer; stdcall; external "MCR.DLL" name "FindWID";
 function GetBId(const lnk:integer; en:byte;gh_only,all:boolean;p:pTWs): Integer; stdcall; external "MCR.DLL" name "GetBid";
 function FreeSpace(a1,a2,a3:pInt): Integer; stdcall; external "MCR.DLL" name "FreeSpace";
 function RODict: boolean; stdcall; external "MCR.DLL" name "ReadOnlyDict";
 function GetVer: PChar; stdcall; external "MCR.DLL" name "Ver";
 function AddPara(outdata: pTWs): integer; stdcall; external "MCR.DLL" name "AddParadigma";
 function CTS(const constid:byte):PChar; stdcall; external "MCR.DLL" name "ConstIdToStr";
 function VTS(const constid,varid:byte):PChar; stdcall; external "MCR.DLL" name "VarIdToStr";

implementation

uses Unit2;
{$R *.dfm}
{ 1. Change MS Word properties via OLE }

procedure say(s:string);
begin
Form1.Memo1.Lines.Add(s);
end;

procedure close1(); external "C:\BIBLIO\word+lema6\rr.dll" name "close";

procedure TForm1.Button2Click(Sender: TObject);
begin
Form2.StringGrid1.Cells[0,0]:="Лема";
Form2.StringGrid1.Cells[1,0]:="Слово";
Form2.StringGrid1.Cells[2,0]:="Номер";
Form1.Visible:=False;
Form2.Visible:=True;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
Memo1.Clear;
path:=GetCurrentDir;
end;

procedure Reading (Document:OLEVariant);
var t1,t2,Temp:string;
TSL: TStringList;
begin
TSL:=TStringList.Create;
Temp:=Document.range;//Копирование всего файла в Temp
say (DateTimeToStr(Now));

   TSL.Text:=WordItem(Temp);//Процедура разбивки
   i2:=TSL.Count; SetLength(Indexes,i2);

Form1.ProgressBar1.Max:=i2;
Form1.ProgressBar1.Position:=0;
       for i1:=1 to i2 do
       begin
       Indexes[i1].Word:=TSL[i1-1];
       Temp:=TSL[i1-1];
       Form1.ProgressBar1.Position:=i1;
       end;
say (DateTimeToStr(Now));
end;

procedure Lema ();
var
         Te:String;
         rc:integer;
         dir:string;
         s,s1:string;
         count,i:integer;
         Uid :Tids;
         WData:TWs;
         cstr,vstr:array[byte] of char;
         h: HWND;
         cl:Boolean;
 Rlst: LongBool;
 StartUpInfo: TStartUpInfo;
 ProcessInfo: TProcessInformation;
 Error: integer;
 ExitCode: Cardinal;
begin
//Hint: правильно укажите путь к файлу
dir:=path+"\zal.mcr";
InitMcr;

Продолжение следует...


 
Pavelkq   (2004-07-01 14:13) [11]

Продолжение:
// Моя вставка
begin
 FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0);
 with StartUpInfo do
 begin
   cb := SizeOf(TStartUpInfo);
   dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
   wShowWindow := SW_SHOWNORMAL;
 end;
 Rlst := CreateProcess(nil,
 "rr.res",
 nil,
 nil,
 false,
 NORMAL_PRIORITY_CLASS,
 nil,
 nil,
 StartUpInfo,
 ProcessInfo);
rc:=LoadMcr(PChar(dir));
 if Rlst then
 with ProcessInfo do begin
   WaitForInputIdle(hProcess, INFINITE); // ждем завершения инициализации
   WaitforSingleObject(ProcessInfo.hProcess, INFINITE); // ждем завершения процесса
   GetExitCodeProcess(ProcessInfo.hProcess, ExitCode); // получаем код завершения
   CloseHandle(hThread); // закрываем дескриптор процесса
   CloseHandle(hProcess); // закрываем дескриптор потока
 end
else Error := GetLastError;
end;
// конец моей вставки

// rc:=LoadMcr(PChar(dir));
if rc<=0 then
begin
ShowMessage("Ошибка загрузки словаря. Код "+IntToStr(rc))
end
else
begin
say("Словарь загружен");
end;
Form1.ProgressBar1.Position:=0;
for i1:=1 to i2 do
// Программа от Димы
      begin
      Form1.ProgressBar1.Position:=i1;
      s:=Indexes[i1].Word;
      count:=FindWID(PChar(s),@Uid);
        if count>0 then
          begin
          rc:=GetBid(uid.ids[0].lnk,uid.ids[0].en,false,false,@WData);
            if rc>=0 then
                begin
                strcopy(cstr,CTS(WData.inlex[0].cid));
                strcopy(vstr,VTS(WData.inlex[0].cid,WData.inlex[0].vid));
                s1:="";
                s1:=StrPas(WData.inlex[0].anword);
                Indexes[i1].Lema:=s1;
                Indexes[i1].Index:=i1;
                end;
          end;
      end;
// Конец программы от Димы
end;

Procedure SubIndex();
var LemI,WordI:integer;
   Fdata: TStringList;
   Temp:String;
Begin
  FData:=TStringList.Create;
For i1:=1 to i2 do
   begin                          //************************
   Fdata.Sorted := true;          // Сортировка лем и
   Fdata.Duplicates := dupIgnore; // удаление дубликатов
   FData.Add(Indexes[i1].Lema);   //************************
   end;

{Temp:="";
For i1:=0 to Fdata.Count-1 do
   begin
   Temp:=Temp+FData.Strings[i1]+" ";
   end;
ShowMessage(Temp);}

Base.Sum:=Fdata.Count-1;         // Количество уникальных лем
SetLength(Base.SIndex,Base.Sum);// Оно же равно количеству строк таблицы
For LemI:=0 to Base.Sum do
 begin
 Base.SIndex[LemI].Lema:=FData.Strings[LemI];
 Temp:=FData.Strings[LemI];
 WordI:=0;
 for i1:=1 to i2 do
    begin
    if Base.SIndex[LemI].Lema=Indexes[i1].Lema then
       begin
       WordI:=WordI+1;
       SetLength(Base.SIndex[LemI].Word,WordI);
       SetLength(Base.SIndex[LemI].Index,WordI);
       Base.SIndex[LemI].Word[WordI]:=Indexes[i1].Word;
       Base.SIndex[LemI].Index[WordI]:=Indexes[i1].Index;
       end;
    end;
 end;

end;

Procedure save();
var F : file of TempIndex;
Begin
Form1.ProgressBar1.Position:=0;
AssignFile(F, path+"\index111.dat");
Rewrite(F);
Indexes[0].Index:=i2;
write (F,Indexes[0]);
for i1:=1 to i2 do
        begin
        Write (F, Indexes[i1]);
        Form1.ProgressBar1.Position:=i1;
        end;
CloseFile(F);
End;

procedure TForm1.Button1Click(Sender: TObject);
const
 wdSaveChanges = $FFFFFFFF;
var
   WordApp: OLEVariant;
   Document: OLEVariant;
   SaveChanges: OleVariant;
   AWordDoc: String;
begin
AWordDoc:="";
OpenDialog1.Execute;
AWordDoc:=OpenDialog1.FileName;
if AWordDoc="" then exit;
ProgressBar1.Visible:=true;
     try
     WordApp := CreateOleObject("Word.Application");
     except
     // Error....
     Exit;
     end;
 try
 Document:=WordApp.Documents.Open(AWordDoc);
      say("Чтение файла...");
      Reading (Document);
  SaveChanges := wdSaveChanges;
  WordApp.Quit(SaveChanges, EmptyParam, EmptyParam);

      say("Лематизация");
      Lema();

      say("Создание индекса");
      SubIndex();

      say("Сохранение результатов");
      //Save ();

      say("Готово!");
 finally
 end;
ProgressBar1.Visible:=False;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var result:Integer;
begin
result:=MessageBox(0,"Удалить индексный файл index.dat?","Завершение программы",MB_YESNOCANCEL);
if result=2 then Action := caNone;
if result=6 then DeleteFile(path+"\index111.dat");
end;

end.


 
Digitman ©   (2004-07-01 14:14) [12]


> "access violation at 0x00401c79


вот эта информация 0x00401c79, она для Пушкина, конечно же, не для тебя


 
Pavelkq   (2004-07-01 14:17) [13]

R, я хотел бы создать клас, но что это и с чем его едят? Ничего более простого, чем я сделал, представить не могу:-(
 Мне нужно будет эту всю кучу сохранять в файл. Позже читать и сравнивать... Как лучше сделать? Может БД поюзать?


 
romeo   (2004-07-01 14:18) [14]

SetLength(Base.SIndex,Base.Sum);// Оно же равно количеству строк таблицы
For LemI:=0 to Base.Sum - 1 do


 
Pavelkq   (2004-07-01 14:19) [15]

Может и для Пушкина, но я его на форуме не встречал. Может кто разъяснит, что это значит?


 
Pavelkq   (2004-07-01 14:42) [16]

For LemI:=0 to Base.Sum - 1 do не помогло. Я же говорю, ошибка возникает при LemI=0 и WordI=4.


 
Sandman25 ©   (2004-07-01 14:43) [17]

[9]


 
Тимохов ©   (2004-07-01 14:47) [18]


> Pavelkq   (01.07.04 14:19) [15]

это значит адрес возникновения ошибки.
место ошибки можно найти search\find error.
надо скомпилиться.


 
Pavelkq   (2004-07-01 14:49) [19]

[9] Да, есть недочеты. Но не в этом суть проблемы. Почему
SetLength(Base.SIndex[LemI].Word,WordI); проходит, а SetLength(Base.SIndex[LemI].Index,WordI); умирает?
Я, кстати, пробовал сделать тип для Index:String, а дальше поюзать IntToStr. Тогда WirdI доростала до 5.


 
DieHard   (2004-07-01 14:55) [20]

По идее, падать должно на следующей строчке:
      Base.SIndex[LemI].Word[WordI]:=Indexes[i1].Word;
      Base.SIndex[LemI].Index[WordI]:=Indexes[i1].Index;


 
Sandman25 ©   (2004-07-01 14:58) [21]

[19] Pavelkq   (01.07.04 14:49)

Включите Range checking на Project-Options-Compiler


 
©   (2004-07-01 15:05) [22]

Пример не рабочий хотя полный,
надо было упростить в один обработчик
Base.SIndex[LemI].Index-это что за тип?


 
Pavelkq   (2004-07-01 15:19) [23]

[21] Включил Range checking и точно по Range checking error вылетел.
[22] Вверху в типах явно указано Index : array of LongInt;  // его адрес


 
Sandman25 ©   (2004-07-01 15:20) [24]

[23] Pavelkq   (01.07.04 15:19)

>Включил Range checking и точно по Range checking error вылетел.

И что, до сих пор неясно, как исправить?


 
Pavelkq   (2004-07-01 15:21) [25]

[20] Почему оно должно падать?
[22] Пример не рабочий из-за того, что используются внешние модули (dll, res, unit...)


 
begin...end ©   (2004-07-01 15:24) [26]


> [25] Pavelkq   (01.07.04 15:21)

Ну ты где-то вышел за границы индексов массива.


 
begin...end ©   (2004-07-01 15:28) [27]

Вот после этого:

> SetLength(Base.SIndex[LemI].Word,WordI);

верхняя граница у индексов массива Word стала WordI - 1.
А вот здесь:

> Base.SIndex[LemI].Word[WordI]:=Indexes[i1].Word;

ты обращаешься к элементу с индексом WordI. А его нету!


 
WondeRu ©   (2004-07-01 15:30) [28]

2Pavelkq   (01.07.04 14:19) [15]

>Может и для Пушкина, но я его на форуме не встречал. Может кто разъяснит, что это значит?

"Project Project1.exe faulted with message: "access violation at 0x00401c79: write of address 0x00000001". Process Stoped. Use Step or Run to continue."

Типичная ошибка Access violation (AV) - нарушение доступа (попытка выполнить неразрешенную операцию с памятью, например, попытка записи в буфер, предназначенный только для чтения, доступ к памяти сверх лимита пространства адресов текущей программы, доступ к запрещенной странице; доступ к странице, резидентно находящейся в памяти, но предназначенной для использования компонентом исполняющей системы (Executive) и т.п.)

Вот... удачи)


 
Pavelkq   (2004-07-01 15:33) [29]

[27] О чем ты говоришь? Это же динамический массив и я его границы задаю непосредственно перед занисением туда данных?

      SetLength(Base.SIndex[LemI].Word,WordI);
      SetLength(Base.SIndex[LemI].Index,WordI);
      Base.SIndex[LemI].Word[WordI]:=Indexes[i1].Word;
      Base.SIndex[LemI].Index[WordI]:=Indexes[i1].Index;

Еще раз поясняю, что ошибка возникает при
      SetLength(Base.SIndex[LemI].Index,WordI);

 Люди, как другим способом можно оформить вышеуказанный массив данных?


 
Sandman25 ©   (2004-07-01 15:38) [30]

[29] Pavelkq   (01.07.04 15:33)

Объясняю.
При SetLength(A, 3) в массиве A появятся 3 элемента:
A[0], A[1] и A[2].
При указании
I := 0;
for J := 0 to do
begin
 I := I + 1;
 A[I] := ... // получаем ошибку, потому что обращения будут к элементам
// A[1], A[2] и A[3].
end;


 
begin...end ©   (2004-07-01 15:38) [31]


> [29] Pavelkq   (01.07.04 15:33)

Я говорю о том, что после

SetLength(Base.SIndex[LemI].Word,WordI)

элемента в массиве Word с индексом WordI у тебя нету. НЕТУ!


 
Igorek ©   (2004-07-01 15:48) [32]

var
 A: array of integer;
 I: Integer;
begin
 SetLength(A, 10);
 for I := Low(A) to High(A)  do
 begin
   A[I] = 0;
 end;


 
Pavelkq   (2004-07-01 15:52) [33]

А как же заполнять массив динамически расширяя его размеры?
Так можно:

For i=0 to 50 do
 begin
 SetLength(A,i);
 A[i]:=i;
 end;

 Поправьте меня, если я ошибаюсь.


 
Sandman25 ©   (2004-07-01 15:53) [34]

Нет. A[i-1].


 
Erik1   (2004-07-01 15:53) [35]

Точнее в масиве SIndex элемента LemI нету. А то говорят всякое.


 
Pavelkq   (2004-07-01 15:57) [36]

[32]Игорек, это пойдет, если заранее известно количество элементов. А в моем случае они обнаруживаются в этом же цикле. Хотя, можно дважды пройтись по всему массиву выяснив сначала его размеры, а потом заполнив...


 
Amoeba ©   (2004-07-01 15:59) [37]


> Pavelkq   (01.07.04 15:57) [36]

О, Господи! Ему гоаорят "брито", а он все твердит, что "сторижено".


 
Igorek ©   (2004-07-01 16:04) [38]


> Pavelkq   (01.07.04 15:57) [36]

Обычно размер массива известен сразу если ты его создаешь и заполняешь в одной процедуре (напр. [33].
А если ты время от времени увеличиваешь массив, то делай так:

SetLength(Mas, Length(Mas) + 1);
Mas[High(Mas)] := ...;


 
PVOzerski ©   (2004-07-01 16:20) [39]

1) Короче, усвой, что указывая размер в SetLength для динамического массива (в отличие от строки, кстати), ты указываешь не номер последнего разрешенного элемента, а число элементов, которое на 1 больше этого номера. Притом, что минимальный разрешенный элемент имеет индекс 0, а не 1.
2) Динамические массивы - вообще дело тонкое, иногда можно сильно проиграть в скорости из-за скрытого перевыделения и копирования блоков памяти. Посмотри класс TList - он эффективнее, хотя и сложнее в использовании. А для самообразования можешь еще поиграть в связные списки.


 
Sandman25 ©   (2004-07-01 16:23) [40]

[39] PVOzerski ©   (01.07.04 16:20)

Не, ну нельзя так однозначно. Если память под динамический массив выделяется лишь один раз, то TList оказывается далеко позади. Особенно, если это array of integer, например.



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

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

Наверх




Память: 0.6 MB
Время: 0.032 c
14-1088247100
vidiv
2004-06-26 14:51
2004.07.18
Вопрос на засыпку


14-1088144458
YurikGL
2004-06-25 10:20
2004.07.18
Во сколько оценить компьютер


3-1088325416
SergP
2004-06-27 12:36
2004.07.18
Проблема с компонентами odac


4-1086351014
fishca
2004-06-04 16:10
2004.07.18
Файлы открытые процессом


1-1089133875
YChak
2004-07-06 21:11
2004.07.18
Динамический массив.