【问题标题】:How to loop scanf_s() until success?如何循环 scanf_s() 直到成功?
【发布时间】:2018-11-23 04:57:51
【问题描述】:
#include <stdio.h>

int main(){

    float x,y;

    printf("Enter 2 numbers: \n");
    scanf_s("%f %f", &x, &y);

    if (getchar() == '\n')
    {
    printf("Division: %f\n", x / y);
    printf("Product: %f\n", x * y);
    printf("Sum: %f\n", x + y);
    printf("Difference: %f\n", x - y);
    }
    else
    {
        printf("no Float-Value!");
    }

getchar();
return 0;
}

我们需要一个循环,所以如果我们输入错误的格式,程序应该再次要求输入两个数字

【问题讨论】:

  • 还有什么问题?尝试执行此操作时遇到了什么问题?你尝试了什么?
  • 什么是错误格式?
  • 我需要在代码中添加一个循环,如果您输入错误的格式,程序会再次要求我输入 2 个值
  • 要检查“格式错误”,您应该将输入作为字符串获取并解析它...使用scanf 会引起各种麻烦。寻找fgets
  • @EnzoFerber 是正确的。您的 scanf_s 不会使用该格式字符串解析浮点数以外的任何内容。如果你想验证输入,你应该扫描更广泛的输入,然后检查它们是否确实是浮点数。

标签: c loops while-loop format


【解决方案1】:

检查输入有效性的最佳方法是检查scanf_s 的返回值,它告诉您成功设置的变量数量。在你的情况下,如果它是 2,那么一切都很好;否则你需要重复。

换句话说

do {
    int c;
    while ((c = getchar()) != '\n' && c != EOF); // clear the input stream
    printf("Enter 2 numbers: \n");
} while (scanf_s("%f %f", &x, &y) != 2);

是一个合适的控制结构,而不是if (getchar() == '\n'),你应该放弃它。

【讨论】:

  • 如果输入任何不符合要求的内容,这不会变成无限循环吗?
  • @Yunnosch:确实会。如果这令人反感,请使用额外的计数器。
  • 如果我输入“no”,将是一个死循环,无法扫描那个“no”,计数器如何解决这个问题?
  • @Yunnosch:哎呀。我把惯用的流放得更清楚了。
  • 现在这是我希望在您的名字上方看到的那种答案。 ;-) 把它当作一种恭维。
【解决方案2】:

我不喜欢使用scanf 系列函数的一点是,当你输入错误时它会发疯并让你的程序崩溃。例如,如果您有scanf("%f", &amp;a),请尝试输入stack overflow。疯了!

所以,正如我在 cmets 中所说,我认为您应该构建自己的验证函数,并使用 fgets 将用户输入作为字符串获取。

这是一个简单的代码,可以帮助您入门。这是非常丑陋的代码,你应该重构它。

#include <stdio.h>  /* printf, fgets */
#include <ctype.h>  /* isdigit, isspace */
#include <string.h> /* strlen */

int is_valid_float(char *s, int len)
{
    int i;

    for(i = 0; i < len; i++) {
        /* floats may have a decimal point */
        if(s[i] == '.') continue;

        /* spaces should be ignored, since they separete the nubmers */
        if(isspace(s[i])) continue;

        /* is there's anything besides a number, we abort */
        if(!isdigit(s[i])) return 0;
    }

    /* if we got here, then the input contains two valid floats.
     * 
     * Does it? Test it!
     */
    return 1;
}


int main(void)
{
    float a, b;
    char buf[100];
    int len;

    do {
        fprintf(stderr, "Enter A and B: ");
        fgets(buf, sizeof buf, stdin);

        /* fgets will store a newline at the end of the string, we
         * just overwrite it with a null terminator
         *
         * Thanks to @chux for the strcspn() suggestion.
         */
        buf[strcspn(buf, "\n")] = 0;    
    } while(!is_valid_float(buf, len));

    /* now, after we know the string is valid and won't cause scanf to go
     * berserk, we can use it in our validated string.
     *
     * Here is where you should really take a moment and look at the
     * validation function and improve it. Not valid strings will cause
     * your program to go nuts.
     */
    sscanf(buf, "%f %f", &a, &b);

    /* Did it scan the numbers correctly? */
    printf("A: %f\n", a);
    printf("B: %f\n", b);

    return 0;
}

【讨论】:

  • len = strlen(buf) - 1; buf[len] = 0; 可以被黑客入侵,'\n' 可能不存在于buf 中。考虑使用buf[strcspn(buf, "\n")] = '\0'; 代替潜在的尾随\n
  • @chux 我喜欢strcspn 的建议并更改了答案以使用它。 (关于90,我什至不知道为什么......我更新了它)
猜你喜欢
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 2014-02-04
相关资源
最近更新 更多