2017-08-18 5 views
1

私はC++を学んでいます。C++の単純な機能のジレンマ

シンプルな「電卓」プログラム:文字入力をforbiden場合、値またはエラーを返す計算を、機能することを渡し、二つの数字と記号を読んでここに私の問題があります。私は私の機能の2つのバージョンを思い付いたと私は「正しいもの」であるかわかりません。ここで彼らは、次のとおりです。

まず一つは良い練習ではありません直接印刷は、(それはある?)ん。例えば、入力が「5」である場合、「6」、及び「 - 」には、-1を返します、それはによってミスとして処理される。

void calculate(int x, int y, char s) { 
    switch (s) { 
    case ('+'): { 
    std::cout << x + y << "\n"; 
    } 
    case ('-'): { 
    std::cout << x - y << "\n"; 
    } 
    case ('*'): { 
    std::cout << x * y << "\n"; 
    } 
    case ('/'): { 
    std::cout << x/y << "\n"; 
    } 
    default: { 
    std::cout << "Wrong sign input. Choose on of the following four:+-*/\n"; 
    } 
    } 
} 

もう一つは、まだ唯一の仕事をして欠陥を有しています呼び出し側。

int calculate(int x, int y, char s) { 
    switch (s) { 
    case ('+'): { 
    return x + y; 
    } 
    case ('-'): { 
    return x - y; 
    } 
    case ('*'): { 
    return x * y; 
    } 
    case ('/'): { 
    return x/y; 
    } 
    default: { 
    return -1; 
    } 
    } 
} 

このシナリオでは、あなたはどんなことをしますか?

+5

*発信者が誤って処理する*発信者を修正する。 IMHOの2番目の関数を使用する必要があります。計算と印刷は別々に行う必要があります。 – NathanOliver

+3

2番目がエラーの場合は例外をスローするのが最善です。 –

+0

-1結果と-1エラーをどのように伝えるか? – KOKO

答えて

0

出力と計算は別々の関数でなければなりません。ただし、有効な出力値でもある場合は、エラーを示すために特別なセンチネル値を使用しないでください。

実際の問題は入力確認であり、計算はでもと異なるはずです。私は、潜在的な操作のためのenumを作成し、その中を通過する。

enum class Operation { 
    ADD, 
    SUBTRACT, 
    MULTIPLY, 
    DIVIDE 
}; 

次にOperationcalculateテイクを持っています。あなたはまだどこかで入力を検証する必要がありますが、同じ場所にあるべきではありません。

enum sが彼らの宣言以外の値を持つことができますので、あなたはまだ、calculatedefaultケースが必要になりますが、あなたが他の場所で入力を検証しなければならないので、あなたはそれ簡単なassert作ることができます。

2

(あなたは私が避けたい特別な値、を利用する場合を除きます。)あなたは、両方の動作や状態コードの結果を返すために、戻り値を使用しますが、することはできませんどのようにステータスの戻り値を使用する方法についてその結果を出力引数にセットするか?

int calculate(int x, int y, char s, int & result); // returns: 0 - success; -1 - failure 
+0

このような出力パラメータは、しばしば使いにくいですが、これはうまくいく可能性があります。 –

+1

逆も可能です - 結果の戻り値、ステータスの出力パラメータを使用してください - ユースケースによってはより良いかもしれません – gcbenison

+0

@gcbenison私はそう言います。エラーコードは、黙って無視されるリスクを返します。必要な参照を見落とすのは難しいです。無視して捨てるのはあまり難しくありませんが... – Persixty

1

あなたには2つのオプションがあります。

  1. ポインタ/参照によって渡される変数に実際の結果を入れ、ステータス

の戻り値を使用し

  • 戻りstd::numeric_limits<int>::max()
  • を例外をスロー私は例外のために行くと思います。

    default: 
        throw std::invalid_argument(std::string("invalid operator: ") + s); 
    
  • +1

    4. 'assert'(KOKOが' catch 'の例外を知ることができない場合に例外を投げるのに似ています)、6. * accept *異なる型( 'enum class Operation')と、別の関数で入力検証を行います。私は6回するだろう。検証と計算は同じ関数であってはなりません。 –

    +0

    私は 'enum class Operation'が好きです。それははるかに良いインターフェースを作ります。 – crazypeter

    1

    まず、計算結果を計算結果とは別にすることをお勧めします。間違った入力に対処する方法の質問に来る

    ...ステータスと結果を返すことができるようにする

    もう一つの方法は、戻り値の型としてstd::pairを使用することであろう。

    std::pair<bool, int> calculate(int x, int y, char s) 
    { 
        ... 
    } 
    

    と成功事例のため{true, result}を返し、失敗した場合のため{false, 0}を返すことを確認してください。

    +0

    これはクールだ。 – KOKO

    +0

    もっと良い解決策は 'std :: optional'でしょうが、あなたのコンパイラがそれをまだサポートしていないかもしれません。 –

    0

    EDIT:

    エラーを処理するための正しい方法は、スローとキャッチです。ここにはバージョンがあります。

    #include <iostream> 
    #include <stdexcept> 
    using std::cout; 
    using std::cin; 
    using std::cerr; 
    using std::invalid_argument; 
    
    int calculate(int, int, char); 
    
    int main() 
    { 
        int num1, num2; 
        char symbol; 
        cin >> num1 >> num2 >> symbol; 
        try { 
         cout << calculate(num1,num2,symbol) << '\n'; 
        } catch (const invalid_argument& error) { 
         cout << error.what() << '\n'; 
         return 1; 
        } 
        return 0; 
    } 
    
    int calculate(int x, int y, char s) { 
    switch (s) { 
        case '+': 
         return x + y; 
    
        case '-': 
         return x - y; 
    
        case '*': 
         return x * y; 
    
        case '/': 
         return x/y; 
    
        default: 
         throw invalid_argument("Received non existing option!"); 
    } 
    } 
    

    また、ここにはスローのないバージョンがあります。

    はここにあなたのコードの作業バージョンです。

    #include <iostream> 
    using std::cout; 
    using std::cin; 
    using std::cerr; 
    
    int calculate(int, int, char); 
    
    int main() 
    { 
        int num1, num2; 
        char symbol; 
        cin >> num1 >> num2 >> symbol; 
        cout << calculate(num1,num2,symbol) << '\n'; 
        return 0; 
    } 
    
    int calculate(int x, int y, char s) { 
    switch (s) { 
        case '+': 
         return x + y; 
    
        case '-': 
         return x - y; 
    
        case '*': 
         return x * y; 
    
        case '/': 
         return x/y; 
    
        default: 
         cerr << "Unrecognised option!\n"; 
         return -1; 
    } 
    } 
    

    私も少し書式設定を変更しました。あなたは、コードに関連した質問があれば、それを探求すること自由に感じ、お願いします。

    質問への回答:は第2の方法を優先します。それは正しい方法です。

    +0

    問題は、入力が正しい場合でも関数が-1を返すことができるこの方法です。また、デフォルトを通過する場合は、-1を出力します。 – KOKO

    +0

    私は知っていますが、それがエラーであれば、認識できないオプションもあります! お試しください。 5 6 - 私に-1を与えました。 5 6)私に認識できないオプションが与えられました! -1それを行う正しい方法はスローですが、あなたのチュートリアルに戻ってきたと言いました。今のところ、エラーメッセージを指定することができます。 –

    +0

    私はあなたのポイントを見ます。 – KOKO

    関連する問題