PDA

View Full Version : format and printf bug in SAMP 0.3c R3-1


bocian941
25/07/2011, 11:41 PM
Hello, I found bug..

public OnGameModeInit()
{
new test = 0, test2 = 122, test3 = 0b101011, tmp[16];

printf("test: %d | %b | %x", test, test, test);
printf("test2: %d | %b | %x", test2, test2, test2);
printf("test3: %d | %b | %x", test3, test3, test3);

format(tmp, 16, "Output: %b %b %b", test, test2, test3);
print(tmp);
}

Log:
[01:39:13] test: 0 | b | 0
[01:39:13] test2: 122 | b | 7A
[01:39:13] test3: 43 | b | 2B
[01:39:13] Output: b b b

In 0.3c R2 and older %b works.

Karlip
26/07/2011, 10:57 AM
I can confirm this.

Vince
26/07/2011, 11:06 AM
Confirmed. I have a similar problem. Turned from this:
http://i53.tinypic.com/29elysi.jpg

Into this:
http://i55.tinypic.com/vo0dj9.png

No changes to that part whatsoever.

dugi
26/07/2011, 11:14 AM
Confirmed. I have a similar problem. Turned from this:
http://i53.tinypic.com/29elysi.jpg

Into this:
http://i55.tinypic.com/vo0dj9.png

No changes to that part whatsoever.

Are you running R3 or R3-1 server?

Vince
26/07/2011, 11:32 AM
Are you running R3 or R3-1 server?

Ah sorry, didn't notice there was a hotfix already. Solved, thanks. :)

bocian941
26/07/2011, 01:19 PM
Vince's bug solved, but problem with binary in format/printf not solved..

Y_Less
26/07/2011, 02:28 PM
OK, I ran some tests:


#include <a_samp>

main()
{
new
str[32];
// printf
printf("\"%b\"", 42);
printf("\"%07b\"", 42);
printf("\"%7b\"", 42);
printf("\"%.3b\"", 42);
printf("\"%x\"", 42);
printf("\"%05x\"", 42);
printf("\"%5x\"", 42);
printf("\"%.3x\"", 42);
printf("\"%h\"", 42);
printf("\"%05h\"", 42);
printf("\"%5h\"", 42);
printf("\"%.3h\"", 42);
printf("\"%d\"", 42);
printf("\"%05d\"", 42);
printf("\"%5d\"", 42);
printf("\"%.3d\"", 42);
printf("\"%s\"", "hello");
printf("\"%5.3s\"", "hello");
printf("\"%5s\"", "hello");
printf("\"%.3s\"", "hello");
printf("\"%f\"", 57.0);
printf("\"%05f\"", 57.0);
printf("\"%5f\"", 57.0);
printf("\"%.3f\"", 57.0);
// format
format(str, sizeof (str), "\"%b\"", 42);
print(str);
format(str, sizeof (str), "\"%07b\"", 42);
print(str);
format(str, sizeof (str), "\"%7b\"", 42);
print(str);
format(str, sizeof (str), "\"%.3b\"", 42);
print(str);
format(str, sizeof (str), "\"%x\"", 42);
print(str);
format(str, sizeof (str), "\"%05x\"", 42);
print(str);
format(str, sizeof (str), "\"%5x\"", 42);
print(str);
format(str, sizeof (str), "\"%.3x\"", 42);
print(str);
format(str, sizeof (str), "\"%h\"", 42);
print(str);
format(str, sizeof (str), "\"%05h\"", 42);
print(str);
format(str, sizeof (str), "\"%5h\"", 42);
print(str);
format(str, sizeof (str), "\"%.3h\"", 42);
print(str);
format(str, sizeof (str), "\"%d\"", 42);
print(str);
format(str, sizeof (str), "\"%05d\"", 42);
print(str);
format(str, sizeof (str), "\"%5d\"", 42);
print(str);
format(str, sizeof (str), "\"%.3d\"", 42);
print(str);
format(str, sizeof (str), "\"%s\"", "hello");
print(str);
format(str, sizeof (str), "\"%5.3s\"", "hello");
print(str);
format(str, sizeof (str), "\"%5s\"", "hello");
print(str);
format(str, sizeof (str), "\"%.3s\"", "hello");
print(str);
format(str, sizeof (str), "\"%f\"", 57.0);
print(str);
format(str, sizeof (str), "\"%05f\"", 57.0);
print(str);
format(str, sizeof (str), "\"%5f\"", 57.0);
print(str);
format(str, sizeof (str), "\"%.3f\"", 57.0);
print(str);
// star
format(str, sizeof (str), "\"%b\"", 42);
print(str);
format(str, sizeof (str), "\"%0*b\"", 7, 42);
print(str);
format(str, sizeof (str), "\"%*b\"", 7, 42);
print(str);
format(str, sizeof (str), "\"%.*b\"", 3, 42);
print(str);
format(str, sizeof (str), "\"%x\"", 42);
print(str);
format(str, sizeof (str), "\"%0*x\"", 5, 42);
print(str);
format(str, sizeof (str), "\"%*x\"", 5, 42);
print(str);
format(str, sizeof (str), "\"%.*x\"", 3, 42);
print(str);
format(str, sizeof (str), "\"%h\"", 42);
print(str);
format(str, sizeof (str), "\"%0*h\"", 5, 42);
print(str);
format(str, sizeof (str), "\"%*h\"", 5, 42);
print(str);
format(str, sizeof (str), "\"%.*h\"", 3, 42);
print(str);
format(str, sizeof (str), "\"%d\"", 42);
print(str);
format(str, sizeof (str), "\"%0*d\"", 5, 42);
print(str);
format(str, sizeof (str), "\"%*d\"", 5, 42);
print(str);
format(str, sizeof (str), "\"%.*d\"", 3, 42);
print(str);
format(str, sizeof (str), "\"%s\"", "hello");
print(str);
format(str, sizeof (str), "\"%*.*s\"", 5, 3, "hello");
print(str);
format(str, sizeof (str), "\"%*s\"", 5, "hello");
print(str);
format(str, sizeof (str), "\"%.*s\"", 3, "hello");
print(str);
format(str, sizeof (str), "\"%f\"", 57.0);
print(str);
format(str, sizeof (str), "\"%0*f\"", 5, 57.0);
print(str);
format(str, sizeof (str), "\"%*f\"", 5, 57.0);
print(str);
format(str, sizeof (str), "\"%.*f\"", 3, 57.0);
print(str);
}


Results side-by-side. 0.3bR2 is on the left, 0.3bR3-1 is on the right.


"101010" "b"
"0101010" "b"
" 101010" "b"
"101010" "b"
"2A" "2A"
"0002A" "0002A"
" 2A" " 2A"
"2A" "2A"
"2A" "2A"
"0002A" "0002A"
" 2A" " 2A"
"2A" "2A"
"42" "42"
"00042" "00042"
" 42" " 42"
"42" "42"
"hello" "hello"
"hel " "hel "
"hello" "hello"
"hel" "hel"
"57.000000" "57.000000"
" 57.000000" "57.000000"
" 57.000000" "57.000000"
"57.000" "57.000"
"101010" "b"
"0101010" "b"
" 101010" "b"
"101010" "b"
"2A" "2A"
"0002A" "0002A"
" 2A" " 2A"
"2A" "2A"
"2A" "2A"
"0002A" "0002A"
" 2A" " 2A"
"2A" "2A"
"42" "42"
"00042" "00042"
" 42" " 42"
"42" "42"
"hello" "hello"
"hel " "hel "
"hello" "hello"
"hel" "hel"
"57.000000" "57.000000"
" 57.000000" "57.000000"
" 57.000000" "57.000000"
"57.000" "57.000"
"101010" "b"
"0101010" "b"
" 101010" "b"
"101010" "b"
"2A" "2A"
"0002A" "0002A"
" 2A" " 2A"
"2A" " 2A"
"2A" "2A"
"0002A" "0002A"
" 2A" " 2A"
"2A" " 2A"
"42" "42"
"00042" "00042"
" 42" " 42"
"42" " 42"
"hello" "hello"
"hel " "hello"
"hello" "hello"
"hel" "hello"
"57.000000" "57.000000"
" 57.000000" "57.000000"
" 57.000000" "57.000000"
"57.000" "57.000000"



Summary:

"b" doesn't work at all.
Padding on floats does nothing any more.
"*" doesn't work for padding or precision in strings and floats.
".*" in decimals/hex is now interpreted as padding instead of the old ignored precision (but ".3" isn't).

Note that I've not tested negative paddings at all.

JernejL
26/07/2011, 02:33 PM
Floating point precision specifier works as long as you specify if fully = %0.1f for example.

As for %b, who ever used that?

Y_Less
26/07/2011, 02:37 PM
The "0" in "0.1" isn't part of the precision though, the period here separates information, it doesn't denote fractions. Everything before the "." relates to padding with a leading 0 meaning "pad with 0s" and no leading 0 meaning "pad with spaces":


%.3f = Only 3 numbers after the decimal point, don't pad the length of the number.
%02f = Default (6) numbers after the decimal point, pad the length to at least 2 characters (before the decimal point) with 0s if required.
%2f = Default (6) numbers after the decimal point, pad the length to at least 2 characters (before the decimal point) with spaces if required.
%02.3f = 3 numbers after the decimal point, pad the length to at least 2 characters (before the decimal point) with 0s if required.


And apparently the OP uses %b.

Edit: Apparently "%09f" doesn't pad with zeroes in earlier SA:MPs, but that definately works on specifiers other than "f":


#define VALUE 99
#define SPECIFIER "h"

#include <a_samp>

main()
{
new
str[32];
// none
format(str, sizeof (str), "\"%"SPECIFIER"\"", VALUE);
print(str);
format(str, sizeof (str), "\"%.2"SPECIFIER"\"", VALUE);
print(str);
format(str, sizeof (str), "\"%.*"SPECIFIER"\"", 2, VALUE);
print(str);
// numered
format(str, sizeof (str), "\"%9"SPECIFIER"\"", VALUE);
print(str);
format(str, sizeof (str), "\"%09"SPECIFIER"\"", VALUE);
print(str);
format(str, sizeof (str), "\"%9.2"SPECIFIER"\"", VALUE);
print(str);
format(str, sizeof (str), "\"%09.2"SPECIFIER"\"", VALUE);
print(str);
format(str, sizeof (str), "\"%9.*"SPECIFIER"\"", 2, VALUE);
print(str);
format(str, sizeof (str), "\"%09.*"SPECIFIER"\"", 2, VALUE);
print(str);
// stared
format(str, sizeof (str), "\"%*"SPECIFIER"\"", 9, VALUE);
print(str);
format(str, sizeof (str), "\"%0*"SPECIFIER"\"", 9, VALUE);
print(str);
format(str, sizeof (str), "\"%*.2"SPECIFIER"\"", 9, VALUE);
print(str);
format(str, sizeof (str), "\"%0*.2"SPECIFIER"\"", 9, VALUE);
print(str);
format(str, sizeof (str), "\"%*.*"SPECIFIER"\"", 9, 2, VALUE);
print(str);
format(str, sizeof (str), "\"%0*.*"SPECIFIER"\"", 9, 2, VALUE);
print(str);
}


Gives:


"57.000000" "57.000000"
"57.00" "57.00"
"57.00" "57.000000"
" 57.000000" "57.000000"
" 57.000000" "57.000000"
" 57.00" "57.00"
" 57.00" "57.00"
" 57.00" "57.000000"
" 57.00" "57.000000"
" 57.000000" "57.000000"
" 57.000000" "57.000000"
" 57.00" "57.00"
" 57.00" "57.00"
" 57.00" "57.000000"
" 57.00" "57.000000"


Same code using "d" and "42":


"42" "42"
"42" "42"
"42" "42"
" 42" " 42"
"000000042" "000000042"
" 42" " 42"
"000000042" "000000042"
" 42" "42"
"000000042" "42"
" 42" " 42"
"000000042" "000000042"
" 42" " 42"
"000000042" "000000042"
" 42" "42"
"000000042" "42"


"s" and "hello":


"hello" "hello"
"he" "he"
"he" "hello"
"hello " "hello "
"hello " "hello "
"he " "he "
"he " "he "
"he " "hello"
"he " "hello"
"hello " "hello "
"hello " "hello "
"he " "he "
"he " "he "
"he " "hello"
"he " "hello"


"h" and "99":


"63" "63"
"63" "63"
"63" "63"
" 63" " 63"
"000000063" "000000063"
" 63" " 63"
"000000063" "000000063"
" 63" "63"
"000000063" "63"
" 63" " 63"
"000000063" "000000063"
" 63" " 63"
"000000063" "000000063"
" 63" "63"
"000000063" "63"


I think that's pretty much a full test set.

Kalcor
27/07/2011, 09:08 AM
Thanks for the detailed report. I plan to release a 0.3c R4 server shortly to address this and some other minor issues.

Left is Y_Less's original 0.3c R1/R2 format test, right is the same code tested in 0.3c R4 server.


0.3c R1/R20.3c R4
"101010" "101010"
"0101010""0101010"
" 101010"" 101010"
"101010""101010"
"2A""2A"
"0002A""0002A"
" 2A"" 2A"
"2A""2A"
"2A""2A"
"0002A""0002A"
" 2A"" 2A"
"2A""2A"
"42""42"
"00042""00042"
" 42"" 42"
"42""42"
"hello""hello"
"hel ""hel "
"hello""hello"
"hel""hel"
"57.000000""57.000000"
" 57.000000""00057.000000"
" 57.000000"" 57.000000"
"57.000""57.000"
"101010""101010"
"0101010""0101010"
" 101010"" 101010"
"101010""101010"
"2A""2A"
"0002A""0002A"
" 2A"" 2A"
"2A""2A"
"2A""2A"
"0002A""0002A"
" 2A"" 2A"
"2A""2A"
"42""42"
"00042""00042"
" 42"" 42"
"42""42"
"hello""hello"
"hel ""hel "
"hello""hello"
"hel""hel"
"57.000000""57.000000"
" 57.000000""00057.000000"
" 57.000000"" 57.000000"
"57.000""57.000"
"101010""101010"
"0101010""0101010"
" 101010"" 101010"
"101010""101010"
"2A""2A"
"0002A""0002A"
" 2A"" 2A"
"2A""2A"
"2A""2A"
"0002A""0002A"
" 2A"" 2A"
"2A""2A"
"42""42"
"00042""00042"
" 42"" 42"
"42""42"
"hello""hello"
"hel ""hel "
"hello""hello"
"hel""hel"
"57.000000""57.000000"
" 57.000000""00057.000000"
" 57.000000"" 57.000000"
"57.000""57.000"


Summary of fixes:
- Fixed problem with padding for float specifier. Added support for 0 padding in floats.
- Fixed problem where arbitrary precision (.*) would be interpreted as padding.
- Readded support for the binary specifier, even though I think it has no practical purpose in SA-MP.

Y_Less
27/07/2011, 09:31 AM
Awesome, thanks for this Kalcor, I know it may not seem like a big thing but it does make a big difference to one script I'm currently working on.

Meta
27/07/2011, 11:20 AM
As we are talking about those bugs now, how about the string-bug in Timers and some other Functions?

new teststring[4];
public OnFilterScriptInit()
{
teststring = "Hi!";
CallLocalFunction("print", "s", teststring); // does not work
SetTimerEx("print", 1000, 0, "s", teststring); // does not work
SetTimerEx("Func", 2000, 0, "d", 0); // works
SetTimerEx("Func", 3000, 0, "d", 1); // works
}

forward Func(text);
public Func(text)
{
if(text)
{
printf("_%s_", teststring);
}
else
{
print(teststring);
}
}

Output:
_Hi!_
Hi!

Expected Output:
Hi!
Hi!
_Hi!_
Hi!

Y_Less
27/07/2011, 11:26 AM
1) You can't call "print" in a timer, it's not a public function, it's a native function.

2) There is no bug in the code you show - you assign a global variable a string, then you print it correctly.

I think you mean:


public OnFilterScriptInit()
{
SetTimerEx("Func", 1000, 0, "s", "hi");
SetTimerEx("Func", 1000, 0, "s", "there");
}

forward Func(str[]);

public Func(str[])
{
printf("%s", str);
}


Will give:


there
there


If you need to there are ways around this, but they obviously won't be needed if the bug does get fixed. Though this is an existing bug, not a regression bug.

Meta
27/07/2011, 11:41 AM
Oh, never saw that it isn't a public function :o
Actually I meant another bug ... I'll try to explain it in a few minutes

EDIT: This is, what I wanted to show:
new teststring[4];
public OnFilterScriptInit()
{
teststring = "Foo";
SetTimerEx("Func", 1000, 0, "s", teststring);
SetTimerEx("Func", 1500, 0, "s", "Moo");
}

forward Func(text[]);
public Func(text[])
{
print(text);
}

Output:
(null)
(null)

Expected:
Foo
Moo

Jay_
27/07/2011, 12:37 PM
Passing strings in SetTimerEx hasn't worked since the native was wrote. It's nothing to do with any recent server updates.

Meta
27/07/2011, 01:20 PM
Yeah, but it's a bug and if Kalcor is fixing some bugs in format etc. he could fix this, too.

leong124
27/07/2011, 03:01 PM
1) You can't call "print" in a timer, it's not a public function, it's a native function.

2) There is no bug in the code you show - you assign a global variable a string, then you print it correctly.

I think you mean:


public OnFilterScriptInit()
{
SetTimerEx("Func", 1000, 0, "s", "hi");
SetTimerEx("Func", 1000, 0, "s", "there");
}

forward Func(str[]);

public Func(str[])
{
printf("%s", str);
}


Will give:


there
there


If you need to there are ways around this, but they obviously won't be needed if the bug does get fixed. Though this is an existing bug, not a regression bug.

I can confirm this. I found this when I was making a delayed timer system for my server.
IMHO, fixing the existing bugs will be more important than new functions.

SPAWN_METAL
28/07/2011, 04:31 PM
deleted

bocian941
28/07/2011, 04:35 PM
Show Your code..

SPAWN_METAL
28/07/2011, 04:39 PM
deleted

bocian941
28/07/2011, 04:44 PM
new Float:Health, st[16];
GetPlayerHealth(playerid, Health);
format(st, sizeof(st), "%.0f", Health);
TextDrawSetString(HP2D[playerid], st);

SPAWN_METAL
28/07/2011, 04:48 PM
Your code will not solve all problem's
How do I know that in game mode will still not work
Who needs to change the work function when it worked?

bocian941
28/07/2011, 04:54 PM
For me this code works correctly in 0.3c R5

JernejL
28/07/2011, 05:36 PM
With R2 version and others old
http://img717.imageshack.us/img717/9284/33022952.png

With new R3 R4 R5:
http://img217.imageshack.us/img217/8975/37075398.png

what's happened with format %f??????

PLEASE UPDATE TO R5

you obviously haven't done that yet.

SPAWN_METAL
28/07/2011, 06:04 PM
//you obviously haven't done that yet
ALL GOOD WITH R2 and others old

bug with new R3 R4 R5:

FANEX
29/07/2011, 08:05 AM
bug with new R3 R4 R5:
Have you tried R5 version? I don't think so...

[NoV]LaZ
29/07/2011, 08:35 AM
PLEASE UPDATE TO R5

you obviously haven't done that yet.

This problem occurs on Windows R4, and as far as I know R5 fixed some vulnerabilities on Linux only.

Littl3j0hNy
30/07/2011, 05:54 PM
Kills[killerid]++;
format(str, sizeof(str), "~y~Kill Nr. ~r~~h~%d~y~!", Kills[killerid]);
GameTextForPlayer(killerid, str, 2500, 3);
This will show you your current kill number but only when you have 2 or more.
If you have 0 Kills then it will show you "Kill Nr. !" and not "Kill Nr. 1!"

ON R5

SPAWN_METAL
01/08/2011, 05:44 PM
deleted

_Outbreak_
28/08/2011, 02:43 PM
http://forum.sa-mp.com/showpost.php?p=1371398&postcount=318

Also float strings were showing like 150.0000 instead of just 150

Kar
28/08/2011, 03:01 PM
http://forum.sa-mp.com/showpost.php?p=1371398&postcount=318

Also float strings were showing like 150.0000 instead of just 150

150 is an integer, use %0.1f to get 150.0

OUL
29/08/2011, 09:08 AM
Maybe he wanna to get float to integer, use floatround


new Float:Var = 1.5;
printf("# 1.5 -> %d ", floatround(Var)); // will give 1 (integer)

_Outbreak_
29/08/2011, 11:28 PM
150 is an integer, use %0.1f to get 150.0

I made it a float without a decimal place. For example Health is a float, so is armour. In R2 using %.f it shows as no decimal places. In R5 it shows with alot of decimal places.

Y_Less
29/08/2011, 11:51 PM
That should be "%.0f".