![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамический массив типа Record [D6, WinXP]
Pavelkq © (2004-07-01 13:01:00)Здравствуйте! Есть задача создать массив кривой структуры:
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.
Может быть реализовать эту структуру в другом типе. Например в баз данных?
Sandman25 (2004-07-01 15:20:00) [21][23] Pavelkq (01.07.04 15:19)
>Включил Range checking и точно по Range checking error вылетел.
И что, до сих пор неясно, как исправить?
Pavelkq (2004-07-01 15:19:00) [22][21] Включил Range checking и точно по Range checking error вылетел.
[22] Вверху в типах явно указаноIndex : array of LongInt; // его адрес
R (2004-07-01 15:05:00) [23]Пример не рабочий хотя полный,
надо было упростить в один обработчик
Base.SIndex[LemI].Index-это что за тип?
Sandman25 (2004-07-01 14:58:00) [24][19] Pavelkq (01.07.04 14:49)
Включите Range checking на Project-Options-Compiler
DieHard (2004-07-01 14:55:00) [25]По идее, падать должно на следующей строчке:
Base.SIndex[LemI].Word[ WordI]:=Indexes[i1].Word;
Base.SIndex[LemI].Index[ WordI]:=Indexes[i1].Index;
Pavelkq (2004-07-01 14:49:00) [26][9] Да, есть недочеты. Но не в этом суть проблемы. Почему
SetLength(Base.SIndex[LemI].Word,WordI);проходит, аSetLength(Base.SIndex[LemI].Index,WordI);умирает?
Я, кстати, пробовал сделать тип для Index:String, а дальше поюзать IntToStr. Тогда WirdI доростала до 5.
Тимохов (2004-07-01 14:47:00) [27]
> Pavelkq (01.07.04 14:19) [15]
это значит адрес возникновения ошибки.
место ошибки можно найти search\find error.
надо скомпилиться.
Sandman25 (2004-07-01 14:43:00) [28][9]
Pavelkq (2004-07-01 14:42:00) [29]
For LemI:=0 to Base.Sum - 1 doне помогло. Я же говорю, ошибка возникает при LemI=0 и WordI=4.
Pavelkq (2004-07-01 14:19:00) [30]Может и для Пушкина, но я его на форуме не встречал. Может кто разъяснит, что это значит?
romeo (2004-07-01 14:18:00) [31]
SetLength(Base.SIndex,Base.Sum);// Оно же равно количеству строк таблицы
For LemI:=0 to Base.Sum - 1do
Pavelkq (2004-07-01 14:17:00) [32]R, я хотел бы создать клас, но что это и с чем его едят? Ничего более простого, чем я сделал, представить не могу:-(
Мне нужно будет эту всю кучу сохранять в файл. Позже читать и сравнивать... Как лучше сделать? Может БД поюзать?
Digitman (2004-07-01 14:14:00) [33]
> 'access violation at 0x00401c79
вот эта информация 0x00401c79, она для Пушкина, конечно же, не для тебя
Pavelkq (2004-07-01 14:13:00) [34]Продолжение:
// Моя вставка
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.
Pavelkq (2004-07-01 14:12:00) [35]Только не смейтись, я в Дельфях всего месяц:
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;
Продолжение следует...
Sandman25 (2004-07-01 14:12:00) [36][8] romeo (01.07.04 14:08)
Точнее, автор "забыл" что динамические массивы индексируются, начиная с 0
romeo (2004-07-01 14:08:00) [37]
> И вот при WordI=4 на выполнении SetLength(Base.SIndex[N].Index,WordI);
> вылетает непонятная ошибка
Видимо у тебя нет члена массива Base.SIndex[N].Index с индексом 'N'
Sandman25 (2004-07-01 13:56:00) [38]Это потому что KakoyToInteger=4.
R (2004-07-01 13:55:00) [39]Покажи рабочий код без вяких ....
Пример в обработчике кнопки
Pavelkq (2004-07-01 13:53:00) [40]Ну... она просто непонятная. Вот:
Project Project1.exe faulted with message: 'access violation at 0x00401c79: write of address 0x00000001'. Process Stoped. Use Step or Run to continue.
... и еще окошко CPU.