首页 > 解决方案 > 仅在 C 中接受数值

问题描述

我正在尝试读取一个仅数字的值,然后该值将执行特定的函数,具体取决于使用switch语句的值。
我知道我可以使用while(option < 0 || option >3 || option != 99),但是有解决方法吗?

个人工作:

do
{
  printf("Please choose an option :\n0. Create Database\n1.Add New Student \n2. Show All Students \n3.Delete Student\n99.Exit\n");
  scanf("%d", &option);
} while (!isdigit(option));

由于某种原因,这不起作用。

标签: cnumeric

解决方案


您的主要问题是,如果scanf由于某种原因(例如,如果您输入x)未能读取任何数字,它将返回零(成功扫描的项目数),而不是填充option,并且(这是杀手)离开输入指针在与开始之前相同的位置。

不幸的是,这意味着,当您返回获取另一个数字时,它只会尝试重新读取有问题的数据,并且可能最终进入无限循环而不允许更多输入。

scanf系列适用于格式化数据,没有什么比用户输入更无格式的了 :-)

最好的选择是使用坚如磐石的输入功能进入一条线,然后检查该线以查看它是否有效。可以在这里找到这样的功能。将其纳入您的需求将为您提供以下内容:

#include <stdio.h>
#include <string.h>

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2

static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}

#include <ctype.h>  // only needed for isdigit, not for above code.

int main(void) {
    int option;

    do {
        // Only allowed up to two characters (plus '\0').

        char buff[3];
        int result = getLine(
           "Menu\n"
           "   0. Create Database\n"
           "   1. Add New Student\n"
           "   2. Show All Students\n"
           "   3. Delete Student\n"
           "  99. Exit\n"
           "Please choose option: ",
           buff, sizeof(buff));

        // No point continuing on EOF, input stream is closed.

        if (result == NO_INPUT) {
            puts("\n*** End of input");
            return 1;
        }

        // All faults just restart operation: too long, too short,
        // non-digits.

        if (result == TOO_LONG) continue;
        if (! isdigit(buff[0])) continue;
        if (buff[1] != '\0' && ! isdigit(buff[1])) continue;

        // Now get the integer representation and continue unless valid.

        sscanf(buff, "%d", &option);
    } while (option != 99 && (option < 0 || option > 3));                                                                                                                                                        

    printf("You chose %d\n", option);
    return 0;
}

而且,是的,我知道我说过你应该检查返回值,scanf但在我发布的代码的情况下没有必要,因为你已经确定你正在扫描的字符串是有效的一或二数字。


推荐阅读