【问题标题】:Parsing user input for two values解析两个值的用户输入
【发布时间】:2016-08-17 11:56:36
【问题描述】:

我已经搜索了几个小时,但似乎找不到我想要的答案。如果这最终成为重复,我深表歉意。

现在我的程序要求用户输入 2 个整数。示例

Prompt: 15 24

我去后提出了其他问题,所以人们提到了scanffgets。但是每一个都是一次输入一个数字,而我想要两个都来自一个输入。

我的另一个问题是错误检查。他们是否实际输入了整数或无效的内容。示例:

Prompt: Hello World
Prompt: foo 5
Prompt: 4 bar
Prompt: foo
Prompt: 

代码:

int get_input(int* x, int* y) {

    char* p, buf[LINE_MAX];
    int n1, n2;

    printf("Prompt: ");
    fgets(buf, sizeof(buf), stdin);
    n1 = strtol(buf, &p, 10);
    if (p == buf || *p != '\n') {
        return 0;
    }

    n2 = strtol(buf, &p, 10);
    if (p == buf || *p != '\n') {
        return 0;
    }

    *x = n1;
    *y = n2;

    return 1;
}

int main(int argc, char** argv) {
    int x, y;
    if (get_input(&x, &y)) {
        printf("Worked: %d %d\n", x, t);
    } else {
        printf("Invalid\n");
    }
    return 0;
}

缺少一些错误检查,但如果有第二个值,就真的坚持获取第二个值。还要检查是否有超过 2 个值。 我们将不胜感激。

让我走到这一步的参考资料:

SO Question

strtol doc

【问题讨论】:

  • 提示:n2 = strtol(p, &p, 10).
  • DV 甚至没有阅读 scanf 的手册页。
  • @Olaf 我确实尝试过scanf,但我只能让它适用于有效输入。提到的任何无效输入都会给我一个奇怪的输出,我很困惑。加上提到的 SO 问题说不要使用 scanf 所以我在 fgets @zwol 进行了更改,但在尝试有效的东西时无法让它工作。能详细点吗?
  • 你试过用strtok代替strtol吗?使用 strtok 您可以提取前两个条目,无论输入有多长。之后,您可以使用 atoi() 将它们转换为整数。您还可以检查第二个 strtok 之后的字符是否为换行符“\n”,如果是,则它是有效输入。否则无效。
  • 不要费心尝试使用scanf,它已按规定损坏。正如您所发现的,它的问题之一是无效输入实际上不可能可靠地处理。

标签: c validation input


【解决方案1】:

我最终想出的方法也适用于可变数量的值。

bool get_input(int count, int* ref_values) {
    char buffer[MAX_LINE_LENGTH];
    char* input = fgets(buffer, sizeof(buffer), stdin);
    char* end;
    int i = 0;

    if (feof(stdin)) {
        clearerr(stdin);
        return false;
    }

    for (long val = strtol(input, &end, 10); input != end && i < count; val = strtol(input, &end, 10), i++) {
        input = end;
        if (errno == ERANGE) {
            errno = 0;
            return false;
        }

        if (val <= INT_MIN || val >= INT_MAX) {
            return false;
        }
        ref_values[i] = val;
    }
    return i == count && strlen(input) == 1;
}

int main(int argc, char** argv) {
    while (true) {
        int values[2] = {};
        printf("Enter 2 numbers: ");
        if (get_input(2, values)) {
            printf("You entered %d %d %d\n", values[0], values[1]);
        } else {
            printf("Invalid\n");
        }
    }
    return 0;
}

【讨论】:

    【解决方案2】:

    一旦你在字符串中输入,你就可以正常使用sscanf,但最后需要一个技巧参数:

    int get_input(int* x, int* y) {
    
        char* p, buf[LINE_MAX], buf2[LINE_MAX];
        int n1, n2;
    
        printf("Prompt: ");
        fgets(buf, sizeof(buf), stdin);
        if  (sscanf(buf, "%d%d%s", &n1, &n2, buf2) == 2) {
            /* Success */
            *x = n1;
            *y = n2;
            return 1;
        }
        /* Failure */
        return 0;
    }
    

    注意:

    第三个参数 (buf2) 用于防止第二个整数之后的无效输入。这个技巧有效,因为您首先将输入读入字符串。如果您尝试直接输入scanf("%d%d%s", ...),则会提示用户进一步输入,直到他提供一些非空格以放入buf2

    【讨论】:

      猜你喜欢
      • 2016-02-25
      • 2014-03-14
      • 1970-01-01
      • 2011-12-16
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多