views:

458

answers:

5

How do you use the return value from scanf to make sure it is a double I've got?

double input;

do {  /* do this as long as it not a double */
  printf("Input?");
  scanf("%lf", &input);
} while(scanf("%lf", &input) != 1); /* this will not work */
+2  A: 

scanf() and friends return the number of input items successfully matched and assigned. No information related to type. But since you've specified lf in the conversion string, you'll get a double - I think I'm missing your point though.

Michael Foukarakis
A: 

scanf() will return the number of input given / provided. It will not return any data-type related result.

Devi
+1  A: 

Just like Michael said, scanf() returns and integer that represents the number of elements suceccesfully read. As far as I can see from the manpage you can't use the return value to verify if what was read is a double or not.

lordsandwich
+2  A: 

I think this is what you're trying to do:

double input;

do {  /* do this as long as it not a double */
  printf("Input?");
} while(!scanf("%lf", &input));
Dumb Guy
+1  A: 

scanf will return the number of items assigned. In your case, since the format string contains only %lf, it will return 1 exactly in the case where you got your double. The problem with your code is that you first call scanf inside the loop, which will read the double off the stream. Then, in your while condition, you call scanf again, but there isn't another double to be read, so scanf does not do anything.

The way I would write your code would be something like

int no_assigned;
do {
    printf("Input?");
    no_assigned = scanf("%lf", &input);
} while (no_assigned != 1);

The extra variable is there because it feels to me like the scanf is code that should be inside the loop, not in the while condition, but that is really a personal preference; you can eliminate the extra variable and move (note, move, not copy) the scanf call inside the condition instead.

EDIT: And here's the version using fgets that's probably better:

double input;
char buffer[80];

do {
    printf("Input? ");
    fflush(stdout); // Make sure prompt is shown
    if (fgets(buffer, sizeof buffer, stdin) == NULL)
        break; // Got EOF; TODO: need to recognize this after loop
    // TODO: If input did not fit into buffer, discard until newline
} while (sscanf(buffer, "%lf", &input) != 1);
jk
+1 for saying it's personal preference. I prefer it inside the loop myself, but who am I to judge?
Chris Lutz
I did this but I have to fflush(stdin); after scanf or it will loop forever ( if I put it in the whilecondition)?
Chris_45
No, don't do `fflush(stdin);` as that is not guaranteed to do what you think it does. The `scanf` will indeed leave a newline in the input. If you use `scanf` in the future, that should not matter as `scanf` skips whitespace, but if you use some other input function, you will need to get rid of the newline before that. In fact, a better approach would probably be to input a line in the `while` loop with `fgets` and then use `sscanf` on that line in the same way as you now use `scanf`.
jk
Ok, great answer BTW! But if you read something in and leave stuff "behind" does that mean you have made a poor job reading?And I understand you have an alternative thing going in there but I don't really comprehend this.Is there a safe method that swallows everything including the \n?
Chris_45
The "safer" method is what I edited in afterwards of using `fgets` as `fgets` reads complete lines so you won't leave extra newlines into the buffer. `scanf` is not really well-suited for interactive input; the comp.lang.c FAQ has a few things to say about it: http://c-faq.com/stdio/scanfprobs.html
jk
Ok, great thanks!
Chris_45