Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 5

Модерирует : ShIvADeSt

ShIvADeSt (19-05-2010 05:14): Продолжаем тут http://forum.ru-board.com/topic.cgi?forum=33&topic=11215  Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

   

ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Продолжение темы Вопросы по Delphi (до версии 2009) - часть 4

Познаем сами, помогаем другим...
Обсуждаем вопросы, не связанные с юникоидными версиями Delphi - для этого есть соответствующая тема (см. ссылки ниже).

Правила топика:
    Прежде чем спрашивать:
  1. Желательно изучить вопрос, попытаться найти ответ в прилагаемых мануалах, хелпах и анализируя исходники.
  2. Выполнить поиск по топику (открыть "Версия для печати" и поискать ответ там).
  3. Применить фильтр по разделу "Прикладное программирование". Ответы на многие старые вопросы могли быть даны в отдельных темах.
  4. Продумайте вопрос. На поверхностные вопросы вы получите поверхностные ответы, или вообще ответов не получите.
  5. Желательно указывать версии используемого компилятора и операционной системы.
    Прежде чем отвечать:
  1. Если не можете помочь, не мешайте.
  2. Если уж вы отвечаете на вопрос, давайте ответ по сути.
  3. Если вы не уверены, так и говорите! Ошибочный, но авторитетно звучащий ответ хуже, чем отсутствие ответа.
  4. Задавайте дополнительные вопросы, чтобы получить больше информации.
  • Отсутствие ответа не равносильно игнорированию - иногда участники форума просто не знают ответ. Повторная посылка вопроса не приветствуется. Посты типа "неужели никто не знает ответа..." или "может мне все-таки кто-нибудь ответит" недопустимы.  
  • Все большие куски кода (более 5 строк) оформляем в тег [morе] дабы уменьшить размер поста. FAQ по тегу [morе].

  • Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 02:09 28-06-2009 | Исправлено: psa1974, 12:00 02-02-2010
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Да, спасибо. IP Helper это для использования iphlpapi.dll. В версии JEDI нет некоторых новых функций, да он вообще походу не обновлялся.
     
    Еще что хотел узнать. Если есть кто-нибудь из тех кто освоил функцию DeCompressBuf, дайте знать, а то есть вопрос. Не знаю где уже искать, попадается одна и та же ерунда про поток и стримадаптеры эти. Мне нужно декодировать строку, пожатую из gzip в string обычный. Получаю строку с сервера, естественно там ответ закодирован, вот и надо все это дело раскодировать.
     

    Код:
    procedure DeCompressGzipString(const InpStr: AnsiString; var OutStr: AnsiString);
    var
      InpBuf : Pointer;
      InpSize: Integer;
      OutBuf : Pointer;
      OutSize: Integer;
    begin
      InpBuf := nil;
      OutBuf := nil;
      InpSize := lstrlen(@InpStr[1]);
      if (InpSize > 0) then
      try
        GetMem(InpBuf, InpSize);
        lstrcpy(InpBuf, @InpStr[1]);
        DeCompressBuf(@InpBuf, InpSize, 0, OutBuf, OutSize);
        OutStr := PAnsiChar(OutBuf);
      finally
        if (InpBuf <> nil) then
          FreeMem(InpBuf);
        if (OutBuf <> nil) then
        FreeMem(OutBuf);
      end;
    end;

     
    Помотрел примеры где стримадаптеры используются, да вроде тоже самое, но тут вылет с исключением. Что не так кто знает.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 21:56 26-10-2009 | Исправлено: Maks150988, 21:58 26-10-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Я тут посмотрел объявление и реализацию ф-ции DeCompressBuf:

    Код:
    procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);

    В первом параметре передается НЕ ссылка на указатель типа Pointer, а САМ УКАЗАТЕЛЬ типа Pointer, который потом внутри ф-ции DecompressBuf присваивается полю next_in: PChar записи TZStreamRec. Короче, надо так:

    Код:
    DeCompressBuf(InpBuf, InpSize, 0, OutBuf, OutSize);

    ЗЫ: если бы в объявлении было DecompressBuf(var InBuf: Pointer;.......... ), тогда твой вариант был бы верным... А так получается, что длину буфера ты определяешь правильно по входной строке InpStr, а передаешь в функцию не адрес буфера, содержащего строку, а адрес памяти, где хранится указатель на буфер и который занимает всего 4 байта (размер указателя), вот тебе и эксцепшен .

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 23:00 26-10-2009 | Исправлено: psa1974, 23:09 26-10-2009
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    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;

     
    Вроде работает, но все равно какой-то кот в мешке.
     
    Вот код для отправки пост запроса на сервер гугл переводчика. Далее Там закодирвана часть текста GPL соглашения как надо. вот отправляю на сервер, он выдает результат. но поулчается одна строчка с символами ив се. Как полностью ответ от сервера сохранить?  Если WriteLn вызывать после каждого чтения данных, в консоль пишется все, а так если к строке прибавлять тот же самый текст дял последующего его декодирования - фигушки какие-то. В чем дело не пойму.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 23:41 26-10-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    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;

    в строке   szContent := szContent + szBuffer; как минимум первый раз идет НЕ присвоение, а тупо передача в szContent ссылки на область памяти szBuffer и увеличение счетчика ссылкок. На втором шаге цикла сразу после вызова InternetReadFile, еще не выполняя присваивание, в szContent уже будет новое значение (поскольку и szContent и szBuffer ссылаются на одну область памяти).  Что там дальше происходит, я не разбирался, но попробуй вызвать после строки szContent := szContent + szBuffer; процедуру UniqueString(szContent); - UniqueString гарантирует, что после ее вызова в памяти будет выделен новый буфер для переданной в качестве параметра строки
    зы: попробовал твой код выполнить, HttpSendRequest возвращает false (запрос не уходит...) . Изменил, для примера по тексту строку: szScript := 'www.rsdn.ru'; и остальное по смыслу,  все отработало (само собой исключая ф-цию DeCompressGzipString)...
    далее

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 07:49 27-10-2009 | Исправлено: psa1974, 07:54 27-10-2009
    JohnSilver182



    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    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;

    Всего записей: 829 | Зарегистр. 03-06-2009 | Отправлено: 08:53 27-10-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    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;

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 09:09 27-10-2009 | Исправлено: psa1974, 09:14 27-10-2009
    JohnSilver182



    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    А почему нельзя сделать копию обьекта ??7
     Procedure Kiss(const a_ini:TIniFile);

    Всего записей: 829 | Зарегистр. 03-06-2009 | Отправлено: 09:17 27-10-2009
    Cryogen2003



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Доброе утро.
     
    Как из Active Directory прочитать весь список пользователей с их логинами, ФИО и адресами почты?

    ----------
    Холодильники мы

    Всего записей: 745 | Зарегистр. 08-12-2004 | Отправлено: 09:19 27-10-2009
    Vladkyr

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    JohnSilver182
    потому что, const не делает копию объекта, а всего лишь запрещает менять значение переменной a_ini (указателя на объект), а сам объект все равно передается по ссылке, т.е. его самого менять вполне можно.

    Всего записей: 26 | Зарегистр. 28-12-2006 | Отправлено: 10:21 27-10-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    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;
     

     
    ЗЫ: Если я тебя не убедил, почитай какую-нибудь книжку по программированию в Дельфи

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 10:36 27-10-2009 | Исправлено: psa1974, 16:12 27-10-2009
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Опа, только что заметил что я оказывается пытался сжать данные, а не расжать (CompressBuf использовал в DeCompressGzipString).
    Сделал так

    Код:
    DecompressBuf(Addr(InpStr[1]), InpSize, 0, OutBuf, OutSize);

    Но опять исключение вылетает.
    Код переделал вот так, чего-то от UniqueString толку нет, хотя я наверное опять намудрил...
    Далее
    Теперь впринципе загружает все, только надо бы это дело расжать. Еще попались примеры, с ними такие же дела с исключением. Ну первый надо полагать уже ошибку содержит где первым параметром в функции распаковки идет @Input[1].

    Код:
    Function DeCompressString(Input: String): String;
      Var Buffer: Pointer;
        BufSize: Integer;
     
      Begin
        Buffer := nil;
        Try
          DeCompressBuf(@Input[1], Length(Input), 0, Buffer, BufSize);
          SetLength(Result, BufSize);
          Move(Buffer^, Result[1], BufSize);
        Finally
          If Buffer <> nil Then FreeMem(Buffer);
        End;
      End;
     
    function DecompressFrom(const instring : string) : string;
    var p : pointer;
    size : integer;
    begin
     
    DecompressBuf(addr(instring[1]),length(instring),trunc(length(instring)/0.7)
    ,p,size);
    Setlength(Result,size);
    Move(p^,Result[1],size);
    FreeMem(p);
    end;

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 10:38 27-10-2009
    SerBUser

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Такой вопрос  - есть домен Rogaikopyta, у него может быть два (и более) контроллеров, а может и один (например server1.Rogaikopyta.ru и server1.Rogaikopyta.ru). Как  узнать полное имя сервера контроллера (server1.Rogaikopyta.ru)?

    Всего записей: 123 | Зарегистр. 31-08-2009 | Отправлено: 10:48 27-10-2009
    JohnSilver182



    BANNED
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974 Убедил
     
     
    Добавлено:
    Академический вопрос

    Код:
    ............
    var p1,p2:^integer;
    begin
    new(p1);new(p2);
    p1^:=1;
    p2:=p1;
    dispose(p1);
    if Assigned(p2) then dispose(p2);
    ................................

     
    if Assigned(p2) then dispose(p2);  у меня дает TRUE .Потому что память не отдана другим данным ?? И человеческого способа проверить нет кроме EXCEPT ?

    Всего записей: 829 | Зарегистр. 03-06-2009 | Отправлено: 11:30 27-10-2009
    Varenik



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    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; и если это так, освободить и его
    ................................

    Так понятно?

    ----------
    Если нравится, считайте, что получилось…

    Всего записей: 1766 | Зарегистр. 21-07-2001 | Отправлено: 15:49 27-10-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    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;
     


    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 15:52 27-10-2009 | Исправлено: psa1974, 16:32 27-10-2009
    Maks150988



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    psa1974
    Спасибо. Проверил на сжатии/разжатии текста обычном, работает замечательно. Только исключение вылетает все равно при распаковке gzip данных от запроса. Может гугл свинью подложил и там другой алгоритм упаковки.

    Всего записей: 836 | Зарегистр. 23-12-2006 | Отправлено: 16:14 27-10-2009
    Varenik



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    JohnSilver182
    Допустил неточность: так, как я написал, будет, если вставить после

    Код:
    p2:=p1;
    p1:=nil;
    dispose(p1);                                Указателю p1 никуда не указывать и ващще           освободить область памяти, которую он занимал
    if Assigned(p2) then dispose(p2); При этом указатель p2 всё ещё указывает на ту же самую 1; и если это так, освободить и его
     
     
    Если не присвоить nil, то после dispose(p1); оба указателя никуда не указывают и вроде как не существуют, но они не равны nil; по-этому проверка Assigned(p2) проходит, а попытка dispose(p2); вызывает исключение

    ----------
    Если нравится, считайте, что получилось…

    Всего записей: 1766 | Зарегистр. 21-07-2001 | Отправлено: 16:33 27-10-2009
    psa1974



    Full Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Maks150988
    Ну тут уж я хоть и волшебник, но не настолько

    Всего записей: 438 | Зарегистр. 08-11-2005 | Отправлено: 16:35 27-10-2009
    Cryogen2003



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Привет. А мне кто-нибудь поможет?

    ----------
    Холодильники мы

    Всего записей: 745 | Зарегистр. 08-12-2004 | Отправлено: 16:43 27-10-2009
    volser

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Cryogen2003
    Ссылка

    Всего записей: 713 | Зарегистр. 31-03-2006 | Отправлено: 16:57 27-10-2009
       

    Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 5
    ShIvADeSt (19-05-2010 05:14): Продолжаем тут http://forum.ru-board.com/topic.cgi?forum=33&topic=11215


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru