473,327 Members | 1,976 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,327 software developers and data experts.

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

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
9 2653

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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Jeff Thies | last post by:
I have this: var hash=new Array(); hash='some_value'; hash='some other value'; Whar do you call that in javascript? I know it's possible to define this in one line, but I've forgotten how....
3
by: Colleyville Alan | last post by:
I am constructing a SQL command from a function. Some code builds the WHERE clause in a looping structure and passes that as an argument to the SQL-building function. But the results do not...
1
by: Herve MAILLARD | last post by:
Hi, My dataGrid is filled by a dataset. I want to modify the data but I don't want that the user can add a new line... How can I do ? Thanks for your help. H. MAILLARD
1
by: Alan Silver | last post by:
Hello, I have the following line of code in a script... litMsg.Text = Server.MapPath("/"); where litMsg is an ASP.Net Literal control. When I try and run this page, I get the error ... ...
3
by: news | last post by:
Hi I have problem: My program reads 3 digits from keyboard using scanf("%d", &a) then calculate it,everything is OK until I put "1,2,3,4,5,6,7,8,9,0" but if I put "char " like "a,b,c,d etc" my...
4
by: Oliver Block | last post by:
Hi, I have an 'a' element with 'display:block' and 'float: left' followed by a table element within a div; Now I want to force the table to appear in the "next line". That does work without...
4
by: Hexes | last post by:
Ok i am making program wicth has from txt file put lines from first to last. well If i code it like this: ---- nFileNum = FreeFile Open "C:/VB/VB.txt" For Input As nFileNum FreeNum = 1
12
by: Dom | last post by:
VB had a "line" control, just a simple line that let you separate controls without the wasted space of a Groupbox. Did CSharp drop this? Dom
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...

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.