具有文件结尾功能的循环重复两次输出文件中的最后一个数字

时间:2017-06-29 06:11:46

标签: c++

嗨,我知道这可能听起来像是一个重复的问题,但我已经花了很多天才解决这个问题而无法找到解决方案。在我的代码中我有一个while(true)循环,在文件的末尾我有一个带有文件结束函数和break的if语句,但在输出中它重复了最后一个数字两次。

#include <fstream>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main ()
{

int line=0;

ifstream    infile; //INPUT input file stream
ofstream    outfile; //OUTPUT output file stream

infile.open("inputPartb.txt");
if (! infile)
{
    cout <<"Problem opening input file inputPartb.txt"<<endl;
    return 1; //not successful
}

outfile.open("resultsPartb.txt");
    if (! outfile)
    {
        cout <<"Problem opening output file resultsPartb.txt"<<endl;
        return 1; //not successful
    }


while (true)
{
    double num1;
    double num2;

    int intnum1;
    int intnum2;

    char mathOperator;

    double addition;
    double subtraction;
    double multiplication;
    int division; //division is using remainders so float isnt needed
    double power;

    double remainder;

    line = line +1;


    //reading numbers from the file
    infile >> num1 >> num2 >> mathOperator;

    intnum1 = num1;
    intnum2 = num2;


    //if statement for addition
    if (mathOperator == '+')
    {
        //one for both num1 and num2 being integers
        if ((num1-intnum1==0)&&(num2-intnum2==0))
        {
            addition = num1+num2;
            outfile << fixed<< setprecision(0)<< num1 << " + " << num2 << " = " <<addition <<endl;
        }
        //one for either num1 or num2 being a float
        else
        {
            addition = num1+num2;
            outfile << fixed << setprecision(4)<< num1 << " + " << num2 << " = " <<addition <<endl;
        }

    }


    //if statement for subtraction
    else if (mathOperator == '-')
    {
        //one for both num1 and num2 being integers
        if ((num1-intnum1==0)&&(num2-intnum2==0))
        {
            subtraction = num1-num2;
            outfile << fixed<< setprecision(0)<< num1 << " - " << num2 << " = " <<subtraction <<endl;
        }
        //one for either num1 or num2 being a float
        else
        {
            subtraction = num1-num2;
            outfile << fixed<< setprecision(4)<< num1 << " - " << num2 << " = " << subtraction <<endl;
        }

    }
    //if statement for multiplication
    else if (mathOperator == '*')
    {
        //one for both num1 and num2 being integers
        if ((num1-intnum1==0)&&(num2-intnum2==0))
        {
            multiplication = num1*num2;
            outfile << fixed<< setprecision(0)<< num1 << " * " << num2 << " = " <<multiplication <<endl;
        }
        //one for either num1 or num2 being a float
        else
        {
            multiplication = num1*num2;
            outfile << fixed<< setprecision(4)<< num1 << " * " << num2 << " = " << multiplication <<endl;
        }

        continue;
    }
    //if statement for division
    //one for both num1 and num2 being integers
    else if (mathOperator == '/')
    {
        if ((num1==intnum1)&&(num2==intnum2))
        {
            if (num2 == 0)
            {
                outfile << num1 << " / " << num2 << " = ERROR" <<endl;
                cout << "ERROR encountered on line "<<line<<endl;

            }
            else if ((num2==0)&&(num1==0))
            {
                division = static_cast<int>(num1)/static_cast<int>(num2);
                remainder = (static_cast<int>(num1) % static_cast<int>(num2));
                outfile <<setprecision(0)<<fixed<< num1 << " / " << num2 << " = " << division<<"R"<<remainder<<endl;
            }
            else
            {

                division = static_cast<int>(num1)/static_cast<int>(num2);
                remainder = (static_cast<int>(num1) % static_cast<int>(num2));
                outfile <<setprecision(0)<<fixed<< num1 << " / " << num2 << " = " << division<<"R"<<remainder<<endl;
            }
        }
        //one for either num1 or num2 being a float
        else
        {
            if (num2 == 0)
            {
                outfile << num1 << " / " << num2 << " = ERROR" <<endl;
                cout << "ERROR encountered on line "<<line<<endl;

            }
            else if ((num2==0)&&(num1==0))
            {
                division = static_cast<int>(num1)/static_cast<int>(num2);
                remainder = (static_cast<int>(num1) % static_cast<int>(num2));
                outfile <<setprecision(4)<<fixed<< num1 << " / " << num2 << " = " << division<<"R"<<remainder<<endl;
            }
            else
            {

                division = static_cast<int>(num1)/static_cast<int>(num2);
                remainder = (static_cast<int>(num1) % static_cast<int>(num2));
                outfile <<setprecision(4)<<fixed<< num1 << " / " << num2 << " = " << division<<"R"<<remainder<<endl;
            }
        }

    }
    //if statement for power
    else if (mathOperator == '^')
    {
        if ((num1-intnum1==0)&&(num2-intnum2==0))
        {
            if ((num1 == 0)&& (num2 == 0))
            {
                outfile << num1 << " ^ " << num2 << " = " << "ERROR" <<endl;
                cout << "ERROR encountered on line "<<line<<endl;
            }
            else
            {
                power = pow(num1 , num2);
                outfile <<setprecision(0)<<fixed<< num1 << " ^ " << num2 << " = " << power <<endl;
            }
        }
        else
        {
            if ((num1 == 0)&& (num2 == 0))
            {
                outfile << num1 << " ^ " << num2 << " = " << "ERROR" <<endl;
                cout << "ERROR encountered on line "<<line<<endl;
            }
            else
            {
                power = pow(num1 , num2);
                outfile <<setprecision(4)<<fixed<< num1 << " ^ " << num2 << " = " << power <<endl;
            }
        }

    }
    //else statement for something other than the listed choices
    else
    {
        if ((num1-intnum1==0)&&(num2-intnum2==0))
        {
            outfile <<setprecision(0)<<fixed<<num1 << " " << mathOperator << " "<< num2 << " = ILLEGAL"<<endl;
            cout <<"ILLEGAL operator encountered on line "<<line<<endl;
        }
        else
        {
            outfile <<setprecision(4)<<fixed<< num1 << " " << mathOperator << " "<< num2 << " = ILLEGAL"<<endl;
            cout <<"ILLEGAL operator encountered on line "<<line<<endl;
        }
    }



if( infile.eof() ) break;

}
outfile.close();
infile.close();


return 0;

}

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

eof-check是有问题的,原因有两个:

  1. 如果任何读取操作失败,则流的失败位将被设置,并且任何后续读取也将失败。结果,流不再前进,永远不会达到eof,所以你陷入无限循环,重复打印出最后一次成功的操作,如果有的话,否则是未定义的行为,然后你评估至少一个未初始化的值(运算符&gt;&gt;在失败时不会触及值!)。
  2. 您在运算符中读取了一个字符,因此operator>>将只使用这一个字符。但是,您的文件可能会被尚未使用的换行符终止,因此不会设置eof位。然而,下一次读取将失败(将设置失败和eof位,因此您的循环将退出),但是当您执行此操作时评估您的值之后检查,您将重复上一次成功的操作再次,类似于1中所描述的。但是,这次你的循环 退出是因为设置了eof-bit ...
  3. 所以请检查一下:

    while (true)
    {
        infile >> num1 >> num2 >> mathOperator;
        if(!infile) // possible as ifstream offers a bool cast operator...
            break;
    
        // evaluate values now
    }
    

    可以使用eof(),如果您想要更细粒度的处理,但也要检查fail()

    while (true)
    {
        infile >> num1 >> num2 >> mathOperator;
        if(infile.eof()) 
            break;
        if(infile.fail())
        {
            // report error
            break;
        }
    }
    

    一些旁注:

    将浮点值与==进行比较检查绝对相等性。但由于可能发生的舍入(我们的位数有限,因此精度也有限),这可能会严重失败。请查看here,特别是按照提供的链接。

    此外,你有批次的重复代码,你应该真的避免。

    你可以做的第一件事:

    infile >> num1 >> num2 >> mathOperator;
    if(!infile)
        break;
    int precision = num1 - intnum1 == 0 && num2 - intnum2 == 0 ? 0 : 4;
    

    现在您可以在输出时使用精度:

    outfile << fixed << setprecision(precision);
    

    您可以立即完全放弃if / else的大部分内容。即使你没有,你应该更喜欢这个:

    addition = num1 + num2; // common code, keep outside!
    if (/*...*/)
    {
        outfile << fixed << setprecision(0);
    }
    else
    {
        outfile << fixed << setprecision(4);
    }
    

    对于加法,减法和乘法,您可以提供常见的处理:

    double result;
    if(op == `+`)
         result = num1 + num2;
    else if(op == `-`)
         result = num1 - num2;
    else if(op == `*`)
        result = num1 * num2;
    else
        goto OTHERS;
    
    outfile << fixed << setprecision(precision) << num1 << op << num2 << '=' << result << endl;
        continue; 
    
    OTHERS:
        // do the rest...
    

    好的,在任何人抱怨之前:你可能已经读过关于goto是邪恶的。嗯,不,那不是真的。它本身并不邪恶,但你可以用邪恶的东西 - 比如斧头,你可以用它来砍伐木头,但你也可以用它来杀人......比较下面的内容(留下一些线条) ,所以没有有效的C ++!):

    if(op == `+`)
    else if(op == `-`)
    else if(op == `*`)
    // else
    // ^ we leave it away entirely!
    
    if(op == `+` || op == `-` || op == `*`) // we repeate the checks!
    {
        outfile << fixed << setprecision(precision) /* ... */;
    }
    else
    {
        // the LARGE block here has an additional level of indentation
        // alternatively, we could have used continue in the if...
    }
    

    或者这个:

    if(op == `+`)
    else if(op == `-`)
    else if(op == `*`)
    else
    {
         // very LARGE block of code
    
         continue; // this one, you miss easily!
    }
    
    // and the common code to the initial if's is located FAR away from the them...
    

    老实说,goto没有让代码更清晰吗?