Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.02.2009, 10:08   #1
Armorer
Подтвердите свой е-майл
 
Регистрация: 07.04.2007
Сообщений: 120
По умолчанию Вопрос по PChar

Написал простую программу. Все работает кроме функции Convert1, почему она не работает?

Код:
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils,
   Windows;

Function Convert1( S : String ) : String;
begin
 CharToOem( PChar(S), PChar(S) );
 Result := S;
end;

Function Convert2( S : String ) : String;
begin
 CharToOem( @S[1], @S[1] );
 Result := S;
end;

var
 TestStr : String;

begin
 TestStr := 'Строка1';
 CharToOem( PChar(TestStr), PChar(TestStr) );
 Writeln( TestStr );

 TestStr := 'Строка2';
 CharToOem( @TestStr[1], @TestStr[1] );
 Writeln( TestStr );

 Writeln( Convert2( 'Тест' ) );
 Readln;
end.
Когда искал ответ на вопрос, прочитал статью на сайте про PChar. Но вопросов стало еще больше=)

Код:
procedure TForm1.Button1Click(Sender: TObject);
 var S : String;
begin
 S := 'Привет';
 MessageBox(0, @S[1], @S[1],0);
 MessageBox(0, PChar(S), PChar(S),0);
 {Все работает нормально, выводит два раза "Привет"}
end;

procedure TForm1.Button2Click(Sender: TObject);
 var Str1 : String;
     Str2 : String[10];
begin
 Str1 := 'Привет';
 MessageBox(0, @Str1, @Str1,0);
 {Выводит кракозябру, хотя в статье написано

 "Мы всегда пишем MessageBox(0,pchar(str),pchar(str),0);
  Всё нормально. Тот же результат при использовании указателей.
  MessageBox(0,@str,@str,0); "

  У меня не работает.
 }

 Str2 := 'Привет';
 MessageBox(0, @Str2, @Str2,0);
 {Тут выводи лишний символ перед строкой. Как и написано в статье.
 Почему в первом случае не выводит тоже самое?
}
end;
Str1 и Str2 отличаются только типом. Кажется, читал что тип
String[10] равнослиен типу ShortString; Тип String в динамической памяти (почти как дин. массив), тип ShortString статический всегда равен 256 байт.
Но что храниться по адресу @Str1 и @Str2 ?

Вот еще код

Код:
procedure TForm1.Button3Click(Sender: TObject);
 var S1 : String;
     S2 : String[10];
     S3 : ShortString;
begin
 S1 := 'Привет';
 Label1.Caption := IntToStr( Byte( @S1 ) );

 S2 := 'Привет';
 Label2.Caption := IntToStr( Byte( @S2 ) );

 S3 := 'Привет';
 Label3.Caption := IntToStr( Byte( @S3 ) );

 { В итоге на метках написано 64 53 53 }
end;
Тут вообще не понятно =)

По идее
Byte( @S1 ) должно быть равно 6, так как в строке 6 символов.
Armorer вне форума Ответить с цитированием
Старый 10.02.2009, 10:39   #2
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,547
По умолчанию

Дело в том, что тип string сам является указателем на строку, т.е. если записать так:
Код:
var Str1 : String;
begin
 Str1 := 'Привет!';
 MessageBox (0, Pointer (Str1), Pointer (Str1), 0);
Получим "Привет!".
Но, если при объявлении типа string мы явно указываем длину строки, то этот стринг работает как в TurboPascal - массив символов, в котором нулевой элемент содержит длину строки. Т.е. уже не указатель. Поэтому можно записать так:
Код:
var Str1 : String[8];
begin
 Str1 := 'Привет!'#0;
 MessageBox (0, @Str1, @Str1, 0);
На выводе получим "[]Привет!", где [] - нулевой символ (длинна). В конец строки я явно дописал #0, иначе результат мог быть непредсказуемым.
Arigato вне форума Ответить с цитированием
Старый 10.02.2009, 11:20   #3
Armorer
Подтвердите свой е-майл
 
Регистрация: 07.04.2007
Сообщений: 120
По умолчанию

Спасибо, уже понятнее=)

Ещё один вопрос не могу найти в исходниках функцию Length, если на вести на неё и нажать ctrl+лкм то просто перекидывает в модуль System
Поиском тоже найти не получается. Так и с некоторыми другими функциями. Как найти их код?

И последнее =) Почему в первом примере
Код:
Function Convert1( S : String ) : String;
begin
 CharToOem( PChar(S), PChar(S) );
 Result := S;
end;
Программа вылетает при вызове CharToOem( PChar(S), PChar(S) )?

Последний раз редактировалось Armorer; 10.02.2009 в 11:56. Причина: понял почему=)
Armorer вне форума Ответить с цитированием
Старый 10.02.2009, 11:51   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
не могу найти в исходниках функцию Length
А потому что это псевдофункция. Это скорее директива чем функция.

Рекомендую так:
Код:
Function Convert1( S : String ) : pchar;
begin
 getmem(result,length(s));
 CharToOem( PChar(S), (result) );
end;

begin
c:=Convert1('qwee');
end;
I'm learning to live...

Последний раз редактировалось Stilet; 10.02.2009 в 11:55.
Stilet вне форума Ответить с цитированием
Старый 10.02.2009, 12:08   #5
Armorer
Подтвердите свой е-майл
 
Регистрация: 07.04.2007
Сообщений: 120
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
А потому что это псевдофункция. Это скорее директива чем функция.
То есть я никак не могу посмотреть как она и подобные функции реализованы?

Цитата:
Рекомендую так:
Код:
Function Convert1( S : String ) : pchar;
begin
 getmem(result,length(s));
 CharToOem( PChar(S), (result) );
end;

begin
c:=Convert1('qwee');
end;
Спасибо. Работает даже без getmem(result,length(s)). Обязательно память выделять?

Но всеже почему Convert2 работает, а Convert1 нет? Должны работать обе, по моему=)
Код:
Function Convert1( S : String ) : String;
begin
 CharToOem( PChar(S), PChar(S) );
 Result := S;
end;

Function Convert2( S : String ) : String;
begin
 CharToOem( @S[1], @S[1] );
 Result := S;
end;
Armorer вне форума Ответить с цитированием
Старый 10.02.2009, 12:39   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Обязательно память выделять?
Чесслово не знаю, от нужно вспомнить как result устроен.
Я никогда ТАК задачи не решал, как по мне это не лучшее решение.
Цитата:
Должны работать обе, по моему=)
Ну вообще-то источник перезаписывать результатом с ходу не лучший идея.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 11.02.2009, 18:51   #7
Armorer
Подтвердите свой е-майл
 
Регистрация: 07.04.2007
Сообщений: 120
По умолчанию

Видимо никто не знает=)
Тогда еще вопрос по теме, почему возникает предупреждение компилятора Unsafe type 'PChar' ?
возникает на строках вроде этой
Код:
Application.MessageBox( PChar( 'Просмотр документа завешен, произведено ' + IntToStr( Count ) + ' замен.' ), PChar( ProgramName ) );
Предупреждение в обоих вызовах PChar
ProgramName - строковая константа.

Как убрать это предупреждение и что оно означает?
Armorer вне форума Ответить с цитированием
Старый 11.02.2009, 18:57   #8
Kotofff
Участник клуба
 
Аватар для Kotofff
 
Регистрация: 11.01.2009
Сообщений: 1,917
По умолчанию

Не должно предупреждать ни о чем !
Можно текст "предупреждения" увидеть как можно полнее ...
"Заряженному танку в дуло не смотрят" @Dekmer in WoT
Kotofff вне форума Ответить с цитированием
Старый 11.02.2009, 19:43   #9
Armorer
Подтвердите свой е-майл
 
Регистрация: 07.04.2007
Сообщений: 120
По умолчанию

Всё как я написал, выдает два Warning'a Unsafe type 'PChar'
Поискав в яндексе нашел, что это предупреждение означает, что под .NET данный код скомпилирован не будет. То есть если программу писать только под win, то на такой варнинг не надо обращать внимание.

В Delphi6 такой же код ничего ничего не выдает, такое сообщение у меня появляется только в 7мом.

Можно ли отключить только такие предупреждения? Я знаю только директиву {$WARNINIGS OFF} но она отключает все.
Armorer вне форума Ответить с цитированием
Старый 11.02.2009, 21:10   #10
Jeni
Форумчанин
 
Регистрация: 31.05.2007
Сообщений: 486
По умолчанию

Цитата:
Сообщение от Armorer Посмотреть сообщение
Можно ли отключить только такие предупреждения? Я знаю только директиву {$WARNINIGS OFF} но она отключает все.
В опциях проекта есть закладка Compiler Messages, там можно отключать разные типы сообщений. Конкретно для тебя будет интересен пункт Unsafe Type.
Jeni вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
PChar Роман Радер Общие вопросы Delphi 2 02.11.2008 18:50
String to PChar D7_beginner Общие вопросы Delphi 2 21.11.2007 14:05
Access violation на строке вида StrLCopy(PChar(st1),PChar(st2),10); malor Общие вопросы Delphi 1 11.07.2007 13:39
Добавление к pchar EdNovice Общие вопросы Delphi 2 15.04.2007 17:00
Как из string получить PChar??? sis Компоненты Delphi 4 11.02.2007 16:58