2014年4月13日日曜日

開発環境

C++実践プログラミング (スティーブ オウアルライン (著)、Steve Oualline (原著)、Steve Oualline(原著)、望月 康司(翻訳)、クイープ(翻訳) 、オライリー・ジャパン)のⅣ部(高度なプログラミング概念)の18章(演算子のオーバーロード)、18.6(プログラミング実習)、実習 18-1.を解いてみる。

その他参考書籍

実習 18-1.

コード(BBEdit, Emacs)

rational.h

#ifndef __rational_h__
#define __rational_h__
#include <iostream>
#include <stdlib.h>

class rational {
private:
  int n;
  int d;
  static int gcd(int m, int n)
  {
    int t;

    m = m < 0 ? -m : m;
    n = n < 0 ? -n : n;
    if (m < n) {
      t = m;
      m = n;
      n = t;
    }
    if (n == 0)
      return m;
    return gcd(n, m % n);
  }
public:
  rational() {
    n = 0;
    d = 1;
  }
  rational(int a, int b) {
    int t = gcd(a, b);
    
    n = a / t;
    d = b / t;
  }
  rational(const rational& old_rational) {
    rational(old_rational.n, old_rational.d);
  }
  ~rational(){}
  rational operator = (const rational& old_rational) {
    n = old_rational.n;
    d = old_rational.d;
    return (*this);
  }
  rational& operator += (const rational& old_rational) {
    (*this) = (*this) + old_rational;
    return (*this);
  }
  rational& operator += (int x) {
    (*this) = (*this) + rational(x, 1);
    return (*this);
  }
  rational& operator -= (const rational& old_rational) {
    (*this) = (*this) - old_rational;
    return (*this);
  }
  rational& operator -= (int x) {
    (*this) = (*this) - rational(x, 1);
    return (*this);
  }    
  rational& operator *= (const rational& old_rational) {
    (*this) = (*this) * old_rational;
    return (*this);
  }
  rational& operator *= (int x) {
    (*this) = (*this) * rational(x, 1);
    return (*this);
  }
  rational& operator /= (const rational& old_rational) {
    (*this) = (*this) / old_rational;
    return (*this);
  }
  rational& operator /= (int x) {
    (*this) = (*this) / rational(x, 1);
    return (*this);
  }
  friend rational operator + (const rational& op1, const rational& op2);
  friend rational operator + (const rational& op1, int op2);
  friend rational operator + (int op1, const rational& op2);
  friend rational operator - (const rational& op1, const rational& op2);
  friend rational operator - (const rational& op1, int op2);
  friend rational operator - (int op1, const rational& op2);
  friend rational operator * (const rational& op1, const rational& op2);
  friend rational operator * (const rational& op1, int op2);
  friend rational operator * (int op1, const rational& op2);
  friend rational operator / (const rational& op1, const rational& op2);
  friend rational operator / (const rational& op1, int op2);
  friend rational operator / (int op1, const rational& op2);
  friend std::ostream& operator << (std::ostream& out_file,
                                    const rational& r);
  friend std::istream& operator >> (std::istream& in_file,
                                    rational& r);
};

inline rational operator + (const rational& op1, const rational& op2) {
  int n1 = op1.n;
  int d1 = op1.d;
  int n2 = op2.n;
  int d2 = op2.d;
  int n = n1 * d2 + n2 * d1;
  int d = d1 * d2;
  int t = rational::gcd(n, d);
  return rational(n / t, d / t);
}
inline rational operator + (const rational& op1, int op2) {
  return op1 + rational(op2, 1);
}  
inline rational operator + (int op1, const rational& op2) {
  return rational(op1, 1) + op2;
}
inline rational operator - (const rational& op1, const rational& op2) {
  int n1 = op1.n;
  int d1 = op1.d;
  int n2 = op2.n;
  int d2 = op2.d;
  int n = n1 * d2 - n2 * d1;
  int d = d1 * d2;
  int t = rational::gcd(n, d);
  return rational(n / t, d / t);
}
  
inline rational operator - (const rational& op1, int op2) {
  return op1 - rational(op2, 1);
}
inline rational operator - (int op1, const rational& op2) {
  return rational(op1, 1) - op2;
}
inline rational operator * (const rational& op1, const rational& op2) {
  int n1 = op1.n;
  int d1 = op1.d;
  int n2 = op2.n;
  int d2 = op2.d;
  int n = n1 * n2;
  int d = d1 * d2;
  int t = rational::gcd(n, d);
  return rational(n / t, d / t);
}
inline rational operator * (const rational& op1, int op2) {
  return op1 * rational(op2, 1);
}
inline rational operator * (int op1, const rational& op2) {
  return rational(op1, 1) * op2;
}
inline rational operator / (const rational& op1, const rational& op2) {
  int n2 = op2.n;
  int d2 = op2.d;
  return op1 * rational(d2, n2);
}
inline rational operator / (const rational& op1, int op2) {
  return op1 / rational(op2, 1);
}
inline rational operator / (int op1, const rational& op2) {
  return rational(op1, 1) / op2;
}
inline std::ostream& operator << (std::ostream& out_file, const rational& r)
{
  if (r.d == 1)
    out_file << r.n;
  else
    out_file << r.n << '/' << r.d;
  return (out_file);
}

extern std::istream& operator >> (std::istream& in_file, rational& r);
#endif  /* __rational_h__ */

rational.cpp

#include <iostream>
#include "rational.h"

std::istream& operator >> (std::istream& in_file, rational& r)
{
  int n;
  char ch;
  int d;
  int t;

  r = rational();

  std::istream::sentry the_sentry(in_file, true);

  if (the_sentry) {
    if (in_file.fail()) return (in_file);
    in_file >> n;
    if (in_file.fail()) return (in_file);
    in_file >> ch;
    if (in_file.fail()) return (in_file);
    if (ch != '/') {
      in_file.setstate(std::ios::failbit);
      return (in_file);
    }
    in_file >> d;
    if (in_file.fail()) return (in_file);
    t = rational::gcd(n, d);
    r.n = n / t;
    r.d = d / t;
  }
  else
    in_file.setstate(std::ios::failbit);
  
  return (in_file);
}

test_rational.cpp

#include <iostream>
#include "rational.h"

int main(int argc, char *argv[])
{
  rational r1(1, 3);
  rational r2(1, 2);
  rational r3;
  
  std::cout << r1 << " + " << r2 << " = " << r1 + r2 << std::endl;
  std::cout << r1 << " - " << r2 << " = " << r1 - r2 << std::endl;
  std::cout << r1 << " * " << r2 << " = " << r1 * r2 << std::endl;
  std::cout << r1 << " / " << r2 << " = " << r1 / r2 << std::endl;

  std::cout << "分数を入力(n/d): ";
  std::cin >> r3;
  std::cout << r1 << " + " << r3 << " = " << r1 + r3 << std::endl;
  r2 += 1;
  std::cout << r2 << "(3/2)" << std::endl;
  r1 -= r3;
  std::cout << r1 << "(-1/6)" << std::endl;
  std::cout << rational(1, 2) + rational(5, 10) << "(1)" << std::endl;
  return (0);
}

Makefile

#
# FSFのg++コンパイラ用のMakefile
#
CC=g++
CFLAGS=-g -Wall
all: test_rational

test_rational: test_rational.o rational.o
 ${CC} ${CFLAGS} -o test_rational test_rational.o rational.o

test_rational.o: test_rational.cpp
 ${CC} -c -o test_rational.o test_rational.cpp

rational.o: rational.cpp
 ${CC} -c -o rational.o rational.cpp

clean:
 rm test_rational

入出力結果(Terminal)

$ make && ./test_rational
g++ -c -o test_rational.o test_rational.cpp
g++ -c -o rational.o rational.cpp
g++ -g -Wall -o test_rational test_rational.o rational.o
1/3 + 1/2 = 5/6
1/3 - 1/2 = -1/6
1/3 * 1/2 = 1/6
1/3 / 1/2 = 2/3
分数を入力(n/d): 1/2
1/3 + 1/2 = 5/6
3/2(3/2)
-1/6(-1/6)
1(1)
$

0 コメント:

コメントを投稿