Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005?

Reply
Thread Tools

difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005?

 
 
Keith Thompson
Guest
Posts: n/a
 
      04-27-2006
Martin Jørgensen <(E-Mail Removed)> writes:
> Ben Pfaff wrote:
>> Martin Jxrgensen <(E-Mail Removed)> writes:
>>
>>>When I read something like this line:
>>>
>>>03 04 05, 00 04 01, 05 03 07, 08 03 00, 09 06 03 ... etc.
>>>
>>>with something like scanf("%i %i %i, ", &var1, &var2, &var3);
>>>
>>> then it stopped reading data starting with "08", "09" etc... But
>>> everything such as "07" and below worked...
>>>
>>>Then I tried scanf("%d %d %d, ", &var1, &var2, &var3);

>> %d reads a decimal integer.
>> %i reads a C-like integer, so that a leading 0 means "octal".
>> Your reference manual should have told you this.

>
> Now I double-checked my book: "C primer plus, 5th edition".
>
> It simply *doesn't* tell this... What a piece of junk...
>
>
> It says (table 4.6, p.117):
>
> %d = interpret input as a signed decimal integer
> . . .
> %i = interpret input as a signed decimal integer
> %o = interpret input as a signed octal integer
> %x = interpret input as a signed hexadecimal integer
>
>
> So the above is wrong?


Yes.

John Bode recommended Harbison&Steele, _C: A Reference Manual_, 5th
Edition; so do I, it's excellent. You *might* consider the standard
itself (the most recent draft is n1124.pdf); it's definitely not for
beginners, but with some effort it can answer these questions for you.

> And what are %o and %x for if you can do exactly the same with %0i and
> probably %x-something? ? ?


scanf() reads integer literals with the same syntax used by strtoul();
the use of %d vs %i vs %o vs %x changes the base.

For "%d", the input is assumed to be decimal. A "0x" or "0X" prefix
is not allowed, and a leading 0 doesn't make the number octal.
(Actually, if you have a leading "0x" or "0X", it just reads the "0",
and the "x" or "X" and everything following it is left in the input
stream.)

For "%i", the input looks like an integer literal in a C program (with
an optional sign). A leading "0" makes it octal, and a leading "0x"
or "0X" makes it hexadecimal. "123" yields 123, "0123" yields 83, and
"0x123" yields 291. Use this only if you expect the input to use a
leading "0", "0x", or "0X" to indicate the base. If you're getting
interactive input from a user, this probably isn't what you want
(unless you expect the user to be familiar with C syntax).

For "%o", the input is assumed to be octal, even if it doesn't have a
leading "0". For example, either "123" or "0123" yields the integer
value 83. A leading "0x" or "0X" is not allowed (sort of; see above).

For "%x", the input is assumed to be hexadecimal. A leading "0x" or
"0X" is allowed, but ignored. For example, either "123", "0x123", or
"0123" yields the integer value 291.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
 
 
 
regis
Guest
Posts: n/a
 
      04-27-2006
Keith Thompson wrote:

> scanf() reads integer literals with the same syntax used by strtoul();
> the use of %d vs %i vs %o vs %x changes the base.


[...]

> For "%o", the input is assumed to be octal, even if it doesn't have a
> leading "0". For example, either "123" or "0123" yields the integer
> value 83. A leading "0x" or "0X" is not allowed (sort of; see above).
>
> For "%x", the input is assumed to be hexadecimal. A leading "0x" or
> "0X" is allowed, but ignored. For example, either "123", "0x123", or
> "0123" yields the integer value 291.


I found this in N869:
o,u,x are stated to all match optionally signed integers
but expect arguments as pointers to unsigned integers.
This seems rather inconsistent.
A contrario, my man pages state that o,u,x match unsigned integers
and also expect arguments as unsigned integers.

Is it a "cut and paste" typo in N869 ?

From page 322, section 7.19.6.2 The fscanf function:

o Matches an optionally signed octal integer, whose
format is the same as expected for the subject
sequence of the strtoul function with the value 8
for the base argument. The corresponding argument
shall be a pointer to unsigned integer.

u Matches an optionally signed decimal integer, whose
format is the same as expected for the subject
sequence of the strtoul function with the value 10
for the base argument. The corresponding argument
shall be a pointer to unsigned integer.

x Matches an optionally signed hexadecimal integer,
whose format is the same as expected for the subject
sequence of the strtoul function with the value 16
for the base argument. The corresponding argument
shall be a pointer to unsigned integer.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      04-27-2006
regis <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>
>> scanf() reads integer literals with the same syntax used by strtoul();
>> the use of %d vs %i vs %o vs %x changes the base.

>
> [...]
>
>> For "%o", the input is assumed to be octal, even if it doesn't have a
>> leading "0". For example, either "123" or "0123" yields the integer
>> value 83. A leading "0x" or "0X" is not allowed (sort of; see above).
>> For "%x", the input is assumed to be hexadecimal. A leading "0x" or
>> "0X" is allowed, but ignored. For example, either "123", "0x123", or
>> "0123" yields the integer value 291.

>
> I found this in N869:
> o,u,x are stated to all match optionally signed integers
> but expect arguments as pointers to unsigned integers.
> This seems rather inconsistent.
> A contrario, my man pages state that o,u,x match unsigned integers
> and also expect arguments as unsigned integers.

[...]

It's not really inconsistent. The phrase "optionally signed" refers
to the optional '+' or '-' character preceding the integer literal in
the input. This needs to be specified because, in a C program, "-1"
isn't an integer literal; it's a unary "-" operator followed by a
literal "1". If there's a '-', the result is negated (which is well
defined for both signed and unsigned types).

For example, this:

#include <stdio.h>
int main(void)
{
char *s = "-1";
unsigned int x;
int count;

count = sscanf(s, "%o", &x);
printf("count = %d, x = %u\n", count, x);

return 0;
}

prints this:

count = 1, x = 4294967295

where 4294967295 is UINT_MAX on the system where I ran it.

Here's what N1124 says about 'u':

Matches an optionally signed decimal integer, whose format is the
same as expected for the subject sequence of the strtoul function
with the value 10 for the base argument. The corresponding
argument shall be a pointer to unsigned integer.

The wording is similar for 'o' and 'x'.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
regis
Guest
Posts: n/a
 
      04-27-2006
Keith Thompson wrote:
> regis <(E-Mail Removed)> writes:
>
>>I found this in N869:
>>o,u,x are stated to all match optionally signed integers
>>but expect arguments as pointers to unsigned integers.
>>This seems rather inconsistent.
>>A contrario, my man pages state that o,u,x match unsigned integers
>>and also expect arguments as unsigned integers.

>
> It's not really inconsistent. The phrase "optionally signed" refers
> to the optional '+' or '-' character preceding the integer literal in
> the input. This needs to be specified because, in a C program, "-1"
> isn't an integer literal; it's a unary "-" operator followed by a
> literal "1". If there's a '-', the result is negated (which is well
> defined for both signed and unsigned types).


Ok, now I understand.
Thank you for your explanations.

( I find both the wording of N869 and the wording of the man pages
misleading on this subject.

Also, as far as *text* representation of unsigned integers
are concerned, I wonder if accepting negatives representations
of unsigned integers as input at the sight of format "%u"
is a desirable feature. IMHO, since input functions are
the interface with the user, it have been more useful if
such negatives representations made the conversion fail, and only
canonical positive representations made the conversion succeed. )

--
regis
 
Reply With Quote
 
=?ISO-8859-1?Q?Martin_J=F8rgensen?=
Guest
Posts: n/a
 
      04-28-2006
Keith Thompson wrote:
> Martin Jørgensen <(E-Mail Removed)> writes:

-snip-

>>Now I double-checked my book: "C primer plus, 5th edition".
>>
>>It simply *doesn't* tell this... What a piece of junk...
>>
>>
>>It says (table 4.6, p.117):
>>
>>%d = interpret input as a signed decimal integer
>>. . .
>>%i = interpret input as a signed decimal integer
>>%o = interpret input as a signed octal integer
>>%x = interpret input as a signed hexadecimal integer
>>
>>
>>So the above is wrong?

>
>
> Yes.
>
> John Bode recommended Harbison&Steele, _C: A Reference Manual_, 5th
> Edition; so do I, it's excellent. You *might* consider the standard
> itself (the most recent draft is n1124.pdf); it's definitely not for
> beginners, but with some effort it can answer these questions for you.
>
>
>>And what are %o and %x for if you can do exactly the same with %0i and
>>probably %x-something? ? ?

>
>
> scanf() reads integer literals with the same syntax used by strtoul();
> the use of %d vs %i vs %o vs %x changes the base.
>
> For "%d", the input is assumed to be decimal. A "0x" or "0X" prefix
> is not allowed, and a leading 0 doesn't make the number octal.
> (Actually, if you have a leading "0x" or "0X", it just reads the "0",
> and the "x" or "X" and everything following it is left in the input
> stream.)
>
> For "%i", the input looks like an integer literal in a C program (with
> an optional sign). A leading "0" makes it octal, and a leading "0x"
> or "0X" makes it hexadecimal. "123" yields 123, "0123" yields 83, and
> "0x123" yields 291. Use this only if you expect the input to use a
> leading "0", "0x", or "0X" to indicate the base. If you're getting
> interactive input from a user, this probably isn't what you want
> (unless you expect the user to be familiar with C syntax).
>
> For "%o", the input is assumed to be octal, even if it doesn't have a
> leading "0". For example, either "123" or "0123" yields the integer
> value 83. A leading "0x" or "0X" is not allowed (sort of; see above).
>
> For "%x", the input is assumed to be hexadecimal. A leading "0x" or
> "0X" is allowed, but ignored. For example, either "123", "0x123", or
> "0123" yields the integer value 291.


Thanks a lot.


Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
 
Reply With Quote
 
P.J. Plauger
Guest
Posts: n/a
 
      04-28-2006
"regis" <(E-Mail Removed)> wrote in message
news:44515a14$0$26532$(E-Mail Removed)...

> Keith Thompson wrote:
>> regis <(E-Mail Removed)> writes:
>>
>>>I found this in N869:
>>>o,u,x are stated to all match optionally signed integers
>>>but expect arguments as pointers to unsigned integers.
>>>This seems rather inconsistent.
>>>A contrario, my man pages state that o,u,x match unsigned integers
>>>and also expect arguments as unsigned integers.

>>
>> It's not really inconsistent. The phrase "optionally signed" refers
>> to the optional '+' or '-' character preceding the integer literal in
>> the input. This needs to be specified because, in a C program, "-1"
>> isn't an integer literal; it's a unary "-" operator followed by a
>> literal "1". If there's a '-', the result is negated (which is well
>> defined for both signed and unsigned types).

>
> Ok, now I understand.
> Thank you for your explanations.
>
> ( I find both the wording of N869 and the wording of the man pages
> misleading on this subject.
>
> Also, as far as *text* representation of unsigned integers
> are concerned, I wonder if accepting negatives representations
> of unsigned integers as input at the sight of format "%u"
> is a desirable feature. IMHO, since input functions are
> the interface with the user, it have been more useful if
> such negatives representations made the conversion fail, and only
> canonical positive representations made the conversion succeed. )


Negating an unsigned integer is well defined. Some of us find it
useful. In recent years compilers have taken to issuing warnings
about this operation on the assumption that some programmers will
be surprised that the result of any negation is still non-negative.
(I like the ones that complain about -x yet quietly accept 0-x.
Go figure.) But that don't make it wrong.

I, for one, think -1 is a great shorthand for the largest
representable unsigned value. You don't get tired of writing 'f's,
and you don't have to know how many to write.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


 
Reply With Quote
 
regis
Guest
Posts: n/a
 
      04-28-2006
P.J. Plauger wrote:
> "regis" wrote


>>Also, as far as *text* representation of unsigned integers
>>are concerned, I wonder if accepting negatives representations
>>of unsigned integers as input at the sight of format "%u"
>>is a desirable feature. IMHO, since input functions are
>>the interface with the user, it have been more useful if
>>such negatives representations made the conversion fail, and only
>>canonical positive representations made the conversion succeed. )

>
> Negating an unsigned integer is well defined. Some of us find it
> useful. In recent years compilers have taken to issuing warnings
> about this operation on the assumption that some programmers will
> be surprised that the result of any negation is still non-negative.
> (I like the ones that complain about -x yet quietly accept 0-x.
> Go figure.) But that don't make it wrong.
>
> I, for one, think -1 is a great shorthand for the largest
> representable unsigned value. You don't get tired of writing 'f's,
> and you don't have to know how many to write.


Sure. On the programmer side, it is useful:

size_t k, n= strlen (text);
for (k= n-1; k != (size_t)-1; k--) { ... }

My remark was about *text* representations that the user deals with:

int i; scanf ("%i", & i);
The user types "1", he gets 1.
The user types "-1", he gets -1.

unsigned u; scanf ("%u", & u);
The user types "1", he gets 1.
The user types "-1", he gets something that might be different
on different machines...
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-28-2006
regis <(E-Mail Removed)> writes:
[...]
> My remark was about *text* representations that the user deals with:
>
> int i; scanf ("%i", & i);
> The user types "1", he gets 1.
> The user types "-1", he gets -1.
>
> unsigned u; scanf ("%u", & u);
> The user types "1", he gets 1.
> The user types "-1", he gets something that might be different
> on different machines...


One solution to this might be to add a syntax that specifies that a
leading sign is not allowed. For example, with scanf("%u", &u), if
the user enters "-1", UINT_MAX is stored in u. With scanf("%+u", &u),
"-1" would be invalid (though "+1" might be ok).

In the absence of such a language change, if you read the line into a
string to be processed with sscanf() (which is the recommended
practice anyway), you can check for a sign character before calling
sscanf().

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      05-02-2006
regis <(E-Mail Removed)> wrote:

> P.J. Plauger wrote:
> > I, for one, think -1 is a great shorthand for the largest
> > representable unsigned value. You don't get tired of writing 'f's,
> > and you don't have to know how many to write.

>
> Sure. On the programmer side, it is useful:
>
> size_t k, n= strlen (text);
> for (k= n-1; k != (size_t)-1; k--) { ... }
>
> My remark was about *text* representations that the user deals with:
>
> int i; scanf ("%i", & i);
> The user types "1", he gets 1.
> The user types "-1", he gets -1.
>
> unsigned u; scanf ("%u", & u);
> The user types "1", he gets 1.
> The user types "-1", he gets something that might be different
> on different machines...


Then again, it is dubitable whether using scanf() itself for user input
is a good idea.

Richard
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ 7.17 What's the difference between dynamic and lexical (static) scoping? Between local() and my()? PerlFAQ Server Perl Misc 0 01-06-2011 05:00 PM
Difference between << and += for Strings and Arrays. Bug? Pieter Hugo Ruby 13 11-26-2009 10:16 AM
Differences between perhaps-similar constructs? gentsquash@gmail.com Javascript 4 05-28-2008 01:23 PM
Difference between bin and obj directories and difference between project references and dll references jakk ASP .Net 4 03-22-2005 09:23 PM
Exact difference between 'const char *' and 'char *', also diff between 'const' and 'static' Santa C Programming 1 07-17-2003 02:10 PM



Advertisments