473,397 Members | 1,969 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

scanf pushes back two chars?

I ran the following program on gcc:

#include <stdio.h>

int main(void)
{
unsigned int i;
char c;

if (scanf("%x", &i) == 1)
printf("i = %u\n", i);

if (scanf("%c", &c) == 1)
printf("c = %c\n", c);

return 0;
}

I gave it the following input:

0xg

I expected the first scanf call to fail, since 'g' is not a hex digit
and "0x" is not a hex number. The 'g' would then be pushed back onto
the input stream, and the only output would be:

c = g

Instead, I got the following output:

i = 0
c = x

Is this output correct? It seems like the first scanf call must have
pushed *two* characters ('x' and 'g') back onto the input stream. Was
it supposed to?

--Steve
Nov 14 '05 #1
7 1418
On 5 Sep 2004 21:24:07 -0700, st*********@hotmail.com (Steve Kobes)
wrote in comp.lang.c:
I ran the following program on gcc:

#include <stdio.h>

int main(void)
{
unsigned int i;
char c;

if (scanf("%x", &i) == 1)
printf("i = %u\n", i);

if (scanf("%c", &c) == 1)
printf("c = %c\n", c);

return 0;
}

I gave it the following input:

0xg

I expected the first scanf call to fail, since 'g' is not a hex digit
and "0x" is not a hex number. The 'g' would then be pushed back onto
the input stream, and the only output would be:

c = g

Instead, I got the following output:

i = 0
c = x

Is this output correct? It seems like the first scanf call must have
pushed *two* characters ('x' and 'g') back onto the input stream. Was
it supposed to?

--Steve


What makes you think it pushed back two characters? There are several
other possible explanations.

There have been implementations of scanf() that do not handle a "0x"
prefix properly, yours could be one. Have you verified the results
when you enter "0xfg"?

In any case, you have a defect in your library's implementation of the
function, which is a library problem, not a gcc problem. I suggest
you contact the source of the library.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #2
Steve Kobes wrote:
I ran the following program on gcc:

#include <stdio.h>

int main(void)
{
unsigned int i;
char c;

if (scanf("%x", &i) == 1)
printf("i = %u\n", i);

if (scanf("%c", &c) == 1)
printf("c = %c\n", c);

return 0;
}

I gave it the following input:

0xg

I expected the first scanf call to fail, since 'g' is not a hex digit
and "0x" is not a hex number. The 'g' would then be pushed back onto
the input stream, and the only output would be:

c = g

Instead, I got the following output:

i = 0
c = x

To add to your puzzlement, with gcc 3.41 I get
i = 0
c = g

Your result seems right and mine wrong. Since the specification for
strtoul reads

If the value of base is 16, the characters 0x or 0X may optionally
precede the sequence of letters and digits, following the sign if
present.

4 The subject sequence is defined as the longest initial subsequence
of the input string, starting with the first non-white-space
character, that is of the expected form. The subject sequence contains
no characters if the input string is empty or consists entirely of
white space, or if the first non-white-space character is other than a
sign or a permissible letter or digit.

The longest subsequence of the expected form is '0', with the next tail
beginning with 'x'. Note that the '0x' is optional, so '0' *is* of the
expected form.

Nov 14 '05 #3
In article <news:2q************@uni-berlin.de>
Martin Ambuhl <ma*****@earthlink.net> wrote:
... the specification for strtoul reads

If the value of base is 16, the characters 0x or 0X may optionally
precede the sequence of letters and digits, following the sign if
present.

4 The subject sequence is defined as the longest initial subsequence
of the input string, starting with the first non-white-space
character, that is of the expected form. The subject sequence contains
no characters if the input string is empty or consists entirely of
white space, or if the first non-white-space character is other than a
sign or a permissible letter or digit.

The longest subsequence of the expected form is '0', with the next tail
beginning with 'x'. Note that the '0x' is optional, so '0' *is* of the
expected form.


The scanf() specification in the ANSI/ISO C standard -- at least the
original C89 one -- is confusing.

When I wrote the scanf engine for 4.4BSD, I decided that input of
the form:

4.123e+oops

would match %f (and similar) specifications through the "4.123"
but not the "e+oops" part, and thus leave "e+oops" unread in the
stream, available for subsequent input operations (scanf %c
conversions, getc(), etc.).

Since then, I have been told that scanf is supposed to be highly
destructive and discard some or all of the unusable "e+oops" because
it *begins* with a legitimate sequence, but is not actually one.
(Compare 4.123e+oops with 4.123e+17andtrailingstuff, for instance.)

A few example of just what is to be matched, what is to be discarded,
and what is to be left behind in the input stream, on various inputs
for various formats, would help implementors a great deal, I think.
(It certainly would have helped me.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #4
Chris Torek wrote:
.... snip ...
Since then, I have been told that scanf is supposed to be highly
destructive and discard some or all of the unusable "e+oops" because
it *begins* with a legitimate sequence, but is not actually one.
(Compare 4.123e+oops with 4.123e+17andtrailingstuff, for instance.)

A few example of just what is to be matched, what is to be discarded,
and what is to be left behind in the input stream, on various inputs
for various formats, would help implementors a great deal, I think.
(It certainly would have helped me.)


Most, if not all, of these anomalies could be handled in one swell
foop by increasing the pushback limit of ungetc to 3.

--
"I'm a war president. I make decisions here in the Oval Office
in foreign policy matters with war on my mind." - Bush.
"If I knew then what I know today, I would still have invaded
Iraq. It was the right decision" - G.W. Bush, 2004-08-02
Nov 14 '05 #5
Martin Ambuhl <ma*****@earthlink.net> wrote:

if (scanf("%x", &i) == 1)
printf("i = %u\n", i);

if (scanf("%c", &c) == 1)
printf("c = %c\n", c);

I gave it the following input:

0xg

Instead, I got the following output:

i = 0
c = x


To add to your puzzlement, with gcc 3.41 I get
i = 0
c = g

Your result seems right and mine wrong.


Isn't this a feature of glibc rather than gcc ?
Nov 14 '05 #6
Martin Ambuhl wrote:
Steve Kobes wrote:
I expected the first scanf call to fail, since 'g' is not
a hex digit and "0x" is not a hex number. The 'g' would
then be pushed back onto the input stream, and the only
output would be:

c = g

Instead, I got the following output:

i = 0
c = x


To add to your puzzlement, with gcc 3.41 I get
i = 0
c = g

Your result seems right and mine wrong.
[snip strtoul spec]


In scanf,

"An input item is defined as the longest sequence of input characters
(up to any specified maximum field width) which is an initial
subsequence of a matching sequence." (C89)

"An input item is defined as the longest sequence of input characters
which does not exceed any specified field width and which is, or is a
prefix of, a matching input sequence." (C99, AFAICT trying to say the
same thing more clearly)

And in the next paragraph:

"If the input item is not a matching sequence, the execution of the
directive fails: this condition is a matching failure." (C89 and C99)

This sounds pretty clear to me: given 0xg with %x, "0x", not "0", is
the input item, and it is a matching failure because "0x" is not a
matching input sequence. And there's no reason to think that the 'x'
should be pushed back onto the input stream.

Same with 4.123e+oops and %f... the input item is "4.123e+" (the
longest sequence that COULD begin a match), all of which is read and
discarded.

This means GCC gets it wrong for both Martin and me (in two different
ways, which I don't understand since I'm also using 3.4.1). Visual
C++ 6 seems to do it correctly.
Nov 14 '05 #7
ol*****@inspire.net.nz (Old Wolf) writes:
Martin Ambuhl <ma*****@earthlink.net> wrote:
>
> if (scanf("%x", &i) == 1)
> printf("i = %u\n", i);
>
> if (scanf("%c", &c) == 1)
> printf("c = %c\n", c);
>
> I gave it the following input:
>
> 0xg
>
> Instead, I got the following output:
>
> i = 0
> c = x


To add to your puzzlement, with gcc 3.41 I get
i = 0
c = g

Your result seems right and mine wrong.


Isn't this a feature of glibc rather than gcc ?


Yes. More precisely, it's a feature of whatever C library you happen
to be using. (gcc is commonly used with libraries other than glibc.)

<OT>
There's no gcc 3.41, at least not yet; the latest release is 3.4.1.
</OT>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 14 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: B Thomas | last post by:
Hi, I was reading O'Reilly's "Practical C programming" book and it warns against the use of scanf, suggesting to avoid using it completely . Instead it recomends to use using fgets and sscanf....
5
by: Eduardo Olivarez | last post by:
The following code does not work correctly on my machine. Either one of the scanf()'s alone work perfectly. However, when they are combined, the second scanf() call just reads what the first one...
6
by: Rob Thorpe | last post by:
Given the code:- r = sscanf (s, "%lf", x); What is the correct output if the string s is simply "-" ? If "-" is considered the beginning of a number, that has been cut-short then the...
2
by: Bernard Liang | last post by:
In response, I have another question about the scanf family. After reading in a %d value, for instance, do they immediately wade through all subsequent whitespace until a non-whitespace character...
3
by: sosij.morris | last post by:
Hi. I'm trying to find some tutorial-type information on using scanf's regular-expression subset for parsing - to no avail so far. I've looked through quite a few posts to clc, but none that...
68
by: stasgold | last post by:
Hello. I maybe reinvent the weel ... I'm trying to read positive integer number with the help of scanf, if the input value is not positive number but negaive one zero or char , i have to reread...
27
by: Simon Biber | last post by:
The following Example 3 is given in the 1999 C standard for the function fscanf: I have tested several implementations and none of them get the last case right. In no case does fscanf return 0...
26
by: vid512 | last post by:
hi. i wanted to know why doesn't the scanf functions check for overflow when reading number. For example scanf("%d" on 32bit machine considers "1" and "4294967297" to be the same. I tracked...
51
by: deepak | last post by:
Hi, For the program pasted below, scanf is not waiting for the second user input. Can someone suggest reason for this? void main() { char c;
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.