首页 > 解决方案 > 将 char 写入浮点形式时,如何防止程序进入无限循环?

问题描述

我做了一个 Newton-Raphson Method 程序。但我有一个问题。如您所见,“epsilon”和“x0”是浮点类型,当我尝试编写“a”或“b”之类的东西时,程序会发疯。我想阻止它。当发生这样的事情时,我想告诉用户“请输入一个数字”。

你能帮我解决这个问题吗?谢谢你。

代码如下:

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<locale.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include <iomanip>
#include<time.h>
#define f(x) pow(x,5)-pow(x,4)-pow(x,3)+2*pow(x,2)
#define g(x) 5*pow(x,4)-4*pow(x,3)-3*pow(x,2)+4*x
using namespace std;

int main()
{
    setlocale(LC_ALL,"turkish");

    cout << "Problem 4" << endl << "---------" << endl << "Verilen y=(x^2)/(x+1) ve y=(x^3)/(x^3+2) fonksiyonlarının varsa kesim noktalarını bulan C programı\n" << endl;

    float x0, x1, f0, f1, g0, epsilon;
    int tahmin = 1, sinir=1000;

    cout << setprecision(6)<< fixed;

    bastan:
    
    cout << "Epsilon değerini giriniz: "; //Pay attention here. My question is about here.
    epsilonHata:
    cin >> epsilon;
    cout << endl;
    hata:
    cout << "İlk tahmin değerini giriniz: "; //Just like above, my question is about here too.
    cin >> x0;
    cout << endl;

    bla bla...
}

标签: c++

解决方案


发生无限循环问题是因为cin基础ifstream期望 afloat在您的情况下。通过不提供浮点数,cin失败并发生奇怪的循环。更多信息在这里。

由于您无法控制用户并且您不希望程序在用户输入字符时中断,因此您可以将输入读取stringfloat. 这样,不会设置错误标志cin
然后,您应该将字符串转换为浮点数。atof适合这个目的。

#include <iostream>
#include <string>
#include <cstdlib>
...
std::string epsilon_str;
std::cin >> epsilon_str;
double epsilon = atof(epsilon_str.c_str());

从以下文档atof

如果 str 中的第一个非空白字符序列没有形成刚刚定义的有效浮点数,或者由于 str 为空或仅包含空白字符而不存在此类序列,则不执行转换并且函数返回 0.0 .

其他一般编程问题

  • 您包含很多标题。了解哪个功能或类需要什么是最佳实践。我假设您在需要时将它们包括在内,但如果您不使用setprecision,则没有理由使用#include <iomanip>.

  • 使用define意味着简单地复制粘贴。编译器不知道你在做什么。请参阅以下示例。

    #define     WRONG_MULTIPLY(a, b)    a * b
    #define CORRECTED_MULTIPLY(a, b) ((a) * (b))
    ...
    int wrong_result     =     WRONG_MULTIPLY(1 + 2, 3 + 4); // 11
    int corrected_result = CORRECTED_MULTIPLY(1 + 2, 3 + 4); // 21
    

    最佳实践是使用函数。这就是函数的目的。

    int multiply(int a, int b) {
        return a * b;
    }
    ...
    int result = multiply(1 + 2, 3 + 4);
    

    我为宏使用大写字母来吸引人们注意它们是宏。说真的,你不想处理编译器错误,原因是你不知道的宏。
    在这一点上,我建议通过一个教程,比如这个来理解基本概念。

  • 建议不要使用using namespace std;。如果存在std::multiply与您的函数具有相同签名(相同的输入-输出)的签名,则会在您不注意的情况下调用标准函数。有办法防止这种情况发生,但首先不知道发生了什么是问题所在。让编译器指导您,不要欺骗自己。

  • 代码的流程和标签的使用似乎很复杂。编写您将理解的代码,例如,两个月后。我建议将单独的功能分解为功能,例如readFloatcheckEpsilonValid

  • 在需要时声明变量。这样更容易遵循代码。此外,使用有意义的变量而不是两个字母的变量可以提高可读性,您甚至不需要稍后发表评论。

  • 最后,请注意这setprecision会影响cout整个程序。这是关于你是否关心的问题,但对于更大的项目,我建议使用printf("%.06f"), 或"%.06g",然后在必要时刷新。


推荐阅读