代码之家  ›  专栏  ›  技术社区  ›  roshoka

使用e时没有空格,程序会出现奇怪的崩溃

c++
  •  0
  • roshoka  · 技术社区  · 8 年前

    我有一个很奇怪的问题。程序应该将输入的值转换为米,找出最大值和最小值,求和,最后打印所有信息。它似乎在任何情况下都有效,除非我添加一个以e为单位的值,没有空格。例如,如果我按5“enter”e,它会工作,但如果我输入5e,它会完全崩溃。它不会对其他“错误”单元执行此操作。e有什么特别的地方吗?(本程序是为Stroustrup编程手册中的第4章演练编写的)。

            #include<algorithm>
            #include<cmath>
            #include<iostream>
            #include<string>
            #include<vector>
            using namespace std;
            inline void keep_window_open() {char ch; cin >> ch;}
    
    
            double cm_m(double x) //cm to m
            {
                return x/100;   
            }
            double in_m(double x) //in to m
            {
                return (x*2.54)/100.0;
            }
            double ft_m(double x) //ft to m
            {
                return (((x*12))*2.54)/100;
            }
    
            int main()
            {
                int z=0;
                double init=0;
                int w=1;
                string unit;
                double sum=0;
                cout << "Enter an value and a unit (cm,m,in,ft) (To end the program, enter a value with 'd' as the unit. Avoid entering a unit of 'e' without a space.):\n";
    
                double val1=0;
                double val2=0;
                while(w==1)
                {
                    cin >> init >> unit;
                    if(unit!="m" && unit!="cm" && unit!="ft" && unit!="in" && unit!="d" ) //rejects unwanted units
                    {
                        while(unit!="m" && unit!="cm" && unit!="ft" && unit!="in" && unit!="d")
                        {
                            cout << "Incorrect unit. Please enter a correct unit (m,cm,ft,in):\n";
                            cin >> unit;
                        }
                    }
                    if(unit=="m")
                    {
                        cout << "\n" << init << "m\n";
                    }
                    if(unit=="cm")
                    {
                        init=cm_m(init);
                        cout << "\n" << init << "m\n";
                    }
                    if(unit=="ft")
                    {
                    init=ft_m(init);
                    cout << "\n" << init << "m\n";
                    }
                    if(unit=="in")
                    {
                    init=in_m(init);
                    cout << "\n" << init << "m\n";
                    }
                    if(unit=="d") //d for "done"
                    {
                        cout << "\nThe smallest number was: " << val2
                            << "\nThe largest number was: " << val1
                            << "\nThe sum of all numbers entered was: " << sum;
                            keep_window_open();
                            return 0;       
                    }
    
                    sum=init+sum;
    
                    while(z<1) //This is set up so this 'while' loop is only used once to give initial values to val1 and val2
                    {
                        cout << "\nSmallest so far." << '\t' << "Largest so far.\n";
                        val1=init;
                        val2=init;
                        ++z;
                    }   
                    if(init > val1)
                    {
                        cout << "Largest so far.\n";
                        val1=init;
                    }
                    else if (init < val2)
                        {
                            cout << "Smallest so far.\n";
                            val2=init;
                        }
                }
            }
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   Lightness Races in Orbit    8 年前

    您正在从一个流执行所谓的“格式化提取”到 double ,然后转换为 char 。当你给它的时候 5 然后 d ,这些是有效的输入 双重的 烧焦 分别地的其他有效输入 双重的 部分将是 5.000 5.

    然而 5e 是中有效数字的开头 scientific notation ,因此 整体上 对于 双重的 然后流状态设置为“坏”,因为没有给定指数(例如。 5e42 )。我们甚至都没到 烧焦 部分

    因为流状态现在是“坏的”,所以所有后续的I/O操作也会失败,这可能是“它完全崩溃”时所观察到的情况。

    Input          Extraction to double       Then extraction to char     Stream state
    -------------------------------------------------------------------------------------
    5a             5                          a                           OK
    5.000a         5.000                      a                           OK
    5.a            5.                         a                           OK
    5e             5e                         (n/a)                       BAD
    5.e            5.e                        (n/a)                       BAD
    5.000e         5.000e                     (n/a)                       BAD
    5e42           5e42                       (n/a)                       OK*
    5e42a          5e42                       a                           OK
    

    (*但将被阻止,等待您输入要放入的内容 烧焦 )

    所以,是的, e 是特别的。

    始终在执行输入/输出后检查流状态。

    当流出错时,您可能希望清除错误状态,然后提示用户从头开始重试。