Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.26;
Скачать: CL | DM;

Вниз

Работа с PChar средствами Windows (API)   Найти похожие ветки 

 
Max_2006   (2006-11-05 12:38) [0]

как работать с PChar в Delphi средствами Windows, т.е. API? Т.е. надо например воспользоваться API функцией GetSystemDirectory, что делать если после ее выполнения нужно выполнить что-то вроде SetLength(p, Length(p)); т.е. длина строки ранв MAX_PATH, после выполнения функции GetSystemDirectory, как обрезать строку?

var
 p: PChar
begin
 GetMem(p, MAX_PATH);
 GetSystemDirectory(p, MAX_PATH);

...
 FreeMem(p);

Работу со String и ShortString не предлагайте...


 
sniknik ©   (2006-11-05 13:05) [1]

> Работу со String и ShortString не предлагайте...
тогда предлагаю работать с массивом of char;...

p.s. интересно, а откуда берутся, в примерно в одно время, кучи однотипных вопросов, причём с примерно одинаковым незнанием тех же основ разными(???) авторами. и с примерно одинаковым стилем... без малейшего намёка на "зачем", только с "надо вот так" + какие то надуманные ограничения...

==================================
- мама скажи "абырхвал".
- зачем?
- ну скажи!
- нет, ты скажи что это значит и зачем.
- ну мам!
- да не буду я всякую непонятную ерунду говорить.
- ВОТ!!! и меня тогда не заставляйте английский учить!


 
Dmitry_177   (2006-11-05 13:12) [2]

Просто перед тем чтобы передать строку в API функцию, компилятов переводит ее из string в PChar или массив array of Char, на это тратится какое-то время, хотел бы сделать приложение максимально эффективное... Ну и вообще ради интереса...


 
Dmitry_177   (2006-11-05 13:14) [3]

Вопрос схожий с моим ))) Но всеравно, хотел бы получить на него ответ...)))


 
sniknik ©   (2006-11-05 14:02) [4]

> хотел бы сделать приложение максимально эффективное...
а как думаешь делается обрезание по SetLength? выделением нового куска памяти и копированием туда отрезанной части. это эффективно?

хотелось бы тогда получить определение эффективности, что для тебя важнее ресурсы или быстродействие, т.к. с точки зрения быстродействия эффективнее было бы раз отрезать кусок памяти и пользоваться им не перераспределяя т.к. это долгая операция (с другой стороны дельфя уже сделала эту работу за нас, ее менеджер памяти выделяет блок, а после раздаёт кусочки без запросов от системы, если не вылезти за пределы конечно...)
ну и получается ты со своим полным незнанием работы системы хочешь написать эффективнее чем борланд, обходя то что он встроил? думаешь получится?
я вот сомневаюсь.
ну ладно, пусть решили что оставить размер как есть эффективнее (не будем память экономить, переключимся на быстродействие), но в показанном куске есть подозрение используется локальная переменная(!!!) это значит что при передаче она либо потеряется либо мы ее должны будем скопировать в другую с другой областью видимости, а это эффективно?, но тем не менее по другому нельзя и получается все ранние потуги насмарку...

уффф..., ещё не начал объяснять а уже упарился... все таки вам проще книжечку/лекции взять почитать... потому как однозначных ответов нет.

и самое главное, все это, то что ты делаешь думая что оптимизация...,  на самом деле называется "экономия на спичках", за счет указателей, сдвигов, самостоятельных учетов блоков памяти, выиграть можно не более 5% скорости (испортить и сделать медленнее гораздо проще и вероятнее) чем если следовать стандартам (где уже все продумано), а вот на логике приложения можно выиграть на порядки (200%/1000%), если решать задачу а не проблемы выбранного пути решения... но почему то о ней не задумываются.


 
Leonid Troyanovsky ©   (2006-11-05 14:03) [5]


> Max_2006   (05.11.06 12:38)  

>  GetMem(p, MAX_PATH);
>  GetSystemDirectory(p, MAX_PATH);


var
 a: array [0..MAX_PATH] of Char;
 p: PChar;
 n : Longint;
 ..
 n := GetSystemDirectory(a, MAX_PATH);
 Win32Check(n <> 0);
 p := StrAlloc(n);
 StrCopy(p, a);
 ..

--
Regards, LVT.


 
Max_2006   (2006-11-05 14:21) [6]

Leonid Troyanovsky, Я имел ввиду на API, не используя модуль SysUtils. А функции StrAlloc и StrCopy какраз от туда...


 
palva ©   (2006-11-05 14:22) [7]

Можно так:

{$APPTYPE CONSOLE}
uses Windows;
var
 s: String;
 len: Integer;
begin
 len := GetSystemDirectory(nil, 0);
 WriteLn(len);   // 18
 SetLength(s, len - 1);
 GetSystemDirectory(PChar(s), len);
 WriteLn(s);   // C:\WINNT\system32
end.


 
Leonid Troyanovsky ©   (2006-11-05 14:24) [8]


> Max_2006   (05.11.06 14:21) [6]

> Leonid Troyanovsky, Я имел ввиду на API, не используя модуль
> SysUtils. А функции StrAlloc и StrCopy какраз от туда...


GetMem, Move

--
Regards, LVT.


 
KilkennyCat ©   (2006-11-05 14:37) [9]

> [4] sniknik ©   (05.11.06 14:02)
> и самое главное, все это, то что ты делаешь думая что оптимизация...,
>  на самом деле называется "экономия на спичках", за счет
> указателей, сдвигов, самостоятельных учетов блоков памяти,
> выиграть можно не более 5% скорости (испортить и сделать
> медленнее гораздо проще и вероятнее) чем если следовать
> стандартам (где уже все продумано), а вот на логике приложения
> можно выиграть на порядки (200%/1000%), если решать задачу
> а не проблемы выбранного пути решения... но почему то о
> ней не задумываются.


Абсолютно верно. Причем это ведь настолько часто разжевывается, в нормальных книжках, особенно разжевывают "игроделы", но воз и ныне там... Лезут в дебри, оптимизируют оптимизированное... лучше бы уж просто на приятный интерфейс время тратили :)


 
Anatoly Podgoretsky ©   (2006-11-05 14:47) [10]

> Max_2006  (05.11.2006 12:38:00)  [0]

Ее на надо образать, это лишнее, у нее есть естественный ограничитель.
А за что так ненавидишь тип String, вот там твое пожелание будет
естественным образом реализовано.

S := P;

Правда и P тут совсем лишнее. И заботиться об удалении не надо, и ошибок
будет на порядок меньше. В справке четко сказано, что тип String полностью
совместим с PCharи поэтому твое желание выглядит как то очень странно, если
не сказать больше.


 
Anatoly Podgoretsky ©   (2006-11-05 14:49) [11]

> sniknik  (05.11.2006 13:05:01)  [1]

> интересно, а откуда берутся, в примерно в одно время, кучи однотипных
> вопросов, причём с примерно одинаковым незнанием тех же основ разными(???)
> авторами

А ты не знаешь? К сожалению в наших учебных заведения экзамены,
самостоятельные! работы проходят в одно и тоже время, а все предыдущее время
проводилось в других местах.


 
Anatoly Podgoretsky ©   (2006-11-05 14:49) [12]

> Dmitry_177  (05.11.2006 13:12:02)  [2]

> хотел бы сделать приложение максимально эффективное

А достигаешь совсем противоположного.


 
Anatoly Podgoretsky ©   (2006-11-05 14:52) [13]

> sniknik  (05.11.2006 14:02:04)  [4]

> ну ладно, пусть решили что оставить размер как есть эффективнее (не будем
> память экономить, переключимся на быстродействие),

А быстродействие с PChar хуже, функциям приходится искать конец строки
методом сканирования. Кроме того как правило надо еще и выделять и
освобождать память, при том в куче.


 
Anatoly Podgoretsky ©   (2006-11-05 14:56) [14]

> Leonid Troyanovsky  (05.11.2006 14:03:05)  [5]

А тепеть тоже самое, но со String


var
  S: string;
  N: Integer;
begin
  N := GetSystemDirectory(S, MAX_PATH);
// если есть желание обрезать то
  S := PChar(S);
// или воспользоваться результатом работы функции
 SetLength(S, N);
end;


 
Anatoly Podgoretsky ©   (2006-11-05 14:57) [15]

> palva  (05.11.2006 14:22:07)  [7]

Мой код короче - одна или две строки, если с обрезанием.


 
Max_2006   (2006-11-05 15:18) [16]

Anatoly Podgoretsky:

> // если есть желание обрезать то   S := PChar(S);// или
> воспользоваться результатом работы функции  SetLength(S,
>  N);

а что быстрее будет работать S := PChar(S); или SetLength(S, N);?

> А быстродействие с PChar хуже, функциям приходится искать
> конец строки методом сканирования. Кроме того как правило
> надо еще и выделять и освобождать память, при том в куче.

А как же то что перед тем как строка string чтобы передалась в API функцию, она всеравно переводится в PChar?


 
Max_2006   (2006-11-05 15:20) [17]

А еще в этом примере, Anatoly Podgoretsky ©   (05.11.06 14:56) [14] на строке N := GetSystemDirectory(S, MAX_PATH); ошибка при компиляции: [Pascal Error] Unit1.pas(32): E2010 Incompatible types: "string" and "PAnsiChar"


 
Ketmar ©   (2006-11-05 15:24) [18]

>[14] Anatoly Podgoretsky(c) 5-Nov-2006, 14:56
>А тепеть тоже самое, но со String
э-э-э... скажи, что ты пошутил, а? не мог же ты серьёзно такой бред родить.


 
Anatoly Podgoretsky ©   (2006-11-05 15:27) [19]

> Max_2006  (05.11.2006 15:18:16)  [16]

> а что быстрее будет работать S := PChar(S); или SetLength(S, N);?
Естественно второе, поскольку не требуется сканировать строку на предмет
определения ее длины

> как же то что перед тем как строка string чтобы передалась в API ?
> функцию, она всеравно переводится в PChar?

Использовать функцию PChar, она проверяет не пустая ли строка и если не
пустая, то возращает указатель как есть, а если пустая, то возращает
указатель на предопределенную пустую строку, доступ к которой RO


 
Anatoly Podgoretsky ©   (2006-11-05 15:31) [20]

> Max_2006  (05.11.2006 15:20:17)  [17]

Сделай придение к PChar - PChar(S) и выдели место для хранения результата
как SetLength(S, MAX_PATH)
Полный код будет выглядеть так


  SetLength(S, MAX_PATH);
  N := GetSystemDirectory(S, MAX_PATH);
  SetLength(S, N);


Добавить обработку ошибок


 
Anatoly Podgoretsky ©   (2006-11-05 15:32) [21]

> Ketmar  (05.11.2006 15:24:18)  [18]

Смотри последний пример, ну не надо же полностью все писать, кое что надо
оставить и автору, у нас тут форум не по написанию программ, а для общения и
советов.


 
sniknik ©   (2006-11-05 15:40) [22]

> а что быстрее будет работать S := PChar(S); или SetLength(S, N);?
спичка, раз...

> ошибка при компиляции: [Pascal Error] Unit1.pas(32): E2010 Incompatible types: "string" and "PAnsiChar"
он не учел, что функция виндовая с входным параметром PChar, и если использовать стринг то он тоже должен быть "наполненным" а не пустым (тогда можно сделать приведение типа после которого там быде во что писать функции)

вот пример "минимум"
procedure TForm1.Button1Click(Sender: TObject);
var
 a: array [0..MAX_PATH] of Char;
 s: string;
 n: Integer;
begin
 n:= GetSystemDirectory(a, MAX_PATH);
 //Win32Check(n <> 0); полезная функция но ексепты в модуле тоже SysUtils
 s:= a; //и "обрезание" и присваивание  
 //после этого можно
 Label1.Caption:= s;
 //впрочем можно и без этого, какая разница откуда копировать, разница где это предполагается использовать...
 Label1.Caption:= a;
end;
итого минимум
procedure TForm1.Button1Click(Sender: TObject);
var
 a: array [0..MAX_PATH] of Char;
begin
 GetSystemDirectory(a, MAX_PATH);
 Label1.Caption:= a;
end;

используя массив (говорилось ещё в [1])


 
Max_2006   (2006-11-05 15:40) [23]

всеравно на строке N := GetSystemDirectory(S, MAX_PATH); ошибка: [Pascal Error] Unit1.pas(33): E2010 Incompatible types: "string" and "PAnsiChar". А так все нормально работает:

SetLength(S, MAX_PATH);
N := GetSystemDirectory(@S[1], MAX_PATH);
SetLength(S, N);


 
Ketmar ©   (2006-11-05 15:46) [24]

>[21] Anatoly Podgoretsky(c) 5-Nov-2006, 15:32
>не надо же полностью все писать, кое что надо
>оставить и автору
так это ж раздел "надмозги". тут неписаными правилами думать воспрещается. равно как и читать справку/книги. а ты издеваешься...


 
Anatoly Podgoretsky ©   (2006-11-05 15:50) [25]

> Max_2006  (05.11.2006 15:40:23)  [23]

Опять забыл приведение сделать, а ты сам не можешь догадаться? Тогда не
стоит программировать.


 
Max_2006   (2006-11-05 16:09) [26]

N := GetSystemDirectory(PChar(S), MAX_PATH); так? Я просто где-то видел что @S[1] так лучше, или это не так?


 
Anatoly Podgoretsky ©   (2006-11-05 16:20) [27]

> Max_2006  (05.11.2006 16:09:26)  [26]

Так и это ты должен был понять из сообщения об ошибке.
А лучше или нет - читай обсуждения, их тут два по этой теме.
Понять ты должен сам, тогда навечно, по крайней мере до смены парадигмы.


 
Max_2006   (2006-11-05 17:03) [28]

Я просто хотел научиться писать программы на одном API, а так как там PChar то его и использовать без использования string, чтобы не тратилось время на перевод string в PChar...


 
Anatoly Podgoretsky ©   (2006-11-05 17:09) [29]

> Max_2006  (05.11.2006 17:03:28)  [28]

string полностью совместим с PChar, имеет дополнительные
средства, управляющие его живучестью, уменьшае количество
ошибок, начинающим очень сложно работать с указателями,
с динамическим выделением памяти. Нет ни каких оснований
не использовать. Не хочешь тратить время на приведение, п
отеряешь время и память на работу с динамическим выделени
ем, при том потеряешь больше и ничего не приобретешь.


 
Max_2006   (2006-11-05 17:37) [30]

а как тогда работают в C++ с WinAPI? Там же нету string.. Если только в MFC на сколько я знаю CString (как-то так называется)... а если без MFC(на одном WinAPI), как они используют строки? Судя из цитаты:

> Не хочешь тратить время на приведение, потеряешь время и
> память на работу с динамическим выделением, при том потеряешь
> больше и ничего не приобретешь.

получается так что приложение написанное с использованием string быстрее работает чем с PChar? Т.е. быстрее чем приложение написанное на C++???


 
Anatoly Podgoretsky ©   (2006-11-05 17:41) [31]

Не всегда, но в основном, поскольку оно обладает информацией о размере, а для PChar такой информации нет. А они с ним и работают.

А что тебя так удивляет, что С++ обладает каким то тайным знанием, там даже цикла FOR нет, под его именем идет цикл WHILE. Так же нет массивово в чистом виде, это замаскированый указатель.
И все что касается циклов и строк как правило работает медлеенне.
Ты не читай заверения маркетологов от С++


 
Max_2006   (2006-11-05 17:50) [32]

Я тут еще так подумал, может string передавать в функцию требующая PChar так: Pointer(str)? или всеже лучше PChar(str)?


 
Anatoly Podgoretsky ©   (2006-11-05 17:57) [33]

> Max_2006  (05.11.2006 17:50:32)  [32]

Ну и прикинь, что у тебя получится для пустой строки.
Не надо фантазировать, делай правильно, кроме тех случаев когда ты точно
знаешь зачем ты это Pointer(str) делаешь


 
Max_2006   (2006-11-05 18:10) [34]

Все же я не очень понимаю чем string выигрывает по скорости массив array [0..MAX_PATH] of Char, если выполнять с массивом какиенибудь действия то его придется копировать в новую память и т.д. А как тогда устроен string, я понимаю что по сути дела это только указатель, но а если строка все больше и больше становится, растет так сказать, то по идее память должна как-то динамически увеличиваться или как? Если динамически то на это тоже не мало времени тратится...


 
Ketmar ©   (2006-11-05 18:22) [35]

>[34] Max_2006 5-Nov-2006, 18:10
один фиг.


 
sniknik ©   (2006-11-05 18:24) [36]

> Т.е. быстрее чем приложение написанное на C++???
очень часто да быстрее, и намного (очень намного). имею под боком трех С-шников, есть прецеденты.

> Все же я не очень понимаю чем string выигрывает по скорости массив array [0..MAX_PATH] of Char
массиву ничем, для доступа, для копирования - не придётся узнавать размер строки, копирование можно сделать одной ассемблерной командой, в случае массива (вернее z терминированной строки) чтобы узнать размер придётся ее сканировать, или если делать условие на конечный 0 прям в копировании то все одно придётся делать циклом, кучей команд переноса и проверкой в цикле на 0... одна команда на все копирование 2 такта (примерно естественно), против кучи на каждый перенесённый байт и проверку, на все те же 2 такта... на каждую команду... считай. а лучше читай, найди чего нибудь для начинающих и просто выучи наизусть (по другому видно не доходит).


 
Leonid Troyanovsky ©   (2006-11-05 18:34) [37]


> Max_2006   (05.11.06 17:50) [32]

> Я тут еще так подумал, может string передавать в функцию
> требующая PChar так: Pointer(str)? или всеже лучше PChar(str)?

From Delphi help: Long string types:

It is also possible to typecast a long string to an untyped pointer, using the
syntax Pointer(S), where S is a long string expression. A Pointer typecast
returns the address of the first character of the long string value. Unlike a PChar
typecast, a Pointer typecast returns nil if the string expression is empty.

--
Regards, LVT.


 
Anatoly Podgoretsky ©   (2006-11-05 20:10) [38]

> Max_2006  (05.11.2006 18:10:34)  [34]

Никаких копирований ВинАПИ не делает.


 
Max_2006   (2006-11-05 22:23) [39]


> Никаких копирований ВинАПИ не делает.

А я вообще про строку имел ввиду...


 
Max_2006   (2006-11-05 22:45) [40]

А если нужно расширить массив? т.е. есть массив array [0..20] of Char и он весь занят и его надо расширить, то всеравно надо создавать новый и делать move?



Страницы: 1 2 вся ветка

Текущий архив: 2006.11.26;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.032 c
15-1162458132
Cyrax
2006-11-02 12:02
2006.11.26
Ограничение прав пользователя в Windows XP


1-1160768320
guav
2006-10-13 23:38
2006.11.26
Преобразование вариантных типов


8-1145261176
TRyaSS
2006-04-17 12:06
2006.11.26
Кто знает, подскажите плз, каким образом можно кривые хранить?


15-1162483616
Другой
2006-11-02 19:06
2006.11.26
5000 статей по Delphi.


15-1162810252
m-kirill-2003
2006-11-06 13:50
2006.11.26
Помогите! Срочно!