6

有理数クラスは、分母numと分母の2つの整数で構成されてdenいます。

次の演算子は、ストリームから有理数を読み取ることになっています。

istream& operator >> (istream& Is, rational& r) {
  char c; //Test char.
   double n; //Could be either the numerator of the fraction or the antiperiod of the repeating decimal number.
    Is >> n;
    int i = 0;
    for (; n*10-pow(10, i+1) < 1 && int(n) != 0; i++) {
        n *= 10;
    }
    for (; int(n*10) % 10; i++) {
        n *= 10;
    }
    n /= pow(10, i);
    if (i == 0) {
        r.num = n;
        Is >> ws;
        c = Is.peek();
        if (c == '/') {
            c = Is.get();
            Is >> r.den;
        } else {
            r.den = 1;
        }
        r.normalize(); //This function normalizes the fraction.
    } else {
        Is >> ws;
        c = Is.peek();
        if (c == 'p' || c == 'P') {
            int p; //Period of the repeating decimal number.
            c = Is.get();
            Is >> p;
            vector<int> a = genFrac(n, p); //This function returns the fraction which express the decimal repeating number. It returns a "vector<int>" with the nominator at index 1 e denominator at index 0.
            r.num = a[1];
            r.den = a[0];
        } else {
            i = 0;
            for (; n*10-pow(10, i+1) < 1 && int(n) != 0; i++) {
                n *= 10;
            }
            for (; int(n*10) % 10 != 0; i++) {
                n *= 10;
            }
            int pot10 = pow(10, i);
            r.num = n;
            r.den = pot10;
        }
        r.normalize();
    }
    return Is;
}

このコードは、「合理的な」クラスの入力を実装するために作成しました。繰り返しを含む10進数の入力を可能にするために、C++の本に書かれているものから変更しました。

これらのタイプの入力を処理できる必要があります。

  • 9/8
  • 9
  • 9.87
  • 1.p3(= 1.3333333333)

しかし、それは機能しません。私が本からコピーした部分でさえも機能しません。

誰か助けてもらえますか?

4

2 に答える 2

5

私はこれを多少異なる方法で書くと思います1

本当に別のことをする必要がない限り、入力の「チャンク」全体 (つまり、次の空白までのすべての文字) を読み取ることから始めて、それが数値をどのように表現するかを整理し、別の可能な各表現の関数:

std::istream &operator>>(std::istream &is, rational &r) {
    std::string temp;

    Is >> temp;
    if (temp.find('/') != std::string::npos)
        r = cvt_fraction(temp, Is);
    else if (temp.find_first_of("pP") != std::string::npos)
        r = cvt_repeating(temp, Is);
    else if (temp.find('.') != std::string::npos)
        r = cvt_float(temp, Is);
    else
        r = cvt_int(temp, Is);
    return Is;
}

istream をそれぞれに渡した理由は 2 つあります。1 つ目は、入力にゴミが見つかった場合に、ストリームの失敗ビットを設定できるようにするためです。第二に、彼らが本当にもっと多くの入力を読む必要がある場合は、そうすることができます (しかし、それが本当に必要になるとしたら、私は少し驚きます)。

これらの変換関数のそれぞれはかなり自明なものであるように思われます: 文字列がdigits "/" digits「数字 "p" 数字」である必要があるという事実から始める場合、変換を行うことは一般的に非常に簡単になります-具体的には、おそらく誰でもコードを一瞥して、各部分が何をすべきかを整理できると思うほど簡単です。


  1. 正直なところ、意地悪をするつもりはありませんが、もし私がコードを保守していて、あなたの に出くわしたらoperator>>、考えられる 2 つの反応のうちの 1 つをとることになります。それ以外の場合は、「技術的負債」リストに載せて、できるだけ早く交換してください。単純な事実として、コードのどの部分がそれぞれを処理するか、全体がどのように処理されるかは言うまでもなく、どの入力形式がサポートされることになっているのかを確認するには、かなりの量の研究が必要です。協力して意味のある結果を生み出す。
于 2012-12-05T15:26:28.110 に答える
1

コメントで言及されている問題 (ステートメントpに表示されていない) は、が実際に に格納されている (そこにに格納されている) という事実に由来します。c=is.peek()pwsis >> ws

上記のコードにも についての言及は含まれていませんwsが、char.

于 2012-12-05T14:50:37.897 に答える