Skip to contentSkip to conversation

why does sscanf() does not interpret number length attributes?

DISCUSSION Kay Sievers 3 participants 4 messages Jul 2, 2003

lore
Share & tools
lore
#0 lore raw

I needed a conversion from hex-string to integer and found this mail from Linus suggesting sscanf:

http://marc.theaimsgroup.com/?l=linux-kernel&m=101414195507893&w=2

but sscanf in linux-2.5/lib/vsprintf.c interpretes length attributes only when the type is a string. It uses simple_strtoul() and it will read the buffer until it finds a non-(hex)digit.

int i;
char str[] ="34AFFE45XYZ";
sscanf(str, "%1x", &i);

i will be '0x34AFFE45' instead of the expected '3'.

Is this behaviour intended or is just nobody caring about?

thanks
Kay

#1 lore raw
Quoted 9 lines · Kay Sievers

I needed a conversion from hex-string to integer and found this mail from Linus suggesting sscanf:

http://marc.theaimsgroup.com/?l=linux-kernel&m=101414195507893&w=2

but sscanf in linux-2.5/lib/vsprintf.c interpretes length attributes only when the type is a string. It uses simple_strtoul() and it will read the buffer until it finds a non-(hex)digit.

Quoted 8 lines

int i;
char str[] ="34AFFE45XYZ";
sscanf(str, "%1x", &i);

i will be '0x34AFFE45' instead of the expected '3'.

Is this behaviour intended or is just nobody caring about?

The in-kernel vsprintf() is very primative, used for very simple things. Note that it doesn't even have "%f". You should just do something like:

	i = (int) *str + '0';

      ... if you need to read part of a number.

You don't really wany to increase the size of the permanent in-kernel stuff if you can help. You add any increased functionality to your modules so it is used only when needed.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.20 on an i686 machine (797.90 BogoMips). Why is the government concerned about the lunatic fringe? Think about it.

#2 lore raw
Quoted 17 lines · Richard B. Johnson
Quoted 15 lines · Kay Sievers

I needed a conversion from hex-string to integer and found this mail from Linus suggesting sscanf:

http://marc.theaimsgroup.com/?l=linux-kernel&m=101414195507893&w=2

but sscanf in linux-2.5/lib/vsprintf.c interpretes length attributes only when the type is a string. It uses simple_strtoul() and it will read the buffer until it finds a non-(hex)digit.

int i;
char str[] ="34AFFE45XYZ";
sscanf(str, "%1x", &i);

i will be '0x34AFFE45' instead of the expected '3'.

Quoted 8 lines
Quoted 2 lines

Is this behaviour intended or is just nobody caring about?

The in-kernel vsprintf() is very primative, used for very simple things. Note that it doesn't even have "%f". You should just do something like:

	i = (int) *str + '0';

And what about hex lowercases ?
Do you meant "- '0'" :-)

Quoted 6 lines

... if you need to read part of a number.

You don't really wany to increase the size of the permanent in-kernel stuff if you can help. You add any increased functionality to your modules so it is used only when needed.

Sure, but the length attribute is already available in a var at processing and all what is needed is one extra parameter for escaping from the char read loop.

i wouldn't call this "increase of permanent stuff".

thanks
Kay

#3 lore raw
In reply to Kay Sievers

Kay Sievers wrote:

[snip]

Quoted 5 lines

but sscanf in linux-2.5/lib/vsprintf.c interpretes length attributes only when the type is a string. It uses simple_strtoul() and it will read the buffer until it finds a non-(hex)digit.

[snip]
You could always try truncating the string, then using strtoul(). Save the character you replace if you want to restore the string to its former glory :)

eg.:
...
savechar = str[3];
str[3]=0;
i = simple_strtoul(str);
str[3]=savechar;
...
- Steve