简体   繁体   English

使用 scanf 进入无限循环

[英]Running into infinite loop with scanf

So I have a bit of code like this ( Just a note this is in C89 ):所以我有一些这样的代码(请注意这是在 C89 中):

void inputChoice(int* choicePtr)
{
    int choice;
    printf(BLUE "\nINPUT: " RESET);                     /* Print input using the ansi colour code for Blue. */
    scanf("%d", &choice);                               /* Parse the choice. */

    while ((choice < 1) && (choice > 5))                /* Loop until choice is one of the menu options. */
    {
        /* Request for a valid menu option, printing this using the ansi colour code for Red, then resetting back to the default colour. */
        printf(RED "\nMenu Selection must be between (1 and 5) inclusive. \nPlease Re-enter. \n" RESET);
        scanf("%d", &choice);                           /* Parse the choice. */
    }
    *choicePtr = choice;                                /* Set the choice pointer to the valid choice after validation. */
}

Which gets the choice.哪个得到选择。 It works fine for integers.它适用于整数。 But if someone enters anything else, for example a Character.但如果有人输入其他任何内容,例如字符。 It infinitely loops.它无限循环。 I want to somehow check for if a character is entered.我想以某种方式检查是否输入了字符。

One way I tried this was by adding this to check if a character was entered since the integer would be 0 if it didn't scan properly.我尝试这样做的一种方法是添加它以检查是否输入了字符,因为如果扫描不正确,integer 将为 0。

Like the below, but that doesn't work either:如下所示,但这也不起作用:

scanf("%d", &choice);

while (choice == 0)
{
    printf("Invalid Choice Re-enter.");
    scanf("%d", &choice);
}

The expression表达方式

while ((choice < 1) && (choice > 5))  

is never true since choice can't be at the same larger than 5 and smaller than 1 .永远不会正确,因为choice不能同时大于5和小于1

You'll need:你需要:

while (choice < 1 || choice > 5) 

scanf will try to parse if there is anything on the buffer but will not be able to, it will continue trying causing the infinite loop, because whatever is in the buffer will remain there until it's successfully parsed.如果缓冲区中有任何内容但无法解析, scanf将尝试解析,它将继续尝试导致无限循环,因为缓冲区中的任何内容都将保留在那里,直到成功解析。

Since scanf will return 0 if no arguments are parsed, you can use that information to clear the buffer removing what is causing the infinite loop:由于如果没有解析 arguments, scanf将返回0 ,因此您可以使用该信息来清除缓冲区,从而消除导致无限循环的原因:

int choice = 0;
int c; 
int scanned;
//...
if ((scanned = scanf("%d", &choice)) == EOF){ //check for EOF return
    puts("Unexpected error.");       
    //error treatment is upt to you, I would avoid the loop
    *choicePtr = scanned;
    return;
}
if (scanned == 0) {
    while ((c = fgetc(stdin)) != '\n' && c != EOF){}
}

in both scanf s.在两个scanf中。

Live demo现场演示

Taking remarks from comments into consideration, here is a modified version:考虑到评论中的评论,这里是一个修改版本:

/* reading an input choice between 1 and 5 or -1 on error */
void inputChoice(int *choicePtr) {
    int choice;

    printf(BLUE "\nINPUT: " RESET);       /* Print input using the ansi colour code for Blue. */

    for (;;) {
        int res = scanf("%d", &choice);   /* Parse the choice. */
        if (res == EOF) {
            printf(RED "unexpected end of file\n" RESET);
            choice = -1;
            break;
        }
        if (res == 0) {
            int c;
            while ((c = getchar()) != EOF && c != '\n')
                continue;
            printf(RED "invalid entry\n" "Please Re-enter.\n" RESET);
            continue;
        }
        if (choice >= 1 && choice <= 5) {
            break;
        }
        /* Loop until choice is one of the menu options. */
        /* Request for a valid menu option, printing this using the ansi 
           colour code for Red, then resetting back to the default colour. */
        printf(RED "\nMenu Selection must be between (1 and 5) inclusive.\n"
               "Please Re-enter.\n" RESET);
    }
    /* Set the choice pointer to the valid choice after validation. */
    *choicePtr = choice;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM