0

I'm learning C++.

nav is an integer .

I want to ask user for typing a valid value, if he / she type an invalid value.

void main()
{
    printf("Type an integer : ");
    if(!scanf("%d", &nav))
    {
        system("cls");
        printf("Invalid ! \n");
        main();
    }
}

But it's blinking after typing first value . It's blinking like reloading screen. I think it's infinite loop.

How can i do it in right way ? I want to ask a number from users, until it's typing a real number .

2
  • recursively calling main() is a little weird. Commented Dec 18, 2011 at 0:02
  • 7
    1) void main() is illegal in C++. 2) calling main() is illegal in C++. Commented Dec 18, 2011 at 0:03

3 Answers 3

3

If the user types an invalid input, scanf() won't consume it, and you'll be left peeking the same offending input character forever. You need to first read whatever the user enters — I recommend using std::getline() — and then try to parse that with strtol(), sscanf() or std::istringstream. Don't use atoi() because it doesn't report failures.

int nav;
{
    string line;
    while (getline(cin, line))
        if (istringstream(line) >> nav)
            break;
}

EDIT: See the comments for a rather beautiful rendition of the above logic. I've left it out of the answer because: a) I don't want to steal someone else's idea, and b) I'm not sure I'd present a newcomer to C++ with that formulation — not in one go, at least.

P.S.: You can't call main() in C++.

Sign up to request clarification or add additional context in comments.

4 Comments

@Marcelo Cantos, thank you but can you give me an example usage for my source code ? I'm new learning C++ and i couldn't adapt this to my codes.
You could compact this into for (std::string line; std::getline(std::cin, line) && !(std::istringstream(line) >> nav); ) { }.
@KerrekSB: Very nice! It's one of those, "Damn, why couldn't I have had that idea!" moments.
@fazo: I'm not sure what point you're making. Yes, calling main() is illegal, but the OP's symptoms suggest that the recursive call was, in fact, succeeding.
1

Two things.

Scanf needs the 'enter' key pressed before it will process input, so the blinking could just be the cursor waiting for the next key.

Also, calling main from main is fairly non-standard. You should look into a 'while' loop.

2 Comments

" the blinking could just be the cursor waiting for the next key." No no , whole screen blinking, like reloading screen.
Then I think the other two answers are correct. . If the character waiting in the input buffer does not match, it is not removed, and when you do the next scanf, you get it again and clear the screen again, and again and again.
0

Your program is not a good one, but nevertheless I will tell you what is happening.

In C/C++, when scanf cannot read an integer (%d) from input, it wouldn't read anything. That is, whatever prevented scanf from reading an int, will remain there. On the next scanf the same character is going to cause an error.

Let me demonstrate by an example. Imagine you are reading many integers from this input:

12 13 Shahbaz 15

Now if you call scanf with %d, you will read 12 and the input would be:

 13 Shahbaz 15

Next, you call scanf with %d and you will read 13. now the input would be:

 Shahbaz 15

Again, you call scanf with %d. Here, the input begins with an S (after the whitespace) which makes scanf return with a failure as it could not read an integer. The input is left untouched (save perhaps for the whitespace). That is, the input will be:

 Shahbaz 15

As you can see, reading the input with %d will give you the exact same error and you are stuck in an infinite loop.

To solve this, you have many choices. This very much depends on how you want to handle the situation, but two methods would be to either read a character (with %c) or a string (with %s) right after printing printf("Invalid\n").

The first method is good for handling input like this:

12 13 q14 15

where q is a mistake that needs to be ignored. The second method is good for handling input like this:

12 13 Shahbaz 15

where the invalid data are meaningful words, but you just want to ignore them.

And the way I would write it, if I wanted to use scanf would be:

int main()   // always write int main
{
    int nav;
    printf("Type an integer: ");
    while (scanf("%d", &nav) != 1)   // scanf returns number of successful %'s read
    {
        printf("Invalid number. Try again: ");
        scanf("%*s");                // read a %s but ignore it
    }
    // The rest of the program, using nav
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.