2

My program works well with invalid inputs such as char, number out of range, but a problem happens when a floating point value such as 1.2 is entered. The program prints menu again, and asks user for input before printing error message. What I try to fix is don't print menu again, but still struggle. For example,

Make your selection: 1.1 [Here is menu content] Make your selection: That selection isn't valid. Please try again.

#include <stdio.h>

#define QUIT 0

int menu();

int main(void)
{
    int choice;
    char c;
    choice = menu();
    while(choice != QUIT)   //execute so long as choice is not equal to QUIT
    {
        choice = menu();
    }
}

int menu(void)
{
    int option;

    printf("Text Encoder Service\n\n");
    printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
    printf("2.\tEnter name of output file (currently not set)\n");
    printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
    printf("4.\tEncode the text\n\n");
    printf("0.\tQuit\n\n");
    printf("Make your selection: ");

    while( (scanf(" %d", &option) != 1) /* non-numeric input */
        || (option < 0)               /* number too small */
        || (option > 4))              /* number too large */
    {
        fflush(stdin);                    /* clear bad data from buffer */
        printf("That selection isn't valid. Please try again.\n\n");
        printf("Your choice? ");
    }
    return option;
}

3 Answers 3

0

I finally could validate floating input. Thanks your advices so much! This is my new code. What else do you think an invalid input?

int menu(void)
{
    int option, parsed_inputs;
    char overcount_char;
    parsed_inputs = 1;

    printf("Text Encoder Service\n\n");
    printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
    printf("2.\tEnter name of output file (currently not set)\n");
    printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
    printf("4.\tEncode the text\n\n");
    printf("0.\tQuit\n\n");
    printf("Make your selection: ");

    parsed_inputs = scanf_s("%d%c", &option, &overcount_char);
    while( parsed_inputs > 1 )              /* number too large */
    {
        if((overcount_char != '\n') || (option < 0) || (option > 4))
        {
            fflush(stdin);                    /* clear bad data from buffer */
            printf("That selection isn't valid. Please try again.\n\n");
            printf("Your choice? ");
            scanf_s("%d%c", &option, &overcount_char);
        }
        else
            break;
    }
    return option;
}
Sign up to request clarification or add additional context in comments.

Comments

0

An input of 1.1 leads to the following:

  • The string is read into an internal buffer.
  • It is then matched against the given format string.
  • On the first non-match, the scanf() call is stopped and it returns the number of successfully scanned values.

Let's test it:

#include <stdio.h>
int main(int argc, char ** argv)
{
    while (1) {
        int option;
        int n = scanf(" %d", &option);
        printf("%d %d\n", n, option);
        if (n <= 0) break;
    }
}

This program reads one line.

Suppose I enter 123 132.

Then the following happens: * As the format string starts with a space, all leading whitespace is consumed. In this case, there is none. * Then the 123 is consumed and put into option. * As the format string is over now, parsing is stopped, n=1 and option=123. * In the next loop run, the same happens, giving n=1 and option=123.

But: Suppose I enter 123.321 or 123#321.

Then the following happens: * As the format string starts with a space, all leading whitespace is consumed. In this case, there is none. * Then the 123 is consumed and put into option. * As the format string is over now, parsing is stopped, n=1 and option=123. * In the next loop run, there is no whitespace to skip. .321 resp. #321 is tried to be matched to %d, but these are no valid ints. Thus, we get n=0 and option keeps its old value. * As no characters are consumed from the input stream (the one used is put back again), the same happens over and over again - that's why I put if (n <= 0) break;.

So you see that the behaviour has nothing to do with floating point, as it doesn't matter if we use . or # to "disturb".

We change our program to

#include <stdio.h>
int main(int argc, char ** argv)
{
    while (1) {
        int option; char c;
        int n = scanf("%d%c", &option, &c);
        printf("%d %d %d %c\n", n, option, c, c);
        if (n <= 0) break;
    }
}

and run it, inputting 4.235#6x7.

Then we get * n=2, option=4 and c='.' at the first run * n=2, option=235 and c='#' at the 2nd run * n=2, option=6 and c='x' at the 3rd run * n=2, option=7 and c='\n' (newline) at the 3rd run

and are prompted for further input.

This makes you open to the option

(parsed_inputs = scanf("%d%c", &option, &overcount_char)) < 1

and then check what overcount_char contains, whenever parsed_inputs is > 1.

2 Comments

I still cannot work through the problem with your hint. Can you explain more?
@user3077220 I tried to do so by reworking the answer.
-1

I think you should put scanf() before the while loop and explicitly check "option" variable in the while loop. What happening is that, here scanf() will always return the value 1, because scanf() returns no. of arguments read successfully. Hence this while loop will run forever. For further information check this link->http://www.cplusplus.com/reference/cstdio/scanf/

Hope this helps!

2 Comments

Why should scanf() always return 1? If I enter something invalid, it will of course return 0.
scanf() would always return the number of inputs you are trying to take from it.. e.g. #include<stdio.h> int main() { int i,j; printf("No of values printed=%d\n", scanf("%d %d",&i,&j)); return 0; } This would return 2 as you are accepting 2 integers from a single scanf(). If at run time scanf() fails to accept from stdin or if you are taking chars or floats, then it should return 0, EOF or some random error. Now,in your code you are not actually checking the input from scanf(), but you are checking the value returned by scanf().

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.