Текущий архив: 2009.05.10;
Скачать: CL | DM;
Вниз
wvsprintf и размер буфера для нее Найти похожие ветки
← →
Тыщ (2008-04-25 18:31) [0]Как узнать, какой велечины буфер будет требоваться функции wvsprintf?
Если это невозможно, посоветуйте замену wvsprintf с совместимыми правилами форматирования (%s, %d, %.14g и т.п.).
← →
Игорь Шевченко © (2008-04-25 19:36) [1]
> посоветуйте замену
Format ?
> Как узнать, какой велечины буфер будет требоваться функции
> wvsprintf?
Это ее возвращаемое значение
← →
Тыщ (2008-04-25 20:14) [2]Игорь Шевченко © (25.04.08 19:36) [1]
> Format ?
Все бы хорошо, да только в программе ожидается такой же вид параметров, что и у wvsprintf...
> Это ее возвращаемое значение
В том и странность, что это значение возвращается уже после того, как строка записана. И если буфер был недостаточно велик, получим либо AV, либо порчу памяти.
← →
palva © (2008-04-25 23:26) [3]В MSDN пишут, что максимум заполнения буфера 1024.
← →
Тыщ (2008-04-26 08:49) [4]palva © (25.04.08 23:26) [3]
Спасибо.
Пните в сторону того, как на стеке выглядят параметры для wvsprintf?
Хочу написать конверсию параметров для другой функции.
← →
Игорь Шевченко © (2008-04-26 11:04) [5]Тыщ (25.04.08 20:14) [2]
> В том и странность, что это значение возвращается уже после
> того, как строка записана. И если буфер был недостаточно
> велик, получим либо AV, либо порчу памяти.
передать nil в качестве буфера не помогает ? (Сам не пробовал, ничего не могу сказать)
> Пните в сторону того, как на стеке выглядят параметры для
> wvsprintf?
+0 адрес возврата
+4 строка формата
+8 параметр1
+12 параметр2
...
← →
palva © (2008-04-26 13:48) [6]
> передать nil в качестве буфера не помогает ? (Сам не пробовал,
> ничего не могу сказать)
Я вчера попробовал, у меня не получилось. Было исключение по защите.
> +0 адрес возврата
> +4 строка формата
> +8 параметр1
> +12 параметр2
Эта функция имеет фиксированное число параметров. Последний параметр является адресом области памяти, содержащей величины, которые интерпретируются в соответствии с форматной строкой. Я попробовал следующий код:
{$APPTYPE CONSOLE}
function wvsprintf(Output: PChar; Format: PChar; arglist: Pointer): Integer;
stdcall; external "user32" name "wvsprintfA";
var
a: array [0..1000] of Char;
ii: array [0..1] of Integer;
begin
ii[0] := 42334543;
ii[1] := 534;
wvsprintf(a, "%d %d", @ii[0]);
WriteLn(a);
ReadLn
end.
+0 адрес буфера с результирующей строкой
+4 строка формата
+8 адрес области параметров
← →
Тыщ (2008-04-26 19:56) [7]Я так понял, что любой параметр всегда будет занимать 4 байта?
Числа с плавающей точкой будут всегда приводиться в single, или передаваться с помощью указателя?
Строки - с помощью указателя?
Со всем остальным понятно, спасибо.
← →
palva © (2008-04-26 20:38) [8]> Я так понял, что любой параметр всегда будет занимать 4 байта?
Ну да, хотя в документации я не видел такого описания.
Параметры должны выглядеть так же, как будто они были бы положены в стек при вызове функции printf в языке си. Что произойдет с плавающими, я не знаю, поскольку не в курсе о наличии соответствующих форматов и не могу проверить. А символы и строки - да.
{$APPTYPE CONSOLE}
function wvsprintf(Output: PChar; Format: PChar; arglist: Pointer): Integer;
stdcall; external "user32" name "wvsprintfA";
var
a: array [0..1000] of Char;
rec: record
i: Integer;
c1: Char;
// Здесь будет вставлено три пустых байта
s: String;
end;
begin
rec.i := 42334543;
rec.c1 := "q";
rec.s := "zxcv";
wvsprintf(a, "%d %c %s", @rec.i);
WriteLn(a); // 42334543 q zxcv
end.
← →
Тыщ (2008-04-26 23:12) [9]Спасибо за пример.
Выяснил, что числа с плавающей точкой будут занимать 8 байт, в том числе и в стеке, то есть тип - double.
А также, что wvsprintf не работает с ними - выводит буковку.
А вот vsprintf из msvcrt.dll - работает.{$APPTYPE CONSOLE}
function vsprintf(Output: PChar; Format: PChar; arglist: Pointer): Integer;
cdecl; external "msvcrt.dll";
function wvsprintf(Output: PChar; Format: PChar; arglist: Pointer): Integer;
stdcall; external "user32" name "wvsprintfA";
{$A4}
var
a: array [0..1023] of Char;
rec: record
i: Integer;
c1: Char;
s: String;
p: pointer;
fd: double;
fd2: double;
end=(
i: 42334543;
c1: "q";
s: "zxcv";
p: Ptr($DEADBEEF);
fd: 1.01;
fd2: 1.01;
);
const fmt="%d %c %s %p %f %.14g";
begin
wvsprintf(a, fmt, @rec.i);
WriteLn("wvsprintf: " + a); // 42334543 q zxcv DEADBEEF f g
vsprintf(a, fmt, @rec.i);
WriteLn(" vsprintf: " + a); // 42334543 q zxcv DEADBEEF 1.010000 1.01
end.
P.S. в Win98 wvsprintf даже указатель не выводит.
← →
Leonid Troyanovsky © (2008-04-27 10:03) [10]
> Тыщ (26.04.08 23:12) [9]
> в том числе и в стеке, то есть тип - double.
> А также, что wvsprintf не работает с ними - выводит буковку.
А чего, wvsprintf обязан работать с float?
--
Regards, LVT.
← →
Тыщ (2008-04-27 10:23) [11]Leonid Troyanovsky © (27.04.08 10:03) [10]
> А чего, wvsprintf обязан работать с float?
По идее да, если эта функция позиционируется, как "Win32 Equivalent for C Run-Time Function".
← →
Leonid Troyanovsky © (2008-04-27 10:44) [12]
> Тыщ (27.04.08 10:23) [11]
> По идее да, если эта функция позиционируется, как "Win32
> Equivalent for C Run-Time Function".
Не всякому рантайму потребны float.
Что там в msdn написано насчет возможных форматов?
Кста, arglist - это, IMHO, указатель на массив поинтеров.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2008-04-27 10:53) [13]
> Leonid Troyanovsky © (27.04.08 10:44) [12]
> Кста, arglist - это, IMHO, указатель на массив поинтеров.
Фу-ты, это первый элемент массива поинтеров, sorry.
--
Regards, LVT.
← →
Тыщ (2008-04-27 10:58) [14]Leonid Troyanovsky © (27.04.08 10:44) [12]
> Что там в msdn написано насчет возможных форматов?
Ограниченность wvsprintf там отражена.
> Кста, arglist - это, IMHO, указатель на массив поинтеров.
Да нет же, см. последний пример, указатель на массив разного всего.
← →
Игорь Шевченко © (2008-04-27 15:41) [15]palva © (26.04.08 13:48) [6]
Пардон, перепутал с wsprintf, буковка v из головы вылетела. В случае с буковкой v все совсем просто - первый аргумент адрес формата, второй аргумент адрес arglist (который va_list, и по которому надо бегать вручную за каждым аргументом, в зависимости от его типа)
← →
Тыщ © (2008-04-29 13:10) [16]
{$APPTYPE CONSOLE}
uses Windows;
function Int2Str(Value:integer):string;
begin
Str(Value,Result);
end;
function Int2Hex(Num:integer):string;
asm
// edx = Pointer to string
// eax = Num
push esi
push edi
bswap eax
push eax
mov edi,edx
mov esi,esp
mov eax,edx
mov edx,8
call System.@LStrSetLength
mov edi,[edi]
mov ecx,4
@@next:
lodsb
mov ah,al
and al,$0F
cmp al,10
sbb al,$69
das
xchg al,ah
shr al,$04
cmp al,10
sbb al,$69
das
stosw
loop @@next
pop eax
pop edi
pop esi
end;
function Double2Str(D:double; Width,Precision:integer; CutEndZeroes:boolean):string;
var Temp:string;
begin
if not CutEndZeroes then
begin
Str(D:0:Width,Temp);
if Precision<Width*2-Length(Temp) then Precision:=Width*2-Length(Temp);
end else Precision:=15;
Str(D:Width:Precision,Result);
if CutEndZeroes then
begin
while Result[Length(Result)]="0" do Delete(Result,Length(Result),1);
if Result[Length(Result)]="." then Delete(Result,Length(Result),1);
Insert(StringOfChar(" ",Width-Length(Result)),Result,1);
end;
end;
function vsprintf(Output,Format:pchar; ArgList:pointer):integer;
cdecl; external "msvcrt.dll";
function dprintf(const Fmt:string; ArgList:pchar):string;
// Supported form: %[width][.precision]type
const
FMT_CHAR=["c","d","f","g","p","s"];
FMT_NUM=["0","1","2","3","4","5","6","7","8","9"];
var
I,Width,Precision:integer;
WidthSpecified:boolean;
begin
if Fmt="" then
begin
Result:="";
Exit;
end;
I:=1;
repeat
if Fmt[I]<>"%" then
begin
Result:=Result+Fmt[I];
end else begin
Inc(I);
if I>Length(Fmt) then break;
Width:=0;
WidthSpecified:=false;
Precision:=0;
while Fmt[I] in FMT_NUM do
begin
WidthSpecified:=true;
Width:=Width*10+Ord(Fmt[I])-48;
Inc(I);
if I>Length(Fmt) then Exit;
end;
if Fmt[I]="." then
begin
Inc(I);
if I>Length(Fmt) then break;
while Fmt[I] in FMT_NUM do
begin
Precision:=Precision*10+Ord(Fmt[I])-48;
Inc(I);
if I>Length(Fmt) then Exit;
end;
end;
if Precision=0 then Precision:=1;
case Fmt[I] of
"c": begin
Result:=Result+ArgList^;
Inc(ArgList,4);
end;
"d": begin
Result:=Result+Int2Str(PInteger(ArgList)^);
Inc(ArgList,4);
end;
"f": begin
if not WidthSpecified then Width:=8;
Result:=Result+Double2Str(PDouble(ArgList)^,Width,Precision,false);
Inc(ArgList,8);
end;
"g": begin
if not WidthSpecified then Width:=1;
Result:=Result+Double2Str(PDouble(ArgList)^,Width,Precision,true);
Inc(ArgList,8);
end;
"p": begin
Result:=Result+Int2Hex(PInteger(ArgList)^);
Inc(ArgList,4);
end;
"s": begin
Result:=Result+PChar(Ptr(PInteger(ArgList)^));
Inc(ArgList,4);
end;
else continue;
end;
end;
Inc(I);
until I>Length(Fmt);
end;
var
a: array [0..1023] of Char;
rec: packed record
i: Integer;
c1: Char; _dummy:array[0..2] of byte;
s: String;
p: pointer;
fd: double;
fd2: double;
fd3: double;
fd4: double;
end=(
i: 42334543;
c1: "q";
s: "zxcv";
p: Ptr($DEADBEEF);
fd: 1.01;
fd2: 1.01;
fd3: 1.01;
fd4: 1.01;
);
s:string;
const fmt="!%d %c %s %p %5.14f %5.14g %f %g %zs!";
//const fmt="!%d %c %s %p %.f %.g %f %g %zs!";
begin
vsprintf(a,fmt,@rec); WriteLn("vsprintf: "+a);
s:=dprintf(fmt,@rec); WriteLn(" dprintf: "+s);
end.
← →
Тыщ © (2008-04-29 13:12) [17]Вот, собственно, написал замену wvsprintf и vsprintf :)
Если кому пригодится - я буду только рад.
← →
Игорь Шевченко © (2008-04-29 17:50) [18]
> Вот, собственно, написал замену wvsprintf и vsprintf :)
> rec: packed record
> i: Integer;
> c1: Char; _dummy:array[0..2] of byte;
> s: String;
> p: pointer;
> fd: double;
> fd2: double;
> fd3: double;
> fd4: double;
> end=(
> i: 42334543;
> c1: "q";
> s: "zxcv";
> p: Ptr($DEADBEEF);
> fd: 1.01;
> fd2: 1.01;
> fd3: 1.01;
> fd4: 1.01;
> );
а эту rec каждый раз вручную кодировать ? :)
Format пользовать всяко проще...
← →
Тыщ © (2008-04-29 18:35) [19]Игорь Шевченко © (29.04.08 17:50) [18]
Да не, rec - это для тестирования.
Писал же для сишной библиотеки, которая ожидает функцию формы (w)vsprintf.
← →
Игорь Шевченко © (2008-04-29 23:27) [20]Тыщ © (29.04.08 18:35) [19]
А как простому программисту использовать ?
← →
Тыщ © (2008-04-30 05:42) [21]Игорь Шевченко © (29.04.08 23:27) [20]
Ой, не знаю. Пусть сам решает.
Страницы: 1 вся ветка
Текущий архив: 2009.05.10;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.01 c