By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,016 Members | 2,265 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,016 IT Pros & Developers. It's quick & easy.

what's the line "scanf..." doing?

P: n/a
Hi,
here's a fract of codes, and what's the line "scanf("%lf%*[^\n]",
&cvi)" doing?
=============================
do {
printf("\nCoefficient: ");
scanf("%lf%*[^\n]", &cvi);
getchar();

} while (cvi <= 0.0);

=============================
%*[^\n] means what?

Thanks in advance for any help:)

Dec 9 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a

Cao Yi wrote:
Hi,
here's a fract of codes, and what's the line "scanf("%lf%*[^\n]",
&cvi)" doing?
=============================
do {
printf("\nCoefficient: ");
scanf("%lf%*[^\n]", &cvi);
getchar();

} while (cvi <= 0.0);

=============================
%*[^\n] means what?
It /should/ absorb any characters up to (but not including) the next
newline

% - introduces a conversion string
* - suppresses assignment, so that anything that this conversion
string catches is discarded
[ - matches a regular expression, is paired with a closing ]
^ - inverts the regular expression, such that anything stated is /not/
counted as a match
\n - indicates a newling character

Put them together and you get
a conversion string that
suppresses assignment and
matches a non-empty sequence of characters
that does not contain a newline

Dec 9 '06 #2

P: n/a
Cao Yi said:
Hi,
here's a fract of codes, and what's the line "scanf("%lf%*[^\n]",
&cvi)" doing?
Failing to check the value returned by scanf. In other words, the code is
broken.

=============================
do {
printf("\nCoefficient: ");
If you want to be sure that the prompt appears before the program blocks for
input, either write a newline character at this point, or fflush(stdout).
scanf("%lf%*[^\n]", &cvi);
getchar();

} while (cvi <= 0.0);

=============================
%*[^\n] means what?
The % means "conversion specification immediately follows."
The * means "suppress assignment - consume data from stdin, but I'm not
giving you an address at which to store the corresponding value, so just
drop it."
If it were not for the ^, we'd have [\n], which would mean "match the
longest non-empty string consisting entirely of input characters from the
set between brackets (in this case, as many newline characters as you
like)."
But we do have a ^. The [^\n] means "match the longest non-empty string
consisting entirely of input characters NOT from the set between brackets."

In other words, "%*[^\n]" means "read and discard everything up to but not
including the next newline character".

All of this can easily be deduced from the scanf documentation in your C
book. If you don't have a C book that describes the standard C library in
this kind of detail, you need to get one. "The C Programming Language", 2nd
edition, Kernighan and Ritchie, fits the bill nicely.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 9 '06 #3

P: n/a
Cao Yi wrote:
Hi,
here's a fract of codes, and what's the line "scanf("%lf%*[^\n]",
&cvi)" doing?
=============================
do {
printf("\nCoefficient: ");
scanf("%lf%*[^\n]", &cvi);
getchar();

} while (cvi <= 0.0);

=============================
%*[^\n] means what?

Thanks in advance for any help:)
The %lf conversion specifier tries to convert the scanned input into a
double value, which is stored at the address specified by &cvi. The %*
tells scanf() not to store the value converted by the following
specifier into any variable. The [ character starts a 'scan set'
sequence, which means that scanf() will try to match, or not match, the
scanned input with what's specified with the scan set. The ^ immediatly
after the [ tells scanf() to try to match all input characters which
_do not_ occur after the ^, which in this case is a newline. The ]
terminates the scan set.

So, in summary, the scanf() call tries to convert and store to the
given variable a double value from the initial part of the input. After
that, it reads and discards all input until a newline is encountered.

PS. The given code is rather fragile. I'd read in whole lines with
fgets() and scan them with sscanf() or strtod().

Dec 9 '06 #4

P: n/a
Thanks for all of you!

The %lf conversion specifier tries to convert the scanned input into a
double value, which is stored at the address specified by &cvi.
//Yes, it does!
The %* tells scanf() not to store the value converted by the following
specifier into any variable.
//Oh, this is the point which confuses me so much!
// As the %ld is corresponding to &cvi, what's corresponding to %*?

I wrote a small procedure using this fract codes:
======================================
#include "stdio.h"

int main() {
double cvi = 0.0;

do {
printf("\nCoefficient of variation of substitution rate among sites
(must be positive)\n");
scanf("%lf%*[^\n]", &cvi);
getchar();
} while (cvi <= 0.0);

return 0;
}
======================================
When I input 1.5, program will ask you to input again,
but when input 9.2, program will exit normally, what's the problem
here?
Obviously, 1.5 and 9.2 are both double numbers.

On 12月9日, 下午12时21分, "santosh" <santosh....@gmail.com>
wrote:
Cao Yi wrote:
Hi,
here's a fract of codes, and what's the line "scanf("%lf%*[^\n]",
&cvi)" doing?
=============================
do {
printf("\nCoefficient: ");
scanf("%lf%*[^\n]", &cvi);
getchar();
} while (cvi <= 0.0);
=============================
%*[^\n] means what?
Thanks in advance for any help:)The %lf conversion specifier tries to convert the scanned input into a
double value, which is stored at the address specified by &cvi. The %*
tells scanf() not to store the value converted by the following
specifier into any variable. The [ character starts a 'scan set'
sequence, which means that scanf() will try to match, or not match, the
scanned input with what's specified with the scan set. The ^ immediatly
after the [ tells scanf() to try to match all input characters which
_do not_ occur after the ^, which in this case is a newline. The ]
terminates the scan set.

So, in summary, the scanf() call tries to convert and store to the
given variable a double value from the initial part of the input. After
that, it reads and discards all input until a newline is encountered.

PS. The given code is rather fragile. I'd read in whole lines with
fgets() and scan them with sscanf() or strtod().
Dec 9 '06 #5

P: n/a
Cao Yi wrote:
Thanks for all of you!
You're welcome but please don't top-post. The material you quote belong
before or interspersed with your text, not below it.
The %lf conversion specifier tries to convert the scanned input into a
double value, which is stored at the address specified by &cvi.
//Yes, it does!
Why are you prefixing your replies with //? Also, in future, in the
code you post, don't include C99 style comments, i.e. //. They're
mangled in Usenet which results in problems for those who want to
compile your code to verify it.
The %* tells scanf() not to store the value converted by the following
specifier into any variable.
//Oh, this is the point which confuses me so much!
// As the %ld is corresponding to &cvi, what's corresponding to %*?
Nothing. That's the purpose of the *. It tells scanf() to scan the
input according to the format specifier, but to throw away the scanned
result, since no storage is provided for it. It useful when you want to
skip past specific input fields.
I wrote a small procedure using this fract codes:
======================================
#include "stdio.h"
When you use the double quotes version of include, you're telling the
compiler to look in places other than where it would look normally by
default. Since stdio.h is a standard library header, you probably don't
want this behaviour. If you happen to have some other header named
stdio.h, the compiler is likely to include that instead of the standard
stdio.h. This could very well result in errors. Use the angled brackets
form of include when you're including standard header files and use the
double quotes form for files you supply seperately.

So modify the above include to:
#include <stdio.h>
int main() {
Under C99 standard, there're only two fully conforming forms of
prototype for main(). They are:
int main(void) and
int main(int argc, char **argv) or int main(int argc, char *argv[])

So change the above to:
int main(void)
double cvi = 0.0;

do {
printf("\nCoefficient of variation of substitution rate among sites
(must be positive)\n");
Don't include a line break directly within string literals. Use a
newline escape sequence and split a long string literal into one or
more seperate, adjacent string literals. Adjacent string literals are
automatically concactenated by the compiler. So:

printf("\nCoefficient of variation of substitution rate among
sites\n"
"(must be positive)\n");
scanf("%lf%*[^\n]", &cvi);
Always check the return value of scanf(), (and other library
functions), for failure. scanf() returns the number of fields it has
successfully converted and stored. So in this case, scanf() should
return one, if it has succeeded. So check it like:

if(scanf("%lf%*[^\n]", &cvi) != 1) deal_with_failure();
else continue_execution();
getchar();
} while (cvi <= 0.0);
Note that directly comparing floating point values may not give the
expected results. Instead you should allow for a small range of the
value above and below the value which you're testing against.

Alternatively, if your compiler supports C99 use the floating point
comparision macros provided in math.h. In this case you can do:

} while (islessequal(cvi, 0.0));

For a full list of C99 standard library functions and their
descriptions, look at the link below:
<http://www.dinkumware.com/manuals/>

Note that though most compilers support C99 partially, (often near
complete), very few claim full compliance. This means that some
functions may not be available across compilers. On the whole, it's
safer to stick with C90 for the moment. Use C99 features, only if you
really need them and you cannot portably implement them with C90 alone.
Such requirements are few.

Dec 9 '06 #6

P: n/a
Thanks very much, i'll never top-post in this unenet from now on.
I modified the codes and compiled on another machine, it works ok.

Dec 9 '06 #7

P: n/a
On 9 Dec 2006 00:32:06 -0800, "Cao Yi" <ir********@gmail.comwrote:
>Thanks for all of you!

The %lf conversion specifier tries to convert the scanned input into a
double value, which is stored at the address specified by &cvi.
//Yes, it does!
The %* tells scanf() not to store the value converted by the following
specifier into any variable.
//Oh, this is the point which confuses me so much!
// As the %ld is corresponding to &cvi, what's corresponding to %*?
Since the * tells scanf not to store the scanned data, there is no
corresponding argument. A corresponding argument is allowed/required
only for those conversion specifications which cause data to be
stored.
>
I wrote a small procedure using this fract codes:
======================================
#include "stdio.h"

int main() {
double cvi = 0.0;

do {
printf("\nCoefficient of variation of substitution rate among sites
(must be positive)\n");
scanf("%lf%*[^\n]", &cvi);
getchar();
} while (cvi <= 0.0);

return 0;
}
======================================
When I input 1.5, program will ask you to input again,
but when input 9.2, program will exit normally, what's the problem
here?
Obviously, 1.5 and 9.2 are both double numbers.
After correcting the #include to use angle brackets and removing the
line break from the printf string literal, I could not duplicate the
symptom you describe. I stepped through with code twice and typed 1.5
followed by ENTER and 1.5 xxx followed by ENTER. In both cases, the
program terminated normally.

Just for reference, neither of your inputs is a double. Both are just
a sequence of characters. After scanf processes the input, the
**converted value** is stored as a double in cvi. If you had typed 1
(which could be considered an integer), scanf would have converted it
to the double value 1.0 and stored in cvi. The same is true if you
had typed 1xyz.
Remove del for email
Dec 9 '06 #8

P: n/a
I cannot repeat the sydrome again too, curiously!
It did so on my machine using in company, Windows XP, cygwin.
The computer using home without cywin, but I compile it with the IDE
Dev-cpp (Mingv32).

Dec 10 '06 #9

P: n/a
On 9 Dec 2006 01:11:35 -0800, "santosh" <sa*********@gmail.comwrote:
Cao Yi wrote:
int main() {

Under C99 standard, there're only two fully conforming forms of
prototype for main(). They are:
int main(void) and
int main(int argc, char **argv) or int main(int argc, char *argv[])
Preliminary nit: there is no category 'fully conforming program' in
the Standard, and (as frequently discussed here and on comp.std.c) the
category 'strictly conforming' is so strict it is useless and the
category 'conforming' is so lax it is useless.

More substantively, the oldstyle/K&R1:
int main () { ... }
int main (argc, argv) int argc; char**argv; { ... }
are still completely standard, and in C89 but not C99 you can omit the
declaration for argc, and in either you can use char*argv[] .

The prototype forms are better style, and allow errorchecking
recursive calls, although such calls are usually bad style anyway.

<snip>
} while (cvi <= 0.0);

Note that directly comparing floating point values may not give the
expected results. Instead you should allow for a small range of the
value above and below the value which you're testing against.
True in general, but usually OK for zero or sign checks.
Alternatively, if your compiler supports C99 use the floating point
comparision macros provided in math.h. In this case you can do:

} while (islessequal(cvi, 0.0));
But those don't do fuzzy. They do safe-against-NaN.
- David.Thompson1 at worldnet.att.net
Dec 26 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.