关于C ++中的文件输入/输出和异常

时间:2013-04-11 13:54:20

标签: c++ file exception file-io exception-handling

我正在阅读Jesse Liberty的SAMS在10分钟内自学C ++并测试书中的示例。我发现代码中有一些关于文件i / o的错误,但我不知道它们在哪里。这本书没有提到任何关于它们的内容。我认为问题是由fstreamcatch(...)引起的,但我不知道如何修复它。所以我想向有经验的C ++用户寻求帮助。

问题:

我不知道为什么程序在输入文件为空时始终会调用ErrorHandling::handleNotANumberError();

此外,当输入文件不存在时,程序有更多错误 。捕获异常并读取basic_ios::clear。为什么会有错误?

当我删除有关例外的代码时,如果该文件不存在,它可以正常工作。

当我从空文件输入时,会出现“无效运营商”消息。

我认为无效的运算符是 eof字符。是吗?

我在谷歌搜索过但仍然无法弄清楚发生了什么。我知道下面的代码有点长,但我真的想知道会发生什么。

main.cpp中的主要内容:

ifstream tapeInputStream; //global variable for callback

char getOperator()
{
    char operatorInput;

    if
    (
        tapeInputStream.is_open() &&
        ( !tapeInputStream.eof() )
    )
    {
        tapeInputStream >> operatorInput;
    }
    else
    {
        cin >> operatorInput;
    }

    return operatorInput;
}

float getOperand()
{
    float operandInput = 1;

    if
    (
        tapeInputStream.is_open() &&
        ( !tapeInputStream.eof() )
    )
    {
        tapeInputStream >> operandInput;
    }
    else
    {
        cin >> operandInput;
    }

    return operandInput;
}

void showResult( float theResult )
{
    cout << endl << "Result: " << theResult << endl;
}

int main( int argc, char* argv[] )
{
    if ( argc > 1 ) //a filename is present
    {
        try
        {
            tapeInputStream.exceptions( tapeInputStream.failbit ); //cin or ofstream?
            tapeInputStream.open( argv[1], ios_base::in );
        }
        catch ( ios_base::failure &ioError )
        {
            ErrorHandling::handleInputStreamError( tapeInputStream, ioError );
            //the stream will be unopened but the failbit will not be set
        }
    }

    Calculator::aCalculatorExternalInterface CalculatorExternalInterface;

    CalculatorExternalInterface.getAnOperator = getOperator;

    CalculatorExternalInterface.getAnOperand = getOperand;

    CalculatorExternalInterface.showResult = showResult;

    int result = Calculator::calculateFromInput( CalculatorExternalInterface );

    tapeInputStream.close(); //close the file to make output stream in tape() possible

    Calculator::tape( '.', 0, argv[1] ); //stream and delete the tape

    return result;

}

ExternalInterfaceModule.cpp中名称空间计算器的一部分:

bool nextCalculation
(
    const aCalculatorExternalInterface &theCalculatorExternalInterface
)
{
    char operatorInput = theCalculatorExternalInterface.getAnOperator();

    switch ( operatorInput )
    {
        case '.': //stop

            return true; //done will become true

        case '?': //show the tape

            tape( operatorInput );
            return false;

        case '=': case '@': //no operand sent to accumulator
        {
            anOperator operatorValue =
                ( operatorInput == '=' ? query : reset );

            float result = accumulator( operatorValue );

            if ( operatorValue == query )
            {
                theCalculatorExternalInterface.showResult( result );
            }

            return false;
        } //use curly brackets to define the scope
        case '+': case '-': case '*': case '/': //calculation
        {
            float number = theCalculatorExternalInterface.getAnOperand();

            anOperator operatorValue =
                operatorInput == '+' ? add :
                operatorInput == '-' ? subtract :
                operatorInput == '*' ? multiply :
                                       divide;

            accumulator( operatorValue, number );
            tape( operatorInput, number );

            return false;
        }
        case '!': //self-test

            selfTest();
            return false;

        default: //anythings else is an error

            throw runtime_error( "Error: Invalid operator.");

    }
}

int calculateFromInput
(
    aCalculatorExternalInterface &theCalculatorExternalInterface
)
{
    ErrorHandling::initialise();

    bool done = false;

    do
    {
        try
        {
            done = nextCalculation( theCalculatorExternalInterface );
        }
        catch ( runtime_error runtimeError )
        {
            ErrorHandling::handleRuntimeError( runtimeError );
        }
        catch (...)
        {
            ErrorHandling::handleNotANumberError();
        }
    }
    while ( !done ); //continue when undone

    return 0;
}

2 个答案:

答案 0 :(得分:1)

我不知道抛出的异常是什么,所以我只添加一些if语句以防止由于空文件或不存在的文件而导致的任何错误。在问题出现问题之前处理问题可能会更好。(我对异常真的不太了解。)

以下是我在main.cpp中的新代码

if ( argc > 1 ) //a filename is present
{
    try
    {

        tapeInputStream.exceptions( tapeInputStream.failbit );

        if ( existFile( argv[1] ) ) //no need to read file if it does not exist
        {
            tapeInputStream.open( argv[1], ios_base::in );

            if ( emptyFile() ) //no need to read file if it is empty
            {
                tapeInputStream.close();
            }
        }
    }
    catch ( ios_base::failure &ioError )
    {
        ErrorHandling::handleInputStreamError( tapeInputStream, ioError );
    }
}

答案 1 :(得分:0)

在行catch ( ios_base::failure &ioError )中,您只是处理一种类型的错误。尝试catch(...)查看所有错误。请提一下运行代码后的其他错误是什么。

另外请确保您以正确的方式提供论据。 Executable<space>file_name_as_argument.