Scanf保持循环

时间:2011-11-07 03:25:36

标签: c

我有这个代码可以找到房间的油漆质量。

void get_room_size(char room_id, int * length, int * width) {
    while (*length <= 0 && *width <= 0) {
        printf("Enter length and width of room %c in feet: ", room_id);
        if (scanf("%d,%d", length, width)) {
            if (*length <= 0) {
                printf("###Error! Length must be a positive value!\n");
            }
            if (*width <= 0) {
                printf("###Error! Width must be a positive value!\n");
            }
            printf("\n");
        } else {
            printf("bad data");
            *length = 0;
            *width = 0;
        }
    }
}

基本上,如果我输入

  

A,1

它会疯狂并继续循环。问题是什么?

4 个答案:

答案 0 :(得分:5)

它变得“疯狂”的原因如下。当scanf 失败a作为数字读取时(因为它显然不是数字),它将不会推进文件指针。

这就是为什么你一般不应该使用scanf操作的原因之一,失败会使文件指针处于不确定的位置(例如,如果你只扫描12个项目中的3个)。

  

另一个原因是scanf表示“扫描格式化”,您将很难找到比用户输入更多的未格式化

无论如何,回到失败。由于文件指针未提前,下次您返回fscanf时,它会尝试再次读取a (并且一次又一次)。< / p>

如果你想要一个像样的功能来处理用户输入,那么请看这里:

#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;
}

这将从用户输入一行,具有溢出保护(与getsscanf不同,无界"%s")。

如果输入太长,它也会刷新到行尾,这将阻止该行的其余部分影响下一个输入操作。

然后,您可以sscanf缓冲区到您的心脏内容,而无需担心文件指针。

以下测试程序显示了如何使用它:

int main (void) {
    int rc;
    char buff[10];

    rc = getLine ("Enter string> ", buff, sizeof(buff));
    if (rc == NO_INPUT) {
        // Extra NL since my system doesn't output that on EOF.
        printf ("\nNo input\n");
        return 1;
    }

    if (rc == TOO_LONG) {
        printf ("Input too long [%s]\n", buff);
        return 1;
    }

    printf ("OK [%s]\n", buff);

    return 0;
}

另外,您可能需要重新检查有效大小的房间的逻辑。你现在拥有的东西允许在-42英尺的范围内输入一个房间: - )

依赖于输入时设置为特定值的输出值通常也不是好的形式。如果长度和宽度(例如)在输入时为3和4,则此功能将立即退出,而不会要求用户输入。

使用||代替&&可以解决第一个问题。第二种方法是在函数开始时将变量初始化为0,以便输入循环。


为了完整起见,如果您将上面的原始代码段(include语句和getLine()函数)与以下略微修改的get_room_size()函数合并:

static void get_room_size(char room_id, int * length, int * width) {
    char buff[100];
    *length = *width = 0;
    while ((*length <= 0) || (*width <= 0)) {
        printf("Enter length and width of room %c in feet: ", room_id);
        int rc = getLine (NULL, buff, sizeof (buff));

        if (rc == NO_INPUT) {
            printf ("\nEnd of file encountered.\n");
            return;
        }

        if (rc == TOO_LONG) {
            printf ("\nInput too long, please retry.\n");
            continue;
        }

        if (sscanf(buff, "%d,%d", length, width) != 2) {
            *length = *width = 0;
            printf ("\nInput not in desired form (<number>,<number>), "
                "please retry.\n");
            continue;
        }

        if ((*length <=0) || (*width <= 0)) {
            *length = *width = 0;
            printf ("\nBoth length and width must be greater than zero, "
                "please retry.\n");
        }
    }
}

以及非常简单的测试main(),您将看到一个完整的程序,展示如何操作。

int main (void) {
    int len, wid;
    get_room_size ('x', &len, &wid);
    printf ("Length is %d, width is %d.\n", len, wid);
    return 0;
}

答案 1 :(得分:0)

你的scanf接受两个整数。 A是一个角色,想你想要 scanf(“%c”,* room_id); scanf(“%d”,长度);

我建议你单独做它们

答案 2 :(得分:0)

试试这个:

...
       if (scanf("%d,%d", length, width) == 2) {
            if (*length <= 0) {
                printf("###Error! Length must be a positive value!\n");
            }
            if (*width <= 0) {
                printf("###Error! Width must be a positive value!\n");
            }
            printf("\n");
        } else {
            printf("bad data");
            *length = -1;
            *width = -1;
        }

答案 3 :(得分:-1)

你不放&amp;在scanf()语句中如何阅读

if (scanf("%d,%d", &length, &width))