c ++函数返回nan而不是double

时间:2017-01-24 10:25:53

标签: c++ scanf nan cin

已解决“在输入正确值后循环后错过了返回”

我使用scanf_s从控制台获取输入。我写了一个检查输入的函数,如果它错了,它再次请求输入。

如果我第一次输入正确的值,一切都很好。如果我必须在funktion中第二次输入值,一切都很好,但是如果返回这个值,则功能返回NaN。为什么只有当我使用scanf_s两次时,双值才会丢失?

如果我调用输入并输入正确的值,则返回double。如果我输入的值小于或等于0,我必须再次输入值,但这次返回NaN。调试时我可以看到eingabe仍然是双倍的。

double input() {
    int n = -1;
    double eingabe = 0.0;

    scanf_s("%lf", &eingabe);

    clearBuffer();
    if (eingabe <= 0.0)
    {
        do
        {
            printf("Invald input");
            printf("Try again: ");

            n = scanf_s("%lf", eingabe);
            clearBuffer();
        } while (eingabe <= 0.0);
    }
    else
    {
        return eingabe;
    }
}

void clearBuffer() {
    //alles aus dem Buffer lesen bis man bei EOF (END OF FILE) ankommt
    int c;
        while ((c = getchar()) != EOF) {
            if (c == '\n')
                break;
        }
}

2 个答案:

答案 0 :(得分:1)

您不会在if (eingabe <= 0.0)内返回值。

您必须重新编写代码,因此将始终返回eingabe。

像这样:

if (eingabe <= 0.0)
{
    do
    {
        printf("Invald input");
        printf("Try again: ");

        n = scanf_s("%lf", &eingabe);
        clearBuffer();
    } while (eingabe <= 0.0);
}
return eingabe;

或者像这样:

if (eingabe <= 0.0)
{
    do
    {
        printf("Invald input");
        printf("Try again: ");

        n = scanf_s("%lf", &eingabe);
        clearBuffer();
    } while (eingabe <= 0.0);
    return eingabe;
}
else
{
    return eingabe;
}

在我看来,第一种情况更好。

修改

在这里,我使用您的代码进行了一些重构。不是每个人都会喜欢它,因为while(true)内容和continue以及return不在函数的末尾。但至少它是用C ++编写的,从我看来它非常自然而且阅读清楚。

#include <iostream>
#include <limits>

double input() {
    double eingabe;

    while (true) {
        std::cout << "Enter a positive real number: ";
        std::cin >> eingabe;

        if (std::cin.fail()) {
            std::cout << "Number expected." << std::endl;
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            continue;
        }

        if (eingabe <= 0) {
            std::cout << "Positive number expected." << std::endl;
            continue;
        }

        return eingabe;
    }
}

答案 1 :(得分:0)

我认为您的解决方案中有一些问题需要讨论。

首先,并非所有控制路径都返回一个值,这可能会导致函数input的不良结果;你的编译器应该警告过你。

其次,您的错误条件基于用户输入的双值,即负数或0被视为错误。如果你想输入负数或0,那么这种方法必须重新设计。您应该使用scanf的返回值,它可以指示是否已成功读取指定的格式。

第三,你使用scanf_s,即&#34; secure&#34;版本scanfscanf_s可以限制写入缓冲区的字符;这有两个原因没有意义:(a)您没有提供缓冲区限制作为附加参数,(b)扫描%lf无论如何都受数据类型double的限制。例如,scanf_s - 参考msdn

  

与scanf和wscanf不同,scanf_s和wscanf_s需要缓冲区大小   要为c,C,s,S或string类型的所有输入参数指定   包含在[]中的控件集。字符的缓冲区大小在指向缓冲区或变量

的指针后立即作为附加参数传递

第四,构造可能有点复杂,例如,double eingabe = 0.0后跟if (eingabe <= 0.0)的语句没有多大意义。

所以,让我提出一个更短的&#34;函数input的解决方案:

double input() {

    double eingabe = 0.0;
    int validInput = 0;
    do {
        if (scanf("%lf", &eingabe) == 1 && eingabe > 0)
            validInput = 1;
        else {
          printf("Invald input\n"
                "Try again:");
          scanf("%*[^\n]\n");
        }
    }
    while (!validInput);
    return eingabe;
}

请注意,语句scanf("%*[^\n]\n")会消耗任何字符,直到下一个\n包括\n,而不将其写入任何缓冲区(格式为*表示)。