Текущий архив: 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]
> непонятная ошибка
кому непонятная ? тебе непонятная ? что конкретно непонятно в ней ? буквы незнакомые или что ?
← →
R © (2004-07-01 13:34) [2]Вот анализирую я алгоритмы и так много любителей
создавать сложные структуры.
Зачем!
Зачем такой сложный тип.
Ведь все можно сделать гораздо проще и без Type
Ведь сам черт голову сломает при работе с ним.
Так много любителей работать с дин.памятью и другими вещами
усложняющими строение программы(не относится к данной ветке).
← →
Ega23 © (2004-07-01 13:36) [3]И вообще нахрена нужен такой рекорд? Лучше класс создай, с ним проще будет.
← →
R © (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.
← →
R © (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
← →
R © (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