Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.11.26;
Скачать: [xml.tar.bz2];

Вниз

Работа с 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.57 MB
Время: 0.04 c
2-1156158641
apic
2006-08-21 15:10
2006.11.26
1024 компонента


1-1160978357
id
2006-10-16 09:59
2006.11.26
XML as Registry


2-1162467307
Juju
2006-11-02 14:35
2006.11.26
Теряются пути...


15-1162750116
Mozart
2006-11-05 21:08
2006.11.26
Всё таки хорошо быть богатым :)


15-1163131418
Slider007
2006-11-10 07:03
2006.11.26
С днем рождения ! 10 ноября





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский