Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 5

Автор: psa1974
Дата сообщения: 26.10.2009 23:00
Maks150988
Я тут посмотрел объявление и реализацию ф-ции DeCompressBuf:

Код: procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
Автор: Maks150988
Дата сообщения: 26.10.2009 23:41
psa1974

А ну тогда все понятно. Подизменил вот так.


Код: procedure DeCompressGzipString(const InpStr: AnsiString; var OutStr: AnsiString);
var
InpBuf : AnsiString;
InpSize: Integer;
OutBuf : Pointer;
OutSize: Integer;
begin
InpSize := lstrlen(@InpStr[1]);
if (InpSize > 0) then
try
InpBuf := InpStr;
CompressBuf(@InpBuf[1], InpSize, OutBuf, OutSize);
SetLength(OutStr, OutSize);
CopyMemory(@OutStr[1], OutBuf, OutSize);
finally
if (OutBuf <> nil) then
FreeMem(OutBuf);
end;
end;
Автор: psa1974
Дата сообщения: 27.10.2009 07:49
Maks150988

Цитата:
но поулчается одна строчка с символами ив се

Имхо, все дело в том что ты вместо переменных типа PChar используешь строки. А для строк Дельфи ведет подсчет ссылок и в коде:

Код:
szContent := '';
SetLength(szBuffer, dwLength + 1);
repeat
InternetReadFile(fRequest, @szBuffer[1], dwLength, dwBytes);
SetLength(szBuffer, dwBytes);
//WriteLn(szBuffer);
szContent := szContent + szBuffer; // !!!!!!!!
until dwBytes = 0;
Автор: JohnSilver182
Дата сообщения: 27.10.2009 08:53
Hi All
Вот в моем примере по команде f_ini:=a_ini; просто передается адресс объекта ?
То есть по идее при этом объект f_ini закрывать низя , иначе закроется глобальный объект который я передаю в процедуру .


Код: Procedure Kiss(a_ini:TIniFile);
var f_ini:TIniFile;
begin
f_ini:=a_ini;
f_ini.WriteString('SUKO','ss2','2');
end;
Автор: psa1974
Дата сообщения: 27.10.2009 09:09
JohnSilver182
безусловно! После f_ini:=a_ini; оба переменные указывают на одну область памяти (классовые переменные на самом деле являются указателями). Никакого копирования самого объекта не происходит. Но я бы чтоб совсем красиво написал так:

Код: Procedure Kiss(a_ini:TIniFile);
var f_ini:TIniFile;
begin
f_ini:=a_ini;
if Assigned(f_ini) then
f_ini.WriteString('SUKO','ss2','2');
end;
Автор: JohnSilver182
Дата сообщения: 27.10.2009 09:17
psa1974
А почему нельзя сделать копию обьекта ??7
Procedure Kiss(const a_ini:TIniFile);
Автор: Cryogen2003
Дата сообщения: 27.10.2009 09:19
Доброе утро.

Как из Active Directory прочитать весь список пользователей с их логинами, ФИО и адресами почты?
Автор: Vladkyr
Дата сообщения: 27.10.2009 10:21
JohnSilver182
потому что, const не делает копию объекта, а всего лишь запрещает менять значение переменной a_ini (указателя на объект), а сам объект все равно передается по ссылке, т.е. его самого менять вполне можно.
Автор: psa1974
Дата сообщения: 27.10.2009 10:36
JohnSilver182
Как я уже говорил, переменные типа КЛАСС являются указателями.
Во-первых, модификатор const по отношению к указателю в общем случае смысла не имеет, поскольку он запрещает изменять значение указателя а не значение памяти, на которую указатель указывает, т.е. применительно к тебе const a_ini:TIniFile приведет к тому, что внутри ф-ции ты не сможешь в переменной a_ini присвоить другое значение, но ты легко сможешь менять данные своего класса как объекта, расположенного в памяти по адресу, на который указывает переменная a_ini
Во-вторых, чтобы скопировать класс, тебе надо скопировать не имя переменной классового типа, а все данные твоего класса. Общий подход такой: надо создать новый класс и скопировать в него данные (именно данные) исходного класса. Для классов, содержащих данные, и для которых имеет смысл выполнять копирование объектов, реализуют метод Assign (например, у класса TStrings - посмотри реализацию, не поленись). Для класса TIniFile нет смысла вообще реализовывать копирование, потому что он сам данных не содержит, он содержит только методы для работы с ини-файлами. Поэтому метод Assign у него отсутствует.
Если уж на то пошло, в твоем случае я бы вообще сделал так:

Код: Procedure Kiss(a_iniName: string);
begin
if FileExists(a_iniName) then
with TInifile.Create(a_iniName) do
begin
WriteString('SUKO','ss2','2');
Free;
end;
end;
Автор: Maks150988
Дата сообщения: 27.10.2009 10:38
psa1974
Опа, только что заметил что я оказывается пытался сжать данные, а не расжать (CompressBuf использовал в DeCompressGzipString).
Сделал так

Код: DecompressBuf(Addr(InpStr[1]), InpSize, 0, OutBuf, OutSize);
Автор: SerBUser
Дата сообщения: 27.10.2009 10:48
Такой вопрос - есть домен Rogaikopyta, у него может быть два (и более) контроллеров, а может и один (например server1.Rogaikopyta.ru и server1.Rogaikopyta.ru). Как узнать полное имя сервера контроллера (server1.Rogaikopyta.ru)?
Автор: JohnSilver182
Дата сообщения: 27.10.2009 11:30
psa1974 Убедил


Добавлено:
Академический вопрос

Код: ............
var p1,p2:^integer;
begin
new(p1);new(p2);
p1^:=1;
p2:=p1;
dispose(p1);
if Assigned(p2) then dispose(p2);
................................
Автор: Varenik
Дата сообщения: 27.10.2009 15:49
JohnSilver182
Академический вопрос

Код: ............
var p1,p2:^integer; Объявить указатель на целое
begin
new(p1);new(p2); Отвести под указатели области памяти
p1^:=1; Указателю p1 указывать на 1
p2:=p1; Указателю p2 указывать на ту же 1
dispose(p1); Указателю p1 никуда не указывать и ващще освободить область памяти, которую он занимал
if Assigned(p2) then dispose(p2); При этом указатель p2 всё ещё указывает на ту же самую 1; и если это так, освободить и его
................................
Автор: psa1974
Дата сообщения: 27.10.2009 15:52
Maks150988
Порешал я твой вопрос, вот РАБОТАЮЩЕЕ решение:

Код:
Function DeCompressString(InputStr: String): String;
var
FBuffer: array[Word] of Char; // ТОЛЬКО ТАК надо задавать входной буфер - как массив символов!
Buffer: Pointer;
BufSize: Integer;
begin
if (Length(InputStr) > 0) then
begin
Move(Pointer(InputStr)^, FBuffer[0], Length(InputStr));
DeCompressBuf(Pointer(@FBuffer[0]), Length(InputStr), 0, Buffer, BufSize);
SetLength(Result, BufSize);
Move(Buffer^, pointer(Result)^, BufSize);
// В случае экцепшена внутри DeCompressBuf, на ее выходе память Buffer она освободит сама
// так же в этом случае сюда мы не дойдем, поэтому следующая строка
// должна выполняться (и выполниться), только если все хорошо:
FreeMem(Buffer);
end;
end;
Автор: Maks150988
Дата сообщения: 27.10.2009 16:14
psa1974
Спасибо. Проверил на сжатии/разжатии текста обычном, работает замечательно. Только исключение вылетает все равно при распаковке gzip данных от запроса. Может гугл свинью подложил и там другой алгоритм упаковки.
Автор: Varenik
Дата сообщения: 27.10.2009 16:33
JohnSilver182
Допустил неточность: так, как я написал, будет, если вставить после

Код: p2:=p1;
p1:=nil;
dispose(p1); Указателю p1 никуда не указывать и ващще освободить область памяти, которую он занимал
if Assigned(p2) then dispose(p2); При этом указатель p2 всё ещё указывает на ту же самую 1; и если это так, освободить и его
Автор: psa1974
Дата сообщения: 27.10.2009 16:35
Maks150988
Ну тут уж я хоть и волшебник, но не настолько
Автор: Cryogen2003
Дата сообщения: 27.10.2009 16:43
Привет. А мне кто-нибудь поможет?
Автор: volser
Дата сообщения: 27.10.2009 16:57
Cryogen2003
Ссылка
Автор: Cryogen2003
Дата сообщения: 27.10.2009 17:12
volser
Это я читал, а без ADO ?
Автор: JohnSilver182
Дата сообщения: 27.10.2009 17:36

Цитата:
Если не присвоить nil, то после dispose(p1); оба указателя никуда не указывают и вроде как не существуют

Я просто это еще не осознал . Будем думать .
Автор: RomanTim
Дата сообщения: 27.10.2009 17:48
Cryogen2003
http://msdn.microsoft.com/en-us/library/aa772170%28VS.85%29.aspx
Автор: Cryogen2003
Дата сообщения: 27.10.2009 17:50
RomanTim
спс большое
Автор: Frodo_Torbins
Дата сообщения: 27.10.2009 19:57
JohnSilver182
Varenik видимо имел ввиду такое:

Код: dispose(p1);
p1:=nil;
if Assigned(p2) then dispose(p2); //а тут p2 показывает в общем случае в космос
Автор: Maks150988
Дата сообщения: 27.10.2009 20:07
psa1974
Ну и на этом спасибо, теперь хоть понятно как расжимать строку. Пригодится.
Автор: psa1974
Дата сообщения: 27.10.2009 21:12
Frodo_Torbins
Varenik
и я сам
Мы тут с вами наверное, вконец запутали человека

JohnSilver182
Я бы порекомендовал, все таки, почитать какую-нибудь литературу сперва, чтобы сложилось хоть какое-то представление... А потом уже - к нам...

От себя еще добавлю 5 копеек:
Ф-ция Assigned НЕ ПРОВЕРЯЕТ, РАСПРЕДЕЛЕНА ЛИ ПАМЯТЬ по данному указателю, а всего лишь проверяет указатель на равенство nil.. Цитата из справки:

Цитата:
Assigned function
Tests for a nil (unassigned) pointer or procedural variable.

Таким образом, на самом деле:

Код:
var p1,p2:^integer; // Объявить указатель на целое
begin
new(p1);new(p2); // Отвести под указатели области памяти
p1^:=1; // Указателю p1 указывать на 1
p2:=p1; // Указателю p2 указывать на ту же 1
dispose(p1); // Освобождаем память, на которую указывает указатель.
// После этого указатель p1 НЕ СТАНОВИТСЯ равным nil,
// и не меняет своего значения!!! Просто та область памяти,
// на которую он указыват, уже не существует!!!
if Assigned(p2) then // Аналогично - память, на которую указывает p2 уже не
// существует, мы ее освободили вызовом dispose(p1),
// однако p2 <> nil (p2 попрежнему имеет значение того
// адреса, по которому когда-то была распределена память),
// поэтому Assigned(p2) = true
dispose(p2); // тут справедливый эксцершен, а что ж ты хотел...
Автор: NOwlar
Дата сообщения: 28.10.2009 12:51
Только new(p2) делать не надо - утечка памяти образуется.
Автор: psa1974
Дата сообщения: 28.10.2009 13:07
NOwlar
Точно, проглядел . Такой маленький кусок кода, а столько "танцев с бубном"...
Автор: JohnSilver182
Дата сообщения: 28.10.2009 13:29
Не так то все просто с указателями
Автор: Cryogen2003
Дата сообщения: 28.10.2009 13:39
Как можно сделать удаление файла, который открыт другим приложением? Ну или может быть как поставить файл на удаление после освобождения его другой программой?

То есть для чего нужно:
1) Создается tempfile для запуска по нему через shellexecute ассоциированной программы.
2) А потом стало быть файл надо удалить

Может быть просто такое, что тот же excel, acrobat reader забыли закрыть и файл разумеется не удалиться.
Через вставку в RunOnce это конечно работает, но если пользователь имеет права простого usera, то такое просто не прокатывает.

Стало быть, чего делать?

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Clipper 5


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.