0

I am trying something simple in C, a program to get the exchange and do some conversions. To make sure scanf gets the right type I placed it into a while loop, which continues to ask for input until a number is inserted. If I enter a character instead of a number it does not ask again for an input.

exRate = 0;
scanfRes = 0;

while(exRate <= 0){
    printf("Enter the exchange rate:");
    while(scanfRes != 1){
        scanfRes = scanf(" %f", &exRate);
    }


    if(scanfRes == 1 && exRate > 0){
        break;
    }

    printf("Exchange rate must be positive.\n");
}

UPDATE: As this is a course assignment, I was not supposed to use anything outside of the taught material. When I asked the academic staff about handling unexpected input, I got an answer that this is a scenario I am not supposed to take into consideration.

The answers and help in the comments is all useful and I added 1 to all useful suggestions. The staff answer makes this question no longer needed.

Dean
  • 7,814
  • 8
  • 30
  • 31
  • 2
    http://stackoverflow.com/questions/1716013/why-is-scanf-causing-infinite-loop-in-this-code – AlexD Nov 13 '14 at 22:04
  • 2
    Think about your loop logic a bit more. `scanf` returns `1` if it read successfully; or `0` if you entered a non-number, or `EOF` if the input was closed. The innermost `while` loop doesnt make any sense – M.M Nov 13 '14 at 22:07
  • 1
    When `scanf()` finds invalid input, it pushes back and returns prematurely. You have to consume the characters that are not numbers, otherwise `scanf` will always be failing with the same erroneous input. – Filipe Gonçalves Nov 13 '14 at 22:09
  • @AlexD: I thought of that, but this is a C course assignment, and they supply the input in files. If I clear the buffer it will flush all the input that I got from the input file. – Dean Nov 13 '14 at 22:27
  • @Dean Did you check this answer: http://stackoverflow.com/a/1716066/3246555? – AlexD Nov 13 '14 at 22:30
  • @AlexD: Yes, aside from switching to another method for getting input (I would be happy to do that, but the assignment allows to use only what they tough so far) the main proposition is to clear STDIN. – Dean Nov 13 '14 at 22:53
  • @Dean Maybe I did not understand something. For me it looks that (1) only characters before next digit are removed, so the next number be read successfully; (2) stdin is redefined in your case, and the solution should work for files as well. – AlexD Nov 13 '14 at 23:00
  • @AlexD Sorry, maybe I missed something. I will look into it again and try it. Thank you. – Dean Nov 13 '14 at 23:11
  • @AlexD The answers suggested both consume input until the next digit. This unfortunately consumes '+', '-', '.'. – chux - Reinstate Monica Nov 13 '14 at 23:16
  • @chux Yep, your solution looks more robust. – AlexD Nov 13 '14 at 23:18

1 Answers1

1

Change handling of scanf() result.

If the input is not as expected, either the offending input data needs to be read or EOF should be handled.

for (;;) {
    printf("Enter the exchange rate:");
    scanfRes = scanf("%f", &exRate);
    if (scanfRes == 0) {
      printf("Exchange rate must be numeric.\n");
      // somehow deal with non-numeric input, here just 1 char read & tossed
      // or maybe read until end-of-line
      fgetc(stdin);
    } else if (scanfRes == EOF) {
      // Handle EOF somehow
      return;   
    } exRate > 0){
      break;
    }
    printf("Exchange rate must be positive.\n");
 }

Note: the " " in " %f" is not needed. "%f" will consume leading white-space.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • There's nothing I would love more than to go for a better C solution here. But I am supposed to follow the course material and allowed to use only the functions and libraries they taught in the university. I am checking it with the academic staff... maybe they didn't take it into account. – Dean Nov 13 '14 at 23:15
  • 1
    @dean There are no new standard library functions here, aside from `fgetc()`, that is not all ready in your post. Thus I do not see how "use only the functions and libraries" applies. If using `fgetc()` is a problem, then replace it with `scanf("%*c")` for the same effect. – chux - Reinstate Monica Nov 13 '14 at 23:19