Форум: "Основная";
Текущий архив: 2004.01.26;
Скачать: [xml.tar.bz2];
ВнизПреобразование в DOS Найти похожие ветки
← →
Zamik (2004-01-14 10:08) [0]Люди помогите начинающем.
Нужно писать в файлик строки в DOS формате.
Пожалуйста пример кода.
← →
[lamer]Barmaglot (2004-01-14 10:11) [1]Из кодировки виндовс в кодировку Dos перекодируется с помощью функции - CharToOem или CharToOemBuff.
← →
YuRock (2004-01-14 10:13) [2]
var
S: String;
begin
...
CharToOem(PChar(S), PChar(S));
...
end;
Можно так например..
← →
Zamik (2004-01-14 10:51) [3]При использовании
YuRock © (14.01.04 10:13) [2]
Delphi выдает ошибку:
Access violation at address 77D34CBD in module "user32.dll"
Помогите погибаю.
← →
alex_*** (2004-01-14 10:55) [4]если хочешь чтоб быстро помогали - приводи source
← →
BiN (2004-01-14 10:57) [5]Zamik © (14.01.04 10:51) [3]
function W2DOS(const Buf:string):string;
begin
SetLength(Result, Length(Buf);
CharToOemBuf(Pchar(Buf), @Result[1], Length(Buf));
end;
← →
Zamik (2004-01-14 10:59) [6]есть вот такой код
procedure TForm1.Button1Click(Sender: TObject);
var
S: String;
begin
s:="получилось?";
CharToOem(PChar(S), PChar(S));
end;
при исполнении вот этой строки
CharToOem(PChar(S), PChar(S));
выдает
Access violation at address 77D34CBD in module "user32.dll"
Не знаю что и думать. Помогите мастера.
← →
PVOzerski (2004-01-14 11:05) [7]А вот так работает:
CharToOem(PChar(@S[1]), PChar(@S[1]));
А почему не работает CharToOem(PChar(S), PChar(S)); - в самом деле, интересно...
← →
[lamer]Barmaglot (2004-01-14 11:10) [8]тогда уж либо
CharToOem(PChar(S[1]), PChar(S[1]));
либо
CharToOem(@S[1], @S[1]);
Все просто сама строка начинается с места S[1], до этого момента идет описание структуры, которое преобразованию естественно не подлежит...
← →
Zamik (2004-01-14 11:13) [9]Всем спасибо Все прекрасно работает.
← →
alex_*** (2004-01-14 11:16) [10][8] - Ты хочешь сказать что PChar(S) не даст адрес первого элемента строки?
← →
PVOzerski (2004-01-14 11:26) [11]<[8] - Ты хочешь сказать что PChar(S) не даст адрес первого элемента строки?
Вот это-то и интересно. Я до сих пор думал так же. Но вот тестик.
procedure TForm1.Button1Click(Sender: TObject);
var
s:string;
begin
s:="Фигня";
Edit1.Text:=IntToHex(longint(pChar(s)),0)+" "+IntToHex(longint(@s[1]),0);
end;
И результат:
426BEC BF3430
← →
[lamer]Barmaglot (2004-01-14 11:27) [12]Нет он конечно даст, но это будет указатель на структуру, то есть не на то место где у тебя хранится строка...
← →
PVOzerski (2004-01-14 11:29) [13]Кажется, разобрался: это опять шутки оптимизатора.
В следующем примере адреса имели честь совпасть.
procedure TForm1.Button1Click(Sender: TObject);
var
s:string;
begin
s:=Edit1.Text;
Edit1.Text:=IntToHex(longint(pChar(s)),0)+" "+IntToHex(longint(@s[1]),0);
end;
А разница в том, что в 1-м моем примере строковой переменной присваивалась константа, а во 2-м - не константа.
← →
Андрей Сенченко (2004-01-14 11:31) [14]PVOzerski © (14.01.04 11:05) [7]
А почему не работает CharToOem(PChar(S), PChar(S)); - в самом деле, интересно...
Уже натыкался на это не раз. И даже здесь это обсуждали около месяца назад.
В итоге вот такая функция вроде как решает проблемы
Function WinToDos (stWin : string) : string;
var
stDOS : pchar;
begin
getmem(stDOS,1048);
CharToOem(pchar(stWIN),stDOS);
WinToDos := string(stDOS);
freemem(stDOS);
end;
← →
alex_*** (2004-01-14 11:34) [15]Оптимизатор must die - проблем больше чем пользы ))
[12] - сам себе противоречишь. Адрес первого эл-та - это адрес првого эл-та, а не адрес структуры описания.
← →
[lamer]Barmaglot (2004-01-14 11:39) [16]Кто тебе сказал, что PChar возвращает указатель на первый элемент? Первый элемент в строке (s[0]) это насколько я помню длина строки...
← →
alex_*** (2004-01-14 11:43) [17]>Первый элемент в строке (s[0]) это насколько я помню длина строки... - для ShortString
← →
BiN (2004-01-14 11:44) [18]lamer]Barmaglot © (14.01.04 11:39) [16]
...было раньше
← →
alex_*** (2004-01-14 11:46) [19]sorry... первый эл-т строки начинается с первой позиции s[1].
А s[0] - компилер будет ругаться.
← →
[lamer]Barmaglot (2004-01-14 11:54) [20]для длинных строк тоже самое (может только в Delphi 6 изменили?). Для проверки запусти этот код...
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
p: pInteger;
begin
s:="lamer";
p:=@s[1];
dec(p,1);
Edit1.text:=inttostr(p^);
end;
← →
alex_*** (2004-01-14 12:09) [21]ну и что.. . Первым элементом является s[1] и PChar(s) укажет на него.
попробуй
ShowMessage(String( PChar(s) ));
← →
YuRock (2004-01-14 12:51) [22]> А почему не работает CharToOem(PChar(S), PChar(S)); - в самом деле, интересно...
Может потому, что S описано как const, т.е. менять его нельзя?
← →
AKul (2004-01-14 12:52) [23]В типе String (в Delphi) индекс может изменяться от 1 и выше.
Элемент с индексом 0 не существует. Поэтому @S==@S[1]!;
Я тут провел маленькое исследование, если кому интересно:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
S: String;
begin
s:="получилось?";
CharToOem(PChar(S), PChar(S));
end;
не работает по следующей причине:
Как известно, строковые константы Delphi располагает в секции кода, которая обычно имеет флаг ReadOnly.
При компиляции строки s:="получилось?"; Delphi генерирует код вида @s:=@"получилось?", т.е. s указывает на участок памяти, расположенный в секции кода (не записываемый). При попытке записи по @s функцией CharToOEM и возникает ошибка.
При:
CharToOem(PChar(@S[1]), PChar(@S[1]));
компилятор передает указатель на динамически созданную копию строки S.
← →
AKul (2004-01-14 13:08) [24]Да, забыл сказать, что исследование проводил на коде, сгенерированом Delphi 5. Может новые версии делают по другому (хотя наврядли).
← →
PVOzerski (2004-01-14 14:17) [25]2AKul:
почти со всем согласен, кроме одного.
>При:
> CharToOem(PChar(@S[1]), PChar(@S[1]));
>компилятор передает указатель на динамически созданную копию строки S.
А вот не должно быть такого, поскольку здесь совершенно "тупой" typecast. Можно вообще написать CharToOem(@S[1],@S[1]);, и это будет работать. IMHO, здесь имеет место быть другое, а именно, по наличию адресного оператора на этапе компиляции определяется, что тело строки нельзя делать read-only. Или что-то подобное.
← →
AKul (2004-01-14 14:53) [26]to PVOzerski © (14.01.04 14:17) [25]:
Согласен, что не должно быть такого, но то что я писал - это не предположение, а то что я "вытянул" из продизассемблированного кода.
При этом "тупом" преобразовании типа Delphi вызывает функцию UniqueString, в которой происходит вызов функции NewAnsiString. Полученный указатель и передается в функцию CharToOEM.
Если не веришь - проверь.
← →
PVOzerski (2004-01-14 15:37) [27]>Если не веришь - проверь
Пожалуй, поверю: дизассемблировать лень :^) Однако всё это впечатляет. Самое удивительное, в таком разе, что при преобразовании pchar(string) аналогичных действий не производится.
← →
VMcL (2004-01-14 15:52) [28]>>Zamik © (14.01.04 10:59) [6]
>есть вот такой код
>procedure TForm1.Button1Click(Sender: TObject);
>var
>S: String;
>begin
>s:="получилось?";
>CharToOem(PChar(S), PChar(S));
>end;
>
>при исполнении вот этой строки
>CharToOem(PChar(S), PChar(S));
>выдает
>Access violation at address 77D34CBD in module "user32.dll"
>Не знаю что и думать. Помогите мастера.
Надоело уже объяснять, может этот "прикол" в FAQ занести?
"s" указывает на конст. строку, а она, скорее всего, находится в области памяти с защитой от записи (что-то типа PAGE_READ).
Следует писать как-нибудь так:
function OemToAnsi(const S: String): String;
begin
SetLength(Result, Length(S));
CharToOem(PChar(S), PChar(Result));
end;
← →
VMcL (2004-01-14 15:53) [29]Sorry,
function AnsiToOem(const S: String): String;
← →
AKul (2004-01-14 16:03) [30]to PVOzerski © (14.01.04 15:37) [27]:
при компиляции PChar(S) генерируется следующий код:
Вызывается процедура LStrToPChar, которая возвращает переданный ей указатель без изменений (@S), если он не равен нулю (nil). В случае nil возвращается указатель на пустую строку, расположенную также в секции кода.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.01.26;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.005 c