Текущий архив: 2004.07.11;
Скачать: CL | DM;
Вниз
Быстрое чтение файла Найти похожие ветки
← →
Кастуся (2004-06-21 22:46) [0]мастера, хелп!
обрабатываю файл "дедовским" методом: построчно читаю данные и со строкой делаю все необходимое.
Но не устраивает скорость. На P-I-133 файл в обрабатывает за . Можно ли увеличить скорость на стадии чтения? (Обработка прочитанной строки оптимизированна до максимума) Я знаю, использовать либо BlockRead либо TFileStream но там надо читать буферами, для этого надо знать где строка заканчивается. А можно как-нибудь построчно читать?
Хотел попробовать сл. код:
Start := Stream.Position;
End := Start;
Repeat
Stream.Read(Buffer^, 1024);
CRPos := FindCR(Buffer^); { где FindCR возвращает 0..1023 для CR,
и 1024, если он не найден}
Inc(End, CRPos);
Until CRPos < 1024;
GetMem(MyPChar, End - Start); { Здесь может быть +-1 -- мне лень сегодня проверять! }
Stream.Seek(Start);
Stream.Read(MyPChar^, End - Start)
но что такое FindCR?
В общем как тут быть. Дело срочное, хелп плиз!!!
← →
Anatoly Podgoretsky © (2004-06-21 23:15) [1]Если не ошибаюсь, то тут два раза чтение из файла того же самого содержимого. Посмотри в сторону текстовыъ файлов и ReadLn
← →
DrPass © (2004-06-21 23:19) [2]
> но что такое FindCR?
Наверняка какая-то самописная функция, которая ищет среди последовательности символов знак возврата каретки.
А после этого файл считывается во второй раз...
← →
RealRascal © (2004-06-21 23:21) [3]Может поможет txtfile:TStringlist;
Чтобы загрузить используй Tstringlist.LoadFromFile()
Потом обращайся к нужной строчке txtfile[i]
← →
Кастуся (2004-06-22 08:40) [4]
> Anatoly Podgoretsky ©
Первоначально и смотрю в сторону ReadLn, но можно быстрее? через TFIleStream или BlockRead?
← →
Anatoly Podgoretsky © (2004-06-22 08:50) [5]Кастуся (22.06.04 08:40) [4]
Выигрываешь немного в скорости чтения, проигрываешь в обработке, придется самому разбирать буфер на строки и не дай бог на составляющии. Текстовые файлы обеспечивают отличный механизм разборки файла и преобразования из буквочек в типы. Но всему свое место, твоя задача нам неизвестна.
Могу предложить, если у тебя текстовый файл, то загнать его целиком в строковую переменную и ее присвоить TStringList.Text возможно это будет быстрее, а то и сразу загрузить в TStringList, по скорости можно выиграть немного, по сравнению с текстовыми файлам, но за счет проигрыша по памяти. Но это хорошо только для текста.
← →
Кастуся (2004-06-22 09:44) [6]С TStringLIst я пробовал - медленнее чем просто readln Использую SetTextBuf Я думаю это помогает?
← →
Serginio666 (2004-06-22 14:10) [7]Посмотри
http://www.1c.hippo.ru/cgi-bin/predownl.cgi?id=2019
Тест на чтения текстовых файлов различными способами. Также исходники объектов для последовательного чтения текстовых файлов
как в прямом так и в обратном направлении TTextReader и TTextBackReader использующие кольцевой буффер размером 64 кб с ограничением на длину строки 64 кб - 3 байта.
← →
BFG9k (2004-06-22 14:45) [8]Паскаль в гробу перевернется после всего этого. CreateFile,SetFilePointer,FileRead,FileWrite,CloseHandle . API функции - лучший друг Delphi-программиста.
← →
Mim1 © (2004-06-22 17:38) [9]
> [8] BFG9k (22.06.04 14:45)
> Паскаль в гробу перевернется после всего этого. CreateFile,SetFilePointer,FileRead,FileWrite,CloseHandle
> . API функции - лучший друг Delphi-программиста.
Ну ну :), я бы сказал лучший враг. Но это субьективно.
Если смотрите в будующее о api лучше забыть.
API приходят и уходят, ЯП остается :)
← →
Кастуся (2004-06-22 17:55) [10]Понимете, вся штука вот в чем: в текстовом файле находится строка-идентификатор, после чего ещё пару строк считывается и они обрабатываются. Т.е. вся фишка в том, чтобы как можно быстрее найти эту заветную строку. Таких блоков может быть много в файле.
Вот смотрел ещё:
http://delphiworld.narod.ru/base/search_text_in_text_file.html
но не могу разобраться. может подскажите?
← →
Anatoly Podgoretsky © (2004-06-22 17:59) [11]Не сортированый список, только перебором
← →
Кастуся (2004-06-22 18:25) [12]серьезно?
← →
Amoeba © (2004-06-22 18:31) [13]
> Кастуся (22.06.04 18:25) [12]
> серьезно?
Совершенно серьезно.
← →
panov © (2004-06-22 18:31) [14]>Кастуся (22.06.04 18:25) [12]
Серьезно.
← →
GrayFace © (2004-06-22 18:37) [15]Искать строку в файле действительно лучше не дедовским способом. Если файл меньше 50 MB (для малых оперативок еще меньше), то можно грузить весь в строку(FileRead или BlockRead) и искать в ней стандартными способами. Если файл огромен, то прийдется немного помучаться.
← →
Serginio666 (2004-06-22 19:13) [16]>>GrayFace ©
Немного ошибаешься. Лучше грузить в блок соизмеримый с размером кэша первого уровня. В отличие от твоего способа, все данные будут лежать в кэше и проход по ним будет быстрее. Что и доказывают тесты в Serginio666 (22.06.04 14:10) [7]
← →
GrayFace © (2004-06-22 19:20) [17]А что такое кэш первого уровня?
← →
Jeer © (2004-06-22 19:33) [18]Который в процессоре и ближе к нему чем к ОЗУ.
← →
Кастуся (2004-06-23 09:08) [19]короче вот что я тет выяснил
путаю я вас тут
львиную долю времени загрузки файла как раз занимет его одновременная обработка!
Может можно как-то подгружать функции в память, чтобы их быстрее вызывать? Вот может посмотрите как можно вот этот код оптимизировать:
AssignFile(F,FileName);
SetTextBuf(f,buf);
Reset(f);
Ln:=FileSize(F);
while not eof(F) do
begin
Readln(F,w);
if Trim(w)="TC" then
begin
Readln(F,W);
rst:=DelSpaces(W);
I:=0;
repeat
inc(i);
Readln(F,W);
w0:=DelSpaces(W);
Bad:=(Length(w0)<>32);
if not Bad then
Bad:=not (LastDelimiter(HexSt,AnsiLowerCase(w0))=32);
k:=0;
if not Bad then
repeat
inc(k);
REAPage.Matr[i,k]:=w0[k];
until (k=32);
until (i=8) or Bad;
if not Bad then
begin
if not Result then Result:=True;
Inc(DataTables[0].CurLen);
for I:=1 to MaxCol do
SetLength(DataTables[0].DataArr[I],DataTables[0].CurLen);
REAInfo.REAPage.ProcessMatr(rst);
end;
end;
Cps:=FilePos(F);
if Ln=0 then MainForm.StBar.Panels.Items[2].GaugeAttrs.Position:=100
else MainForm.StBar.Panels.Items[2].GaugeAttrs.Position:=Round((Cps/Ln)*100);
end;
MainForm.StBar.Panels.Items[1].Text:="";
CloseFile(F);
← →
Anatoly Podgoretsky © (2004-06-23 11:31) [20]Кастуся (23.06.04 09:08) [19]
Функции и так в памяти, всегда, Дельфи не интерпритатор.
← →
Кастуся (2004-06-23 12:33) [21]а так можно как-нибудь увеличить скорость ?
← →
Sandman25 © (2004-06-23 12:39) [22]>а так можно как-нибудь увеличить скорость ?
Не использовать Trim, DelSpaces, LastDelimiter, AnsiLowerCase
Это repeat
inc(k);
REAPage.Matr[i,k]:=w0[k];
until (k=32);
заменить на 1 команду CopyMemory
← →
Кастуся (2004-06-23 15:47) [23]Sandman25 © (23.06.04 12:39) [22]
знац-ца так
AnsiLowerCase отключил
Это repeat
inc(k);
REAPage.Matr[i,k]:=w0[k];
until (k=32);
заменил на 1 команду CopyMemory вот как:
MoveMemory(@REAPage.Matr[i],@w0[1],32);
Скорость впечатляет: файл в 23.8Мб обрабатывает за 46 сек, когда до изменений было 56! Это на моем-то Celerone-533+SDRam-64Mb, а для кого это делается вообще P-I-133 + SD-RAM 16Mb! Так что там разница будет раза в 2 больше. Хотя там такие большие файлы не обрабатывают Макс - ~5Мб
HexSt:="0"+"1"+"2"+"3"+"4"+"5"+"6"+"7"+"8"+"9"+"a"+"b"+"c"+"d"+"e"+"f";
w0:=DelSpaces(W);
Bad:=(Length(w0)<>32);
if not Bad then Bad:=not (LastDelimiter(HexSt,w0)=32);
← →
Sandman25 © (2004-06-23 16:03) [24]LastDelimiter(HexSt,w0)=32
эквивалентно
(Length(w0)=32) and (w0[32] in ["0".."9","a".."f"])
← →
Кастуся (2004-06-23 16:14) [25]мне надо чтобы вся строка состояла из ["0".."9","a".."f"] а не только последняя "буква"(w0[32])! Или я что-то не понимаю?
← →
Sandman25 © (2004-06-23 16:18) [26]Почитайте описание LastDelimiter.
Если захотите проверять каждый символ, скорость чтения файла упадет примерно в 30 раз....
← →
Кастуся (2004-06-23 17:03) [27]Sandman25 © (23.06.04 16:18) [26]
а как тогда быть?
← →
Sandman25 © (2004-06-23 17:04) [28][27] Кастуся (23.06.04 17:03)
От задачи зависит. Если это лабораторная, а не программа управления ядерным реактором, то можно не проверять.
← →
Кастуся (2004-06-23 17:51) [29]
> Sandman25 © (23.06.04 16:18) [26]
Знаешь ли ты английский язык?
Нет?
Вот чт написано в хелпе:
function LastDelimiter(const Delimiters, S: string): Integer;
Returns the byte index in S of the last character that matches any character in the Delimiters AnsiString.
Call LastDelimiter to locate the last delimiter in S. For example, the line
MyIndex := LastDelimiter("\.:","c:\filename.ext");
sets MyIndex to 12.
Перевожу:
function LastDelimiter(const Delimiters, S: string): Integer;
Возвращает индекс последнего символа строки S, который совпадает с любым из символов в строке Delimiters.
Используйте LastDelimiter для определения позиции последнего совпадающего символа. Например, строка
MyIndex := LastDelimiter("\.:","c:\filename.ext");
устанавливает значение MyIndex равным 12.
Даже пример есть, хоть по примеру можно догодацца-то! No comments...
← →
Кастуся (2004-06-23 17:52) [30]
> а не программа управления ядерным реактором,
а если именно эта программа?
← →
Romkin © (2004-06-23 18:09) [31]ЭЭЭ. А нельзя ли получить формальную постановку? А то с кодом как-то разбираться не хочется.
Насколько я понял, тебе парсинг строки сделать надо? Это в общем случае решается конечным автоматом, который просто считывает весь файл непрерывным потоком. Однократно.
Как правило, это быстрее всего. А вот какой автомат должен быть - это надо выбирать...
http://rsdn.ru/article/alg/statemachine.xml
← →
Кастуся (2004-06-23 19:21) [32]Так, вот конкретно. Требуется две вещи:
1) есть ли втроенная процедура удаления из строки всех пробелов? Если нет, то как это можно наибыстрее реализовать? Моя реализация:function DelSpaces(S:String):String;
var
I:Integer;
begin
Result:="";
for I:=1 to Length(S) do
if S[I]<>" " then Result:=Result+S[I];
end;
2) нужна процедура проверки валидности символов в строке, а точнее надо проверить, являются ли все символы в строке "шестнадцатеричными", т.е. принадлежат["0".."9","a".."f"]
. Опять наибыстрым способом. Моя реализация:Bad:=not (LastDelimiter(HexSt,w0)=32);
← →
Romkin © (2004-06-23 19:28) [33]Кастуся (23.06.04 19:21) [32]
1. Фиии.
StringReplace тоже не быстро...
function DelSpaces(const S: String):String;
var
I, k, len:Integer;
begin
len := Length(S);
SetLength(Result, len);
k := 0;
for I := 1 to len do
if S[I]<>" " then
begin
inc(k);
Result[k] := S[I];
end;
SetLength(Result, k);
end;
Думаю, сойдет. Можно и быстрее, но не намного.
2. Если строка не более 16 символов, то
N := IntToStr("$"+S);
Преобразует, если не прет - даст исключение
← →
Romkin © (2004-06-23 19:41) [34]тьфу, StrToInt("$"+S) разумеется
← →
Anatoly Podgoretsky © (2004-06-23 20:13) [35]StrToInt64
← →
Anatoly Podgoretsky © (2004-06-23 20:25) [36]Кастуся (23.06.04 19:21) [32]
Алгоритм очень неэффективный, постоянное перераспределение памяти, алгоритм приведенный Ромкином при определенных условиях даст ускорение на порядки, например если обрабатывать весь громадный файл на один проход, но не на один порядок быстрее. Чем длиннее строка, тем быстрее, зависимость не линейная.
← →
Кастуся (2004-06-23 22:28) [37]> Anatoly Podgoretsky © (23.06.04 20:25) [36]
> Алгоритм очень неэффективный, постоянное перераспределение
> памяти
Это ты про мой?
> алгоритм приведенный Ромкином при определенных условиях
> даст ускорение на порядки
алгоритм удаления пробелов из строки? и при каких условиях
> обрабатывать весь громадный файл на один проход
т.е.?
← →
Кастуся (2004-06-23 22:55) [38]
> Romkin © (23.06.04 19:41) [34]
> Можно и быстрее, но не намного.
Говори как. Для меня очень важна скорость.
> N := StrToInt64("$"+S);
строка 32-х символьная
и при попытке конвертации первой же такой строки возникает ошибка "not a valid integer value" Что делать?
Вот пример строки:
000E190E131002001104294188601618
← →
Anatoly Podgoretsky © (2004-06-23 22:58) [39]Для конвертации такой строки нужен Int128
← →
Fay © (2004-06-24 06:38) [40]2Кастуся (23.06.04 22:28) [37]
Твой способ удаления пробелов в строке ДИКО медленный.
Сравни с [33] на 10000 символах.
← →
Кастуся (2004-06-24 08:42) [41]
> Fay © (24.06.04 06:38) [40]
понимаю, что медленный, скажи как быстрее, чем предложил Romkin!
← →
Кастуся (2004-06-24 08:58) [42]
> Anatoly Podgoretsky © (23.06.04 22:58) [39]
> Для конвертации такой строки нужен Int128
такового типа нет в Дельфи! Как быть?
← →
Fay © (2004-06-24 09:46) [43]2Кастуся (24.06.04 08:58) [42]
Правильно, нет. Но АП и не говорил, что нет - он сказал "нужен"
← →
Fay © (2004-06-24 09:48) [44]2Кастуся (24.06.04 08:42) [41]
Сильно быстрее не получится. Не "стоит выделки".
← →
имя (2004-06-24 09:48) [45]Удалено модератором
← →
Fay © (2004-06-24 09:51) [46]2www.shegeda.by.ru (24.06.04 09:48) [45]
Какой выигрыш?
← →
имя (2004-06-24 09:58) [47]Удалено модератором
← →
имя (2004-06-24 10:00) [48]Удалено модератором
← →
Кастуся (2004-06-24 11:09) [49]
> www.shegeda.by.ru (24.06.04 09:48) [45]
твой алгоритм не работает. Я его в процедуру пихаю:procedure DelSpaces(var S: String);
var
NewLength : integer;
begin
asm
mov edx, s
mov ebx, s
jmp @@NextChar
@@NextChar:
mov al, [ebx]
inc ebx
or al, al
jz @@StrEnd
cmp al, " "
je @@NextChar
@@CopyChar:
mov [edx], al
inc edx
jmp @@NextChar
@@StrEnd:
mov [edx], al
sub edx, s
mov NewLength, edx
end;
SetLength(s,NewLength);
end;
> www.shegeda.by.ru (24.06.04 09:58) [47]
> Это во-первых...
> Во вторых, нужно ли чтение файла?
когда я закомментировал всю обработку строк, а отавил только чтение стандартным методом:while not eof(f) do
readln(f,st);
то мой файл в 8Мб прочитывает за 0.4с. Впечатляет? Так что с этим проблем нету.
А вообще, чего я уже добился с момента начала этой ветки, меня впечатляет! Скорость обработки увеличилась раза в 4-5!!!
← →
Romkin © (2004-06-24 11:21) [50]Не надо беспокоиться, думаю, DelSpaces в моей редакции уже перестала быть узким местом.
Простой пример: допустим, есть программа, и одна функция в ней отнимает 4% времени обработки. Ускорив эту функцию в два раза, вы получите уменьшение времени... всего на 2%.
ЛУчше посмотреть на другие участки программы...
А еще лучше воспользоваться профилировщиком
← →
Fay © (2004-06-24 11:27) [51]2Romkin © (24.06.04 11:21) [50]
К тому же, код [45] не годится для string 8)
← →
Romkin © (2004-06-24 11:28) [52]Кстати, насколько я понял, тебе значение строки не нужно? Тогда StrToInt64, но разбей строку на две половины - как раз влезет.
Может, все-таки скажешь, что у процедуры на входе и что нужно получить на выходе?
← →
Anatoly Podgoretsky © (2004-06-24 11:32) [53]www.shegeda.by.ru (24.06.04 09:48) [45]
Ты диверсант?
← →
имя (2004-06-24 11:46) [54]Удалено модератором
← →
имя (2004-06-24 12:07) [55]Удалено модератором
← →
Fay © (2004-06-24 12:19) [56]2www.shegeda.by.ru (24.06.04 11:46) [54]
Как Вы думаете, для чего Delphi вызывает UniqueStringA?
← →
Anatoly Podgoretsky © (2004-06-24 12:22) [57]www.shegeda.by.ru (24.06.04 11:46) [54]
Так и продолжаешь провоцировать на неприятности в системе?
← →
имя (2004-06-24 12:27) [58]Удалено модератором
← →
Fay © (2004-06-24 12:37) [59]2www.shegeda.by.ru (24.06.04 12:27) [58]
Код скорее "для PChar". Delphi в таком случае лепит вполне пригодный код, хотя на asm-е легко сделать лучше 8).
← →
имя (2004-06-24 12:46) [60]Удалено модератором
← →
Fay © (2004-06-24 12:55) [61]Можно глупый вопрос? А зачем вот такие
FHandle:=0;
штуки?!
← →
имя (2004-06-24 12:59) [62]Удалено модератором
← →
Fay © (2004-06-24 13:06) [63]function TMappedFile.GetIsOpen: boolean;
begin
Result := FHandle <> DWORD(-1);
end;
← →
Fay © (2004-06-24 14:22) [64]Моя версия на основе www.shegeda.by.ru [60]
8)unit MappedFile;
interface
uses
Windows, SysUtils;
type
TMappedFile = class
private
FHandle : DWORD;
FMapping : DWORD;
FSize : DWORD;
FView : PChar;
FActive : Boolean;
FName : string;
procedure SetSize(const Value : DWORD);
procedure SetName(const Value : string);
procedure SetActive(const Value : Boolean);
function GetActive : Boolean;
public
constructor Create;
destructor Destroy; override;
procedure Close;
procedure Open;
property Size : DWORD read FSize write SetSize;
property Data : PChar read FView;
property Active : Boolean read GetActive write SetActive;
property Name : string read FName write SetName;
end;
implementation
constructor TMappedFile.Create;
begin
FHandle := INVALID_HANDLE_VALUE;
FName := "";
end;
destructor TMappedFile.Destroy;
begin
Close;
inherited;
end;
procedure TMappedFile.SetName(const Value : string);
begin
if Active then
raise Exception.Create("Нельзя изменить имя!");
FName := Value;
end;
procedure TMappedFile.SetSize(const Value : DWORD);
begin
if Active then
raise Exception.Create("Нельзя изменить размер!");
FSize := Value;
end;
procedure TMappedFile.SetActive(const Value : Boolean);
var
sz : DWORD;
begin
if FActive = Value then Exit;
if Value then
begin
FHandle := CreateFile(
PChar(FName),
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS,
0);
if FHandle = INVALID_HANDLE_VALUE then
RaiseLastOSError;
sz := GetFileSize(FHandle, nil);
if FSize > sz then
begin
SetFilePointer(FHandle, FSize, nil, FILE_BEGIN);
SetEndOfFile(FHandle);
SetFilePointer(FHandle, 0, nil, FILE_BEGIN);
end
else
FSize := sz;
FMapping := CreateFileMapping(
FHandle,
nil,
PAGE_READWRITE,
0, FSize,
nil);
if FMapping = 0 then
begin
CloseHandle(FHandle);
FHandle := INVALID_HANDLE_VALUE;
RaiseLastOSError;
end;
FView := MapViewOfFile(
FMapping,
FILE_MAP_ALL_ACCESS,
0, 0,
0);
if FView = nil then
begin
CloseHandle(FHandle);
CloseHandle(FMapping);
FHandle := INVALID_HANDLE_VALUE;
FMapping := 0;
RaiseLastOSError;
end;
FSize := GetFileSize(FHandle, nil);
end
else
begin
UnmapViewOfFile(FView);
CloseHandle(FMapping);
CloseHandle(FHandle);
FView := nil;
FMapping := 0;
FHandle := INVALID_HANDLE_VALUE;
end;
FActive := Value;
end;
function TMappedFile.GetActive : Boolean;
begin
Result := FHandle <> INVALID_HANDLE_VALUE;
end;
procedure TMappedFile.Open;
begin
Active := True;
end;
procedure TMappedFile.Close;
begin
Active := False;
end;
end.
← →
Fay © (2004-06-24 14:31) [65]Пляски с sz в SetActive - левые 8)
← →
Кастуся (2004-06-24 17:12) [66]
> Romkin © (24.06.04 11:21) [50]
> ЛУчше посмотреть на другие участки программы...
> А еще лучше воспользоваться профилировщиком
А что такое профилировщикик? Это я так понимаю поределяет что сколько времени занимет в программе? Это какая-то программа и где её достать?
> Romkin © (24.06.04 11:28) [52]
> Кстати, насколько я понял, тебе значение строки не нужно?
> Тогда StrToInt64, но разбей строку на две половины - как
> раз влезет.
Я вот ут думаю, а будет ли это все быстрее работать, чем простоHexSt:="0"+"1"+"2"+"3"+"4"+"5"+"6"+"7"+"8"+"9"+"a"+"b"+"c"+"d"+"e"+"f";
Bad:=not (LastDelimiter(HexSt,w0)=32);
← →
Кастуся (2004-06-24 18:35) [67]короче пробовал я StrToInt64 - медленно работает
← →
имя (2004-06-24 19:21) [68]Удалено модератором
Примечание: Смени ник
← →
имя (2004-06-24 20:30) [69]Удалено модератором
Примечание: Смени ник.
← →
Anatoly Podgoretsky © (2004-06-24 21:13) [70]Слушай не лез бы ты в ассемблер, который раз по счету приводишь грубый и чрезвычайно опасный код. Ты бы хоть раз прочитал справку про встроеный ассемблер и соглашения.
← →
Кастуся (2004-06-24 22:01) [71]
> Anatoly Podgoretsky © (24.06.04 21:13) [70]
> Слушай не лез бы ты в ассемблер, который раз по счету приводишь
> грубый и чрезвычайно опасный код. Ты бы хоть раз прочитал
> справку про встроеный ассемблер и соглашения.
а чем приведённый код може быть опсаным?
← →
Кастуся (2004-06-25 10:08) [72]Так чем?
← →
Anatoly Podgoretsky © (2004-06-25 10:25) [73]Неправильное использоние регистров, в результате могут быть выполнены недопустимые вещи, абсольтно любые и AV самое легкое что может произойти. Код абсолютно безграмотен, именно все приведеные с использование ассемблера.
← →
Romkin © (2004-06-25 11:29) [74]Упс... Все почистили. Зачем же красный карандаш, когда синего было достаточно?!
Кастуся (24.06.04 17:12) [66] Да, именно определяет расход времени на разные функции. GPProfile, например. НАйти можно, достаточно поискать Delphi profiler ;)
И, кстати, почему бы просто не делать кусочную оптимизацию, а переписать все на конечный автомат? Уверяю, скорее всего быстрее, чем автомат ты вряд ли сделаешь.
И я уже пару раз просил дать постановку, а что собственно требуется-то? Улучшать код надо разумно, и, на мой взгляд, лезть в дебри ассемблера и проблемно-зависимой оптимизации кода надо в крайнем случае. Если скорость универсального короткого кода не устраивает, прежде всего надо посмотреть, нельзя ли сам алгоритм улучшить
← →
Кастуся (2004-06-25 15:57) [75]
> Romkin © (25.06.04 11:29) [74]
Может тебе интересно, конечно, что у меня за задача, но, еаверное, ИМХО лень будет тебе что-нибудь делать. В принципе, из этой ветки я извлек для себя массу полезного, благодаря чему, скорость работы моего алгоритма увеличилась в несколько раз.
> почему бы просто не делать кусочную оптимизацию, а переписать
> все на конечный автомат?
А можно пару слов про "конечный автомат"? Что енто такое и с чем его едят?
Так что спасибо огромное всем за помощь!
> Anatoly Podgoretsky © (25.06.04 10:25) [73]
а асм коды чьи-то там все равно не работали!
← →
Anatoly Podgoretsky © (2004-06-25 16:03) [76]Они могли работать в крайнем ограниченом количестве случаев, в большинстве случаев должны приводить к ошибке, хорошо если не критической.
← →
Fay © (2004-06-25 16:32) [77]2Кастуся (25.06.04 15:57) [75]
> А можно пару слов про "конечный автомат"? Что енто такое
> и с чем его едят?
Вам не стыдно, товарищ? Интернет забит подобной инфой. Да и институте не умалчивают 8)
← →
Romkin © (2004-06-25 16:36) [78]>А можно пару слов про "конечный автомат"? Что енто такое и с чем его едят?
НУ я же уже давал:
Romkin © (23.06.04 18:09) [31]
Основная идея простая: файл рассматривается как непрерывный поток байт, каждый из которых проходит через "фильтр", который реагирует на него изменением состояния (и данных). В результате - DelSpaces, например, вообще не нужна будет, реакция на пробел простая - continue :))
← →
Кастуся (2004-06-25 18:39) [79]классно конечно
Ладно всем спасибо!!!
← →
Кастуся (2004-06-27 09:32) [80]Снова чуть-чуть продолжим
> Romkin © (25.06.04 16:36) [78]
Если считывать файл побайтно, возникает проблема с определением положения троки идентификатора. Вот задача:
в общем случае есть в тексте сообщение вида:
MESSAGE: ## ## ## ## ## ##;
Необходимо его идентифицировать и получить, то что находится вместо #. Вот. как это реализ с пом-ю конечн автомата?
← →
Кастуся (2004-06-27 09:55) [81]
> Romkin © (25.06.04 16:36) [78]
вся штука в том, как в этом непрерывном потоке найти идентификационную строку?
или ты предлагаешь считывать строки методом
while not eof(f) do
begin
readln(f,st);
if pos("MESSAGE",st)>0 then
использовать конечный автомат
end;
так?
← →
Anatoly Podgoretsky © (2004-06-27 11:56) [82]Поток длеко не непрерывный, а разбит на строки.
← →
Romkin © (2004-06-28 11:23) [83]Кастуся (27.06.04 09:32) [80] Не все так просто :))
Надо полностью определить правила. Лучше бы реальный пример привел, на первый взгляд, твой случай решается детерминированным автоматом, а то, что ты с message привел - недетерминированным удобнее ;)
Впрочем, эскиз набросать могу. Итак, есть текстовый файл, процедура должна заполнить TStrings частями строк, идущими после "MESSAGE:" и до конца строки, удалив пробелы. Символы между идентификатором и концом строки - любые.
Так пойдет? :)) Сейчас будет...
← →
Romkin © (2004-06-28 12:11) [84]Вот, пожалуйста. Разбирайся, должно работать.
Понятно, Lines должны быть созданы до вызова процедуры...
type
TAutoState = (auWaitIdent, auInIdent, auReadMsg);
const
Ident: string = "MESSAGE:";
EndStrChars: set of char = [ #13,#10];
ExceptChars: set of char = [" "]; //Строка без этих символов
procedure GetMsgStrings(const FileName: string; Lines: TStrings);
var
F: file of char;
auState: TAutoState;
IdLen: Integer;
IdPos: Integer;
ch: char;
MsgStr: string;
begin
idLen := Length(Ident);
MsgStr := "";
assignFile(F, FileName);
reset(F);
try
auState := auWaitIdent;
while not EOF(F) do
begin
Read(F, ch);
case auState of
auWaitIdent: begin //Ждем "MESSAGE:"
if ch = Ident[1] then //первый символ, однако
begin
idPos := 1;
auState := auInIdent;
//На тот случай, если длина Ident = 1
if idPos = idLen then //Ident найден
auState := auReadMsg;
end;
end;
auInIdent: begin //Проверяем, однако, совпадение
Inc(idPos);
if (ch = Ident[idPos]) and (idPos = idLen) then
auState := auReadMsg
else
if ch <> Ident[idPos] then //Это не ident
auState := auWaitIdent;
//увы, только одно состояние :(
//На случай попадания MESMESSAGE: и тд
if (ch = Ident[1]) and (auState <> auInIdent) then
begin
idPos := 1;
auState := auInIdent;
end;
end;
auReadMsg: begin
if not (ch in EndStrChars) then //Конца строки нет
begin
if not (ch in ExceptChars) then //все, кроме пробела
MsgStr := MsgStr + ch;
end
else
begin
auState := auWaitIdent;
Lines.Add(MsgStr);
MsgStr := "";
end
end;
end; //case
end; //while
finally
CloseFile(F);
end;
end;
Страницы: 1 2 3 вся ветка
Текущий архив: 2004.07.11;
Скачать: CL | DM;
Память: 0.71 MB
Время: 0.035 c