验证给定范围内的整数输入c

时间:2014-03-13 12:43:59

标签: c validation fgets

我正在尝试在范围和类型整数之间验证输入。目前我有以下代码。所需的范围是X为0-100,Y为0-50。

for(loop=0;loop<3;loop++){
    printf("\n\nEnter MAGENTA X coordinate from 0 to 100:\n");
    scanf("%d",&mg[loop].x);
    printf("\nEnter MAGENTA Y coordinate from %d to 50:\n");
    scanf("%d",&mg[loop].y);
}

我需要用户选择提前结束输入,可能是输入“end”或类似的东西。然后应该移动到黄色的下一个颜色。

是否有人知道如何使用scanf实现此目的?

------ ----- EDIT

我已实现以下内容,默认为"failure"。我将句柄增加到2并收到错误end is being use without being initialized

for(loop=0;loop<3;loop++){
    printf("\n\nEnter MAGENTA X coordinate from 0 to 100:\n");
    if(scanf("%d%c",&mg[loop].x) != 1 || end !='\n')
        printf("failure");
    else
    printf("\nEnter MAGENTA Y coordinate from 0 to 50:\n");
    scanf("%d",&mg[loop].y); /*Use the same validation here as above*/
}

3 个答案:

答案 0 :(得分:0)

你可以使用scanf,没关系。为什么不? scanf返回成功读取的项目数,因此0表示格式错误。之后,你想在要求另一个输入之前丢弃剩余的输入。

然后根据边界测试读取变量。

您可以为用户希望退出指定一个特殊值,也许某些字符串如“exit”,这会使scanf失败,然后检查它是否“退出”。当你想退出循环时,break命令会很方便。

答案 1 :(得分:0)

您可以使用scanf()但错误报告往往比较棘手。最小化您的代码:

for (loop = 0; loop < 3; loop++)
{
    int rc;
    printf("\n\nEnter YELLOW X coordinate from 0 to 100:\n");
    while ((rc = scanf("%d", &ylw[loop].x)) == 1 &&
           (ylw[loop].x < 0 || ylw[loop].y > 100)
        printf("Enter a value between 0 and 100\n");
    if (rc != 1)
    {
        fprintf(stderr, "Error reading x-value.\n");
        break;
    }
    printf("\nEnter YELLOW Y coordinate from 0 to 50:\n");
    while ((rc = scanf("%d", &ylw[loop].y)) == 1 &&
           (ylw[loop].x < 0 || ylw[loop].y > 50)
        printf("Enter a value between 0 and 50\n");
    if (rc != 1)
    {
        fprintf(stderr, "Error reading y-value.\n");
        break;
    }
}

但是,这种重复会激发一个功能 - 虽然它具有适度复杂的界面:

int prompt_for(const char *what, int min, int max, int err)
{
    int value;
    int rc;
    printf("\nEnter %s from %d to %d:", what, min, max);
    while ((rc = scanf("%d", &value)) == 1 && (value < min || value > max))
        printf("Enter a value between %d and %d\n", min, max);
    if (rc != 1)
    {
        fprintf(stderr, "Error reading %s.\n", what);
        return err;
    }
    return value;
}

样品使用:

for (loop = 0; loop < 3; loop++)
{
    ylw[loop].x = prompt_for("YELLOW X coordinate", 0, 100, -1);
    if (ylw[loop].x == -1)
        break;
    ylw[loop].y = prompt_for("YELLOW Y coordinate", 0, 50, -1);
    if (ylw[loop].y == -1)
        break;
}

如果您使用fgets()sscanf(),则可以使用:

int prompt_for(const char *what, int min, int max, int err)
{
    int value;
    int rc;
    char line[4096];
    printf("\nEnter %s from %d to %d:", what, min, max);
    while (fgets(line, sizeof(line), stdin) != 0 &&
           (rc = sscanf(line, "%d", &value)) == 1 &&
           (value < min || value > max))
        printf("Enter a value between %d and %d\n", min, max);
    if (rc != 1)
    {
        fprintf(stderr, "Error reading %s.\n", what);
        return err;
    }
    return value;
}

尽管如此,这并没有充分利用fgets();当您想要在一行上有多个数据项时,它会得分,因为这样您就可以报告输入的整行。

警告:此代码均未编译

答案 2 :(得分:0)

如果你想强制每个输入都在它自己的输入行上(在交替提示和从stdin读取时是可取的),我建议先将一行读入临时行缓冲区,然后用{{ 1}}。然后检查输入在最后一步是否有效。

因为这可能会使你的代码变得混乱,你可能会为此调整自己的功能:

sscanf

然后您可以这样读取您的坐标:

/*
 *      Read an integer from stdin. Repeat until a valid number between
 *      lo and hi has been given. Returns 0 when a number was read and
 *      -1 when the input has run out.
 */
int read_int(int *x, int lo, int hi)
{
    char buf[80];
    char c;

    for (;;) {
        if (fgets(buf, sizeof(buf), stdin) == NULL) return -1;

        if (sscanf(buf, "%d %c", x, &c) != 1 || *x < lo || *x > hi) {
            printf("Please enter a single value between %d and %d.\n",
                lo, hi);
        } else {
            break;
        }
    }

    return 0;
}

如果用户键入文件名字符(Ctrl-D un Unix,Windows上为Ctrl-Z),则可以缩短坐标数。如果您想使用某个关键字结束输入,请说&#34;结束&#34;,您可以通过读取字符串并首先检查来将其添加到您的函数中:

struct Coord ylw[3] = {{0, 0}};
int i;

for(i = 0; i < MAX; i++) {
    printf("\n\nEnter YELLOW X coordinate #%d from 0 to 100:\n", i);
    if (read_int(&ylw[i].x, 0, 100) < 0) break;

    printf("\nEnter YELLOW Y coordinate #%d from 0 to 50:\n", i);
    if (read_int(&ylw[i].y, 0, 50) < 0) break;
}

(从字符串中查找字符串似乎是多余的,但这样用户可以键入&#34; end&#34;在一些空格之后。您还可以使用不区分大小写的字符串比较函数。)