6
void GasPump::dispense()
{

        bool cont = true;
        char stop;

    do{
        cout << "Press any key, or enter to dispense.\n"
             << "Or press 0 to stop: \n";
        cin.get(stop);

        gasDispensed = gasDispensed + gasDispensedPerCycle;
        charges = costPerGallon*gasDispensed;
        displayGasNCharges();

        if(stop == 0)
            cont = false;

    } while(cont);

}

課題をやって、これはオブジェクトを使って書く私の最初のプログラムですので、我慢してください。このコードの出力を正しく取得できません。ループから抜け出す方法が必要ですが、使用しているものが機能していません。何か提案、ヒント、ヒントはありますか?

4

2 に答える 2

5

停止とゼロ文字を比較してみてください。

stop == '0'

また、これを行うことでコードを単純化できます。

void GasPump::dispense()
{
    char stop;

    do {
        cout << "Press any key, or enter to dispense.\n"
             << "Or press 0 to stop: \n";
        cin.get(stop);

        gasDispensed = gasDispensed + gasDispensedPerCycle;
        charges = costPerGallon*gasDispensed;
        displayGasNCharges();
    } while (stop != '0');
}
于 2010-02-27T04:11:16.290 に答える
3

このシナリオでは、ユーザーが「0」を打った後、もう一度ガスをポンプします。これが望ましくないと仮定すると、「off-by-one エラー」と呼ばれるものがあります。次のように関数を再配置することで、これを修正 (および一時変数を削除) できます。

void GasPump::dispense()
{
    while (true) {
        cout << "Press any key, or enter to dispense.\n"
             << "Or press 0 to stop: \n";

        if (cin.get() == '0')
            break;

        gasDispensed = gasDispensed + gasDispensedPerCycle;
        charges = costPerGallon*gasDispensed;
        displayGasNCharges();
    }
}

break ステートメントの使用を避けるには、次の構造を使用できます。

bool GasPump::shouldDispenseGas()
{
    cout << "Press any key, or enter to dispense.\n"
         << "Or press 0 to stop: \n";
    return (cin.get() != '0');
}

void GasPump::dispense()
{
    while (shouldDispenseGas()) {
        gasDispensed = gasDispensed + gasDispensedPerCycle;
        charges = costPerGallon*gasDispensed;
        displayGasNCharges();
    }
}

編集 (2011 年 9 月 27 日): @TonyK 言語が機能を提供するからといって、それを使用する必要があるわけではありません。このgotoステートメントは、この典型的な例です。

確かに、このような単純なループでは、関数とブレークの使用に違いはありません。どちらも明らかです。ただし、1 か月 (または数年) 後に追加の機能が追加され、ループから抜け出すための追加の条件が追加されると、非常にif大きなループ内で複雑なロジックを含む多重ネストされたステートメントを簡単に見つけることができ、苦労します。その始まりを見つけること、ましてや出口点を見つけること。この種のコードの肥大化に対抗する方法の 1 つは、適切な名前が付けられた、短くシンプルで焦点を絞った関数を作成することです。これを行うと、コード自体が文書化されます。比較

while (true)

while (shouldDispenseGas())

同様に、これを STLfor_eachアルゴリズムと比較します。確かに、std::for_each(v.begin(), v.end(), &foo);は より少し短いですfor (int i = 0; i < v.size(); ++i) { ...body of foo()... }。しかし、本当の利点は、意図が何であるかを簡単に確認できることです。では、for_each各要素に対して一度だけ何かを実行することがすぐにわかります。for ループでは、わかりません。ループカウンタiは、ループ内で変更される場合があります。Abreakも中に隠れているかもしれません。このbreakステートメントを回避して にロジックを埋め込むことshouldDispenseGasで、ループが継続して終了する条件をすぐに理解できます。

于 2010-02-27T05:17:08.890 に答える