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

Вниз

Как совместить два типа PChar и String   Найти похожие ветки 

 
s666   (2004-04-20 22:12) [0]

Подскажите кто может плиз!!!
Как совместить два типа PChar и String.
И как перегонять данные из одного в другой и обратно.


 
s666   (2004-04-20 22:12) [0]

Подскажите кто может плиз!!!
Как совместить два типа PChar и String.
И как перегонять данные из одного в другой и обратно.


 
DrPass ©   (2004-04-20 22:20) [1]

Практически никак. Твой единственный шанс - почитать FAQ


 
DrPass ©   (2004-04-20 22:20) [1]

Практически никак. Твой единственный шанс - почитать FAQ


 
Piter ©   (2004-04-20 22:56) [2]

Не знаю когда Панов все оформит, наверное уже никогда :)
Тем не менее:

В данной мини-статье предлагаю вам рассмотреть поподробнее типы данных PChar и String, так как по ним возникает очень много вопросов в интернете.
Оба этих типа предназначены для хранения произвольного текста. Текст - это набор (масcив) символов в памяти, только разные типы по разному производят хранение этого массива.

PChar
Устройство PChar"а самое элементарное, которое может придти в голову. В памяти компьютера хранится последовательный набор символов, а сам PChar, который является указателем, ссылается на первый символ в памяти (то есть, хранит адрес байта в памяти процесса, который является первым символом строки). Этот символ и последующие и будут составлять строку.
Рассмотрим некий участок памяти:

ялр<e]Г.Тест....U<м3АUhe

В данном месте хранится строка "Тест" плюс я еще выделил несколько байт слева и справа.
Допустим, у буквы "Т" адрес в памяти $00452138. Соответственно, в данном случае PChar и будет равен адресу $00452138, по которому находится первый символ строки.
Но возникает вопрос - а где конец строки? На начало указыват сам PChar, а вот конец строки определяется по завершающему символу. Для PChar он равен #0 в текстовом представлении или, что тоже самое, байту $00 (в примере нулевые байты отображаются как точка ".").

В результате, строка занимает 5 байтов, включая завершающий символ, и занимает адреса в памяти процесса $00452138-$0045213C.

Здесь стоит упомянуть про одну вещь. PChar - это указатель на строку (точнее, на первый символ строки). Но если ввести переменную P:PChar, то @P не будет указывать на первый символ строки. Он будет указывать на область памяти, где хранится указатель на строку.
С первого раза достаточно путано, но на самом деле все логично.
В нашем примере p=$00452138, а вот @p=$0012F5B4.
Если перейти по адресу в памяти $0012F5B4, то мы увидим:

38 21 45 00 30 1E C0 00 (это в шестнадцатеричном виде)

Так как указатель в 32 битных системах занимает те самые 32 бита (то есть 4 байта), то значения по адресу @p=$0012F5B4 равны: 38 21 45 00. А если вспомнить, что числа на платформе  x86 хранятся "задом наперед", то получается 00 45 21 38! А это и есть адрес $00452138, которому и равен P и по которому находится непосредственно наша строка (а точнее первый символ "Т").

Итак, вот что получается. В памяти есть набор символов с завершающим символом в конце. P указывает на первый символ этой строки. @P указывает на указатель строки, то есть указывает на тот участок памяти, где хранится адрес первого символа строки.

String
Сначала определимся, что String - это тип, зависящий от директив компилятора. При директиве {$H+}, которая установлена по умолчанию, String интерпретируется как AnsiString, если {$H-} - то как ShortString.

Итак, PChar не лишен недостатков. Например, вдруг вам захочется сохранить байт 00 в строке (вообще, он не может встречаться в тексте, поэтому и выбран в качестве завершающего символа, но тем не менее). С PChar"ом ничего не получится.
Рассмотрим:


var P:PChar      
...
P := "Я иду" + #0 + " домой";


В результате, в памяти будет строчка "Я иду#0 домой", и PChar будет указывать на букву "Я" в памяти, но при любых операциях с PChar остаток " домой" не будет учитываться, так как после "Я иду" идет завершающий символ, а значит - это конец PChar.

Теперь подумаем - как побороть недостаток PChar"а? Выход прост - пусть строка имеет такой формат:
<количество_символов><сама_строка>.
Именно такой формат имеет ShortString. Первый байт этой строки указывает количество последующих символов. Таким образом, можно хранить любые данные, компьютер не остановится, увидев завершающий символ, так как конец строки определяется по другому признаку. Если длина 15 - то он будет обрабатывать именно 15 символов (байт), независимо от того, что в них хранится. ShortString не имеет завершающего символа в конце, поэтому не совместим с WinApi, где нужно передавать строки именно с завершающим символом.

Недостаток типа ShortString заключается в его названии :) Он достаточно короткий. Так как на длину строки отводится 1 байт, то он не может принимать значение более 255, а значит ShortString не может хранить более 255 символов.

Плавно переходим к типу AnsiString (по умолчанию этому типу и равен String). Тут все достаточно сложно, данная строка хранит размер выделенной памяти, счетчик ссылок, число символов. Мы не будет рассматривать побайтово его структуру в памяти, тем более, что тип недокументирован, а значит его структура может изменяться от одной версии Дельфи к другой. В любом случае, внутренняя реализация скрыта от программиста и использовать тип AnsiString очень удобно.
На размер строки отводится 4 байта, соответственно, AnsiString может хранить огромное количество символов (порядка 2 Гб), что покроет с лихвой любые нужды.
К тому же, AnsiString совместим с типами с завершающими символами в конце. Это означает, что его можно использовать для вызова функций WinApi.
Также стоит упомянуть, что ShortString статический тип, то есть под него однажды выделяют место в памяти и он так и остается там по одному адресу.
AnsiString же тип динамический, эта строка может менять свою длину и "перемещаться" по памяти в поисках наилучшего места для размещения. То есть AnsiString может менять свой адрес в памяти при изменении строки.

Преобразования типов
Итак, как преобразовать тип Pchar к String (AnsiString) и наоборот?

String->PChar
Рассмотрим на примере вызовов функций WinApi, которые принимают параметры типа PChar. А мы работаем в Дельфи и хотим использовать string.

Рассмотрим вызов функции:
function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
которая вызывает на экране появление бокса с сообщением.

Параметры lpText и lpCaption являются PChar.
Указываем компилятору явно преобразовать AnsiString в Pchar:


 
Piter ©   (2004-04-20 22:56) [2]

Не знаю когда Панов все оформит, наверное уже никогда :)
Тем не менее:

В данной мини-статье предлагаю вам рассмотреть поподробнее типы данных PChar и String, так как по ним возникает очень много вопросов в интернете.
Оба этих типа предназначены для хранения произвольного текста. Текст - это набор (масcив) символов в памяти, только разные типы по разному производят хранение этого массива.

PChar
Устройство PChar"а самое элементарное, которое может придти в голову. В памяти компьютера хранится последовательный набор символов, а сам PChar, который является указателем, ссылается на первый символ в памяти (то есть, хранит адрес байта в памяти процесса, который является первым символом строки). Этот символ и последующие и будут составлять строку.
Рассмотрим некий участок памяти:

ялр<e]Г.Тест....U<м3АUhe

В данном месте хранится строка "Тест" плюс я еще выделил несколько байт слева и справа.
Допустим, у буквы "Т" адрес в памяти $00452138. Соответственно, в данном случае PChar и будет равен адресу $00452138, по которому находится первый символ строки.
Но возникает вопрос - а где конец строки? На начало указыват сам PChar, а вот конец строки определяется по завершающему символу. Для PChar он равен #0 в текстовом представлении или, что тоже самое, байту $00 (в примере нулевые байты отображаются как точка ".").

В результате, строка занимает 5 байтов, включая завершающий символ, и занимает адреса в памяти процесса $00452138-$0045213C.

Здесь стоит упомянуть про одну вещь. PChar - это указатель на строку (точнее, на первый символ строки). Но если ввести переменную P:PChar, то @P не будет указывать на первый символ строки. Он будет указывать на область памяти, где хранится указатель на строку.
С первого раза достаточно путано, но на самом деле все логично.
В нашем примере p=$00452138, а вот @p=$0012F5B4.
Если перейти по адресу в памяти $0012F5B4, то мы увидим:

38 21 45 00 30 1E C0 00 (это в шестнадцатеричном виде)

Так как указатель в 32 битных системах занимает те самые 32 бита (то есть 4 байта), то значения по адресу @p=$0012F5B4 равны: 38 21 45 00. А если вспомнить, что числа на платформе  x86 хранятся "задом наперед", то получается 00 45 21 38! А это и есть адрес $00452138, которому и равен P и по которому находится непосредственно наша строка (а точнее первый символ "Т").

Итак, вот что получается. В памяти есть набор символов с завершающим символом в конце. P указывает на первый символ этой строки. @P указывает на указатель строки, то есть указывает на тот участок памяти, где хранится адрес первого символа строки.

String
Сначала определимся, что String - это тип, зависящий от директив компилятора. При директиве {$H+}, которая установлена по умолчанию, String интерпретируется как AnsiString, если {$H-} - то как ShortString.

Итак, PChar не лишен недостатков. Например, вдруг вам захочется сохранить байт 00 в строке (вообще, он не может встречаться в тексте, поэтому и выбран в качестве завершающего символа, но тем не менее). С PChar"ом ничего не получится.
Рассмотрим:


var P:PChar      
...
P := "Я иду" + #0 + " домой";


В результате, в памяти будет строчка "Я иду#0 домой", и PChar будет указывать на букву "Я" в памяти, но при любых операциях с PChar остаток " домой" не будет учитываться, так как после "Я иду" идет завершающий символ, а значит - это конец PChar.

Теперь подумаем - как побороть недостаток PChar"а? Выход прост - пусть строка имеет такой формат:
<количество_символов><сама_строка>.
Именно такой формат имеет ShortString. Первый байт этой строки указывает количество последующих символов. Таким образом, можно хранить любые данные, компьютер не остановится, увидев завершающий символ, так как конец строки определяется по другому признаку. Если длина 15 - то он будет обрабатывать именно 15 символов (байт), независимо от того, что в них хранится. ShortString не имеет завершающего символа в конце, поэтому не совместим с WinApi, где нужно передавать строки именно с завершающим символом.

Недостаток типа ShortString заключается в его названии :) Он достаточно короткий. Так как на длину строки отводится 1 байт, то он не может принимать значение более 255, а значит ShortString не может хранить более 255 символов.

Плавно переходим к типу AnsiString (по умолчанию этому типу и равен String). Тут все достаточно сложно, данная строка хранит размер выделенной памяти, счетчик ссылок, число символов. Мы не будет рассматривать побайтово его структуру в памяти, тем более, что тип недокументирован, а значит его структура может изменяться от одной версии Дельфи к другой. В любом случае, внутренняя реализация скрыта от программиста и использовать тип AnsiString очень удобно.
На размер строки отводится 4 байта, соответственно, AnsiString может хранить огромное количество символов (порядка 2 Гб), что покроет с лихвой любые нужды.
К тому же, AnsiString совместим с типами с завершающими символами в конце. Это означает, что его можно использовать для вызова функций WinApi.
Также стоит упомянуть, что ShortString статический тип, то есть под него однажды выделяют место в памяти и он так и остается там по одному адресу.
AnsiString же тип динамический, эта строка может менять свою длину и "перемещаться" по памяти в поисках наилучшего места для размещения. То есть AnsiString может менять свой адрес в памяти при изменении строки.

Преобразования типов
Итак, как преобразовать тип Pchar к String (AnsiString) и наоборот?

String->PChar
Рассмотрим на примере вызовов функций WinApi, которые принимают параметры типа PChar. А мы работаем в Дельфи и хотим использовать string.

Рассмотрим вызов функции:
function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
которая вызывает на экране появление бокса с сообщением.

Параметры lpText и lpCaption являются PChar.
Указываем компилятору явно преобразовать AnsiString в Pchar:


 
Piter ©   (2004-04-20 22:57) [3]

procedure TForm1.Button1Click(Sender: TObject);
var s1, s2:string;
begin
s1:="text";
s2:="caption";
MessageBox(0,PChar(s1),PChar(s2),0);
end;


Можно сделать проще:
MessageBox(0,"text","caption",0);
при этом компилятор сам приведет текстовые строки к формату PChar и передаст в функцию MessageBox.

Тут все ясно. Но что делать, когда нужно передать PChar для того, чтобы система заполнила его каким-нибудь значением?

Рассмотрим вызов функции
GetWindowsDirectory(lpBuffer: PChar; uSize: UINT): UINT;
которая возвращает путь к директории Windows. А точнее записывает его в передаваемую переменную lpBuffer, а uSize указывает размер этого заготовленного буфера.

procedure TForm1.Button1Click(Sender: TObject);
var s:string;
   Length: integer;
begin
 setlength(s,MAX_PATH);
 Length := GetWindowsDirectory(PChar(s),MAX_PATH);
 setlength(s,Length);
 ...


В общем, тоже самое, но только НЕ ЗАБЫВАЕМ ВЫДЕЛИТЬ ПАМЯТЬ для переменной S перед использованием:
setlength(s,MAX_PATH)
После вызова GetWindowsDirectory в строке S также будет находится MAX_PATH символов. Причем, большинство их них пробелы, которые вовсе не нужны. Поэтому, перед использованием такой строки отрежем ненужные символы. Так как GetWindowsDirectory возвращает количество символов, то код очевиден:
setlength(s,Length);
Можно обойтись и без переменной Length:

procedure TForm1.Button1Click(Sender: TObject);
var s:string;
begin
 setlength(s,MAX_PATH);
 setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));
 ...


Ну а теперь рассмотрим просто пример конвертирования:


var p:PChar;
...
p:=PChar(s); // где-то есть переменная s и в ней хранится некая строка


При этом p начинает указывать на ту же область памяти, что и s. И все будет замечательно, пока с s ничего не происходит. Но вот например:

var p:PChar;
   s:string;
begin
 setlength(s,MAX_PATH);
 setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));
 p:=PChar(s);
 s:=s+"SomeText";
 ...


Итак, строчками
setlength(s,MAX_PATH);
setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));

в s заносится путь к директории windows. В памяти таким образом появляется некая строка, допустим "c:\windows", которой и равна s.
После чего идет
p:=PChar(s);
при этом p начинает указывать на ту же область памяти, где находится строка "c:\windows".
Потом s присваивается другое значение
s:=s+"SomeText";
А точнее к s должно быть прибавлено "SomeText". При этом менеджер памяти анализирует ситуацию, можно ли приписать данный текст прямо в ту же область памяти. Если память после "c:\windows" не занята, то он приписывает нужное количество символов. При этом S будет указывать по прежнему на тот же адрес в памяти, только увеличится счетчик символов. Соответстенно, и с P, указывающим туда же, будет все нормально. И после завершения кода P будет указывать на строчку "c:\windowsSomeText".

Но если невозможно подряд разместить все новые символы, то менеджер памяти будет искать "дырку" в памяти, свободную для размещения всех символов. При этом память, где хранится текущее "c:\windows" будет объявлена свободной, резервируется место для новой строки в другом месте, туда записывается значение "c:\windowsSomeText" и S начинает указывать на новый участок памяти, где хранится новое значение строки. А P по прежнему указывает на старый участок памяти! Скорее всего, там будет продолжать хранится строчка "c:\windows", потому как память никто не зачищал, но эта память является уже свободной. И в случае чего, данное место будет зарезервировано под иные нужды и там разместятся произвольные данные, в результате P будет указывать на черт знает что.
Для демонстрации можно выполнить такой пример:

var p:PChar;
   s:string;
   s2:string;
begin
 setlength(s,MAX_PATH);
 setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));
 p:=PChar(s);
 setlength(s2,1);
 s:=s+"SomeText";
end;


Тоже самое, но добавилась строчка setlength(s2,1);
Рассмотрим еще раз:
p:=PChar(s)
Что s, что P указывают на одну и ту же область памяти.
А потом
setlength(s2,1);
если ничего неожиданного не случится, то менеджер памяти Дельфи выделит под переменную s2 место сразу после s.
В результате, следующая строчка
s:=s+"SomeText";
будет обработана не так, как в предыдущем примере.
Места для добавления "SomeText" по старому адресу уже не хватит (ведь после s идет сразу s2), будет выбрано новое место и s перенесена туда, а "старая" память освобождена. Но P по прежнему ссылается на старое место! После выполнения этого кода, P скорее всего будет указывать на область памяти со значением "c:\windows" (но не факт, так как эта область памяти является свободной и может быть занята чем угодно), а не "c:\windowsSomeText"!
Поэтому будьте внимательны. Если S изменилось, то стоит перепресвоить PChar:
s:=s+"SomeText";
p:=PChar(s);


PChar->String

ну тут все просто. Если P указывает на некую строчку в памяти:

var s:string;
...
s:=p;


То произойдет неявное преобразование типов. При этом строка, на которую указывает p копируется в другую область памяти и s начинает указывать именно туда. В результате, просто появляются две переменные с одинаковыми значениями. И работа их друг от друга не зависит.


 
Piter ©   (2004-04-20 22:57) [3]

procedure TForm1.Button1Click(Sender: TObject);
var s1, s2:string;
begin
s1:="text";
s2:="caption";
MessageBox(0,PChar(s1),PChar(s2),0);
end;


Можно сделать проще:
MessageBox(0,"text","caption",0);
при этом компилятор сам приведет текстовые строки к формату PChar и передаст в функцию MessageBox.

Тут все ясно. Но что делать, когда нужно передать PChar для того, чтобы система заполнила его каким-нибудь значением?

Рассмотрим вызов функции
GetWindowsDirectory(lpBuffer: PChar; uSize: UINT): UINT;
которая возвращает путь к директории Windows. А точнее записывает его в передаваемую переменную lpBuffer, а uSize указывает размер этого заготовленного буфера.

procedure TForm1.Button1Click(Sender: TObject);
var s:string;
   Length: integer;
begin
 setlength(s,MAX_PATH);
 Length := GetWindowsDirectory(PChar(s),MAX_PATH);
 setlength(s,Length);
 ...


В общем, тоже самое, но только НЕ ЗАБЫВАЕМ ВЫДЕЛИТЬ ПАМЯТЬ для переменной S перед использованием:
setlength(s,MAX_PATH)
После вызова GetWindowsDirectory в строке S также будет находится MAX_PATH символов. Причем, большинство их них пробелы, которые вовсе не нужны. Поэтому, перед использованием такой строки отрежем ненужные символы. Так как GetWindowsDirectory возвращает количество символов, то код очевиден:
setlength(s,Length);
Можно обойтись и без переменной Length:

procedure TForm1.Button1Click(Sender: TObject);
var s:string;
begin
 setlength(s,MAX_PATH);
 setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));
 ...


Ну а теперь рассмотрим просто пример конвертирования:


var p:PChar;
...
p:=PChar(s); // где-то есть переменная s и в ней хранится некая строка


При этом p начинает указывать на ту же область памяти, что и s. И все будет замечательно, пока с s ничего не происходит. Но вот например:

var p:PChar;
   s:string;
begin
 setlength(s,MAX_PATH);
 setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));
 p:=PChar(s);
 s:=s+"SomeText";
 ...


Итак, строчками
setlength(s,MAX_PATH);
setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));

в s заносится путь к директории windows. В памяти таким образом появляется некая строка, допустим "c:\windows", которой и равна s.
После чего идет
p:=PChar(s);
при этом p начинает указывать на ту же область памяти, где находится строка "c:\windows".
Потом s присваивается другое значение
s:=s+"SomeText";
А точнее к s должно быть прибавлено "SomeText". При этом менеджер памяти анализирует ситуацию, можно ли приписать данный текст прямо в ту же область памяти. Если память после "c:\windows" не занята, то он приписывает нужное количество символов. При этом S будет указывать по прежнему на тот же адрес в памяти, только увеличится счетчик символов. Соответстенно, и с P, указывающим туда же, будет все нормально. И после завершения кода P будет указывать на строчку "c:\windowsSomeText".

Но если невозможно подряд разместить все новые символы, то менеджер памяти будет искать "дырку" в памяти, свободную для размещения всех символов. При этом память, где хранится текущее "c:\windows" будет объявлена свободной, резервируется место для новой строки в другом месте, туда записывается значение "c:\windowsSomeText" и S начинает указывать на новый участок памяти, где хранится новое значение строки. А P по прежнему указывает на старый участок памяти! Скорее всего, там будет продолжать хранится строчка "c:\windows", потому как память никто не зачищал, но эта память является уже свободной. И в случае чего, данное место будет зарезервировано под иные нужды и там разместятся произвольные данные, в результате P будет указывать на черт знает что.
Для демонстрации можно выполнить такой пример:

var p:PChar;
   s:string;
   s2:string;
begin
 setlength(s,MAX_PATH);
 setlength(s,GetWindowsDirectory(PChar(s),MAX_PATH));
 p:=PChar(s);
 setlength(s2,1);
 s:=s+"SomeText";
end;


Тоже самое, но добавилась строчка setlength(s2,1);
Рассмотрим еще раз:
p:=PChar(s)
Что s, что P указывают на одну и ту же область памяти.
А потом
setlength(s2,1);
если ничего неожиданного не случится, то менеджер памяти Дельфи выделит под переменную s2 место сразу после s.
В результате, следующая строчка
s:=s+"SomeText";
будет обработана не так, как в предыдущем примере.
Места для добавления "SomeText" по старому адресу уже не хватит (ведь после s идет сразу s2), будет выбрано новое место и s перенесена туда, а "старая" память освобождена. Но P по прежнему ссылается на старое место! После выполнения этого кода, P скорее всего будет указывать на область памяти со значением "c:\windows" (но не факт, так как эта область памяти является свободной и может быть занята чем угодно), а не "c:\windowsSomeText"!
Поэтому будьте внимательны. Если S изменилось, то стоит перепресвоить PChar:
s:=s+"SomeText";
p:=PChar(s);


PChar->String

ну тут все просто. Если P указывает на некую строчку в памяти:

var s:string;
...
s:=p;


То произойдет неявное преобразование типов. При этом строка, на которую указывает p копируется в другую область памяти и s начинает указывать именно туда. В результате, просто появляются две переменные с одинаковыми значениями. И работа их друг от друга не зависит.


 
Gero ©   (2004-04-20 23:12) [4]

> Piter ©   (20.04.04 22:57)
Сейчас тебя спросят: "А нельзя ли поподробнее?" :)


 
Gero ©   (2004-04-20 23:12) [4]

> Piter ©   (20.04.04 22:57)
Сейчас тебя спросят: "А нельзя ли поподробнее?" :)


 
Piter ©   (2004-04-20 23:19) [5]

Блин, сам перечитал... действительно, путанно написано. Надо переписать.


 
Piter ©   (2004-04-20 23:19) [5]

Блин, сам перечитал... действительно, путанно написано. Надо переписать.


 
Gero ©   (2004-04-20 23:23) [6]

> s666
Хоть бы спасибо сказал


 
Gero ©   (2004-04-20 23:23) [6]

> s666
Хоть бы спасибо сказал


 
kaif ©   (2004-04-21 00:16) [7]

А что этот вопрос делает в Потрепацца?
Нормальный вопрос, ИМХО.
И ответ я бы дал короткий:

var
 P: PChar;
 s: string;
begin
 P := "Вася";
 s := StrPas(P); //преобразование PChar -> string
 P := PChar(s); //преобразование string -> PChar
end;


 
kaif ©   (2004-04-21 00:16) [7]

А что этот вопрос делает в Потрепацца?
Нормальный вопрос, ИМХО.
И ответ я бы дал короткий:

var
 P: PChar;
 s: string;
begin
 P := "Вася";
 s := StrPas(P); //преобразование PChar -> string
 P := PChar(s); //преобразование string -> PChar
end;


 
Игорь Шевченко ©   (2004-04-21 00:25) [8]

kaif ©   (21.04.04 00:16)

Две копейки можно?

Вместо:
s := StrPas(P); //преобразование PChar -> string
Следует читать:
s := P; //преобразование PChar -> string

С уважением,


 
Игорь Шевченко ©   (2004-04-21 00:25) [8]

kaif ©   (21.04.04 00:16)

Две копейки можно?

Вместо:
s := StrPas(P); //преобразование PChar -> string
Следует читать:
s := P; //преобразование PChar -> string

С уважением,


 
Anatoly Podgoretsky ©   (2004-04-21 00:28) [9]

S := P;
S := PChar(P)
S := StrPas(P);

Объяснить различия

P := S;
P := S[1];
P := "Вася";

Объяснить ощибки и проблемы.


 
Anatoly Podgoretsky ©   (2004-04-21 00:28) [9]

S := P;
S := PChar(P)
S := StrPas(P);

Объяснить различия

P := S;
P := S[1];
P := "Вася";

Объяснить ощибки и проблемы.


 
kaif ©   (2004-04-21 10:33) [10]

Ну вот это уже похоже на обсуждение.

Вот Help:


Converts null-terminated string to a Pascal string.

function StrPas(const Str: PChar): string;

Description

This function is provided for backwards compatibility only. To convert a null terminated string to a Pascal-type string, use a typecast or an assignment.


Функция оставлена только для обратной совместимости версий языка. А вообще для преобразования строки типа PChar в паскалевскую строку использйте приведение типов или присовение.
-------------------------------------------

Теперь встречный вопрос. А можно использовать функции for backwards compatibility ? Ведь это не obsolete - функция, чтобы краснеть в душе и стесняться на людях. Если мы напишем s := StrPas(p), то любой компилятор (возможно даже самый древний) поймет.

Или я неправ?

Кстати, мне кажется, что в статье имеет смысл все же пару слов сказать про то, как эволюционировала совместимость PChar и string от версии к версии.
---------------------------
Но я все равно не понимаю, как это оказалось в Потрепацца.
Возможно даже автор вопроса попросту потерял эту ветку, наткнувшись на что-нибудь вроде "ветка была удалена или перемещена". Например, ткнул с дуру "Чтобы не потерять эту дискуссию, сделайте закладку". Потом через часик зашел - ветки нет. Может быть человек не знает, о том, что на Мастерах форумы постепенно перемещаются в Потрепацца.


 
kaif ©   (2004-04-21 10:33) [10]

Ну вот это уже похоже на обсуждение.

Вот Help:


Converts null-terminated string to a Pascal string.

function StrPas(const Str: PChar): string;

Description

This function is provided for backwards compatibility only. To convert a null terminated string to a Pascal-type string, use a typecast or an assignment.


Функция оставлена только для обратной совместимости версий языка. А вообще для преобразования строки типа PChar в паскалевскую строку использйте приведение типов или присовение.
-------------------------------------------

Теперь встречный вопрос. А можно использовать функции for backwards compatibility ? Ведь это не obsolete - функция, чтобы краснеть в душе и стесняться на людях. Если мы напишем s := StrPas(p), то любой компилятор (возможно даже самый древний) поймет.

Или я неправ?

Кстати, мне кажется, что в статье имеет смысл все же пару слов сказать про то, как эволюционировала совместимость PChar и string от версии к версии.
---------------------------
Но я все равно не понимаю, как это оказалось в Потрепацца.
Возможно даже автор вопроса попросту потерял эту ветку, наткнувшись на что-нибудь вроде "ветка была удалена или перемещена". Например, ткнул с дуру "Чтобы не потерять эту дискуссию, сделайте закладку". Потом через часик зашел - ветки нет. Может быть человек не знает, о том, что на Мастерах форумы постепенно перемещаются в Потрепацца.


 
panov ©   (2004-04-21 10:35) [11]

>kaif

Автору здесь больше нравится.
Хотя, если уж так хочется, то пожалуйста, поехали в основную...


 
panov ©   (2004-04-21 10:35) [11]

>kaif

Автору здесь больше нравится.
Хотя, если уж так хочется, то пожалуйста, поехали в основную...


 
Anatoly Podgoretsky ©   (2004-04-21 10:54) [12]

Для обратной совместимости означает, что старый проект может перемещаться в новый без переделки, но это не означает что в новом проекте стоит использовать эти функции.
Кроме того надо учесть, что с тех пор появился новый типы string, наряду со старыи (ShortString), где эта функция была необходима, появилось еще две AnsiString, которая совместима с PChar, и WideString.

И еще одно, до определенной версии Дельфи StrPas была полностью совместима, но потом ее расширили за пределы 255 символов и пара StrPas/PasStr стала не совсем совместима, но это не проблема, поскольку не стоит ее использовать для AnsiString.


 
Anatoly Podgoretsky ©   (2004-04-21 10:54) [12]

Для обратной совместимости означает, что старый проект может перемещаться в новый без переделки, но это не означает что в новом проекте стоит использовать эти функции.
Кроме того надо учесть, что с тех пор появился новый типы string, наряду со старыи (ShortString), где эта функция была необходима, появилось еще две AnsiString, которая совместима с PChar, и WideString.

И еще одно, до определенной версии Дельфи StrPas была полностью совместима, но потом ее расширили за пределы 255 символов и пара StrPas/PasStr стала не совсем совместима, но это не проблема, поскольку не стоит ее использовать для AnsiString.


 
kaif ©   (2004-04-21 11:01) [13]

2 panov ©   (21.04.04 10:35) [11]
 Видимо я был не прав. Я почему-то не подумал, что автор сам задал этот вопрос с "Потрепаться". А вопрос действительно интересный. Но в любом случае, мне кажется, что здесь его как-то уютнее обсуждать.

2 Anatoly Podgoretsky ©   (21.04.04 10:54) [12]
 Для обратной совместимости означает, что старый проект может перемещаться в новый без переделки, но это не означает что в новом проекте стоит использовать эти функции.

 Согласен, но есть еще писатели компонентов. Они пишут исходный код практически для всех версий, выше 1. Поэтому мне и интересно, с какой версии начиная StrPas не испрользуется. Неужели начиная со 2 ?


 
kaif ©   (2004-04-21 11:01) [13]

2 panov ©   (21.04.04 10:35) [11]
 Видимо я был не прав. Я почему-то не подумал, что автор сам задал этот вопрос с "Потрепаться". А вопрос действительно интересный. Но в любом случае, мне кажется, что здесь его как-то уютнее обсуждать.

2 Anatoly Podgoretsky ©   (21.04.04 10:54) [12]
 Для обратной совместимости означает, что старый проект может перемещаться в новый без переделки, но это не означает что в новом проекте стоит использовать эти функции.

 Согласен, но есть еще писатели компонентов. Они пишут исходный код практически для всех версий, выше 1. Поэтому мне и интересно, с какой версии начиная StrPas не испрользуется. Неужели начиная со 2 ?


 
Anatoly Podgoretsky ©   (2004-04-21 11:05) [14]

kaif ©   (21.04.04 11:01) [13]
Ненужен с той как появился AnsiString и нужен для ShortString, хотя я этот тип уже давно не использую, может уже заложили атоматическое преобразование, думаю что нет, поскольку нет механизма счетчика ссылок и отсутствия контроля за длиной.


 
Anatoly Podgoretsky ©   (2004-04-21 11:05) [14]

kaif ©   (21.04.04 11:01) [13]
Ненужен с той как появился AnsiString и нужен для ShortString, хотя я этот тип уже давно не использую, может уже заложили атоматическое преобразование, думаю что нет, поскольку нет механизма счетчика ссылок и отсутствия контроля за длиной.


 
Плохиш   (2004-04-21 11:13) [15]

Может в исходник StrPas посмотрим ;-)


 
Плохиш   (2004-04-21 11:13) [15]

Может в исходник StrPas посмотрим ;-)


 
DiamondShark ©   (2004-04-21 11:17) [16]

Странный какой-то backwards compatibility.
В BP7 спокойно работало
var
 S: string[5];
 P: PChar;
begin
 P := "1234567890";
 S := P;
 writeln(S);
end;
результат:
12345


 
DiamondShark ©   (2004-04-21 11:17) [16]

Странный какой-то backwards compatibility.
В BP7 спокойно работало
var
 S: string[5];
 P: PChar;
begin
 P := "1234567890";
 S := P;
 writeln(S);
end;
результат:
12345


 
Плохиш   (2004-04-21 11:21) [17]

>DiamondShark ©   (21.04.04 11:17) [16]

> Странный какой-то backwards compatibility.
> В BP7 спокойно работало

А сейчас, что беспокойно работает?


 
Плохиш   (2004-04-21 11:21) [17]

>DiamondShark ©   (21.04.04 11:17) [16]

> Странный какой-то backwards compatibility.
> В BP7 спокойно работало

А сейчас, что беспокойно работает?


 
DiamondShark ©   (2004-04-21 11:27) [18]


> Плохиш   (21.04.04 11:21) [17]
> >DiamondShark ©   (21.04.04 11:17) [16]
>
> > Странный какой-то backwards compatibility.
> > В BP7 спокойно работало
>
> А сейчас, что беспокойно работает?

Сейчас ещё спокойнее ;-)
Вот я и говорю: странный какой-то компатибилити...


 
DiamondShark ©   (2004-04-21 11:27) [18]


> Плохиш   (21.04.04 11:21) [17]
> >DiamondShark ©   (21.04.04 11:17) [16]
>
> > Странный какой-то backwards compatibility.
> > В BP7 спокойно работало
>
> А сейчас, что беспокойно работает?

Сейчас ещё спокойнее ;-)
Вот я и говорю: странный какой-то компатибилити...


 
Андрей Сенченко ©   (2004-04-21 11:31) [19]

>> Piter ©   (20.04.04 22:56) [2]

Хорошее описание. Под конец только несколько сумбурно, видимо писал "на одном дыхании" и подустал


 
Андрей Сенченко ©   (2004-04-21 11:31) [19]

>> Piter ©   (20.04.04 22:56) [2]

Хорошее описание. Под конец только несколько сумбурно, видимо писал "на одном дыхании" и подустал



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

Форум: "Основная";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.63 MB
Время: 0.035 c
6-1079623700
suschek
2004-03-18 18:28
2004.05.09
Звук в терминальной сесии


1-1082388392
Тимохов
2004-04-19 19:26
2004.05.09
Thread.Terminated II.


6-1079671581
Pete
2004-03-19 07:46
2004.05.09
TServerSocket &amp; TClientSocket


3-1081482578
User_OKA
2004-04-09 07:49
2004.05.09
Сортировка


1-1082433197
Bond
2004-04-20 07:53
2004.05.09
Печать





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский