2014年5月4日日曜日

開発環境

C++実践プログラミング (スティーブ オウアルライン (著)、Steve Oualline (原著)、Steve Oualline(原著)、望月 康司(翻訳)、クイープ(翻訳) 、オライリー・ジャパン)のⅤ部(言語のその他の機能)の22章(例外)、22.3(プログラミング実習)、実習 22-2.を解いてみる。

その他参考書籍

実習 22-2.

コード(BBEdit, Emacs)

fraction.h

#ifndef __fraction_h__
#define __fraction_h__
#include <iostream>
#include <cstdlib>

class zero_div_err {
 public:
  const std::string what;
 zero_div_err(const std::string& i_what) : what(i_what) {}
};

class fraction {
 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:
  fraction() {
    n = 0;
    d = 1;
  }
  fraction(int a, int b) {
    if (b == 0) {
      throw zero_div_err("division by zero");
    }
    int t = gcd(a, b);
    
    n = a / t;
    d = b / t;
  }
  fraction(const fraction& old_fraction) {
    fraction(old_fraction.n, old_fraction.d);
  }
  ~fraction(){}
  fraction operator = (const fraction& old_fraction) {
    n = old_fraction.n;
    d = old_fraction.d;
    return (*this);
  }
  fraction& operator += (const fraction& old_fraction) {
    (*this) = (*this) + old_fraction;
    return (*this);
  }
  fraction& operator += (int x) {
    (*this) = (*this) + fraction(x, 1);
    return (*this);
  }
  fraction& operator -= (const fraction& old_fraction) {
    (*this) = (*this) - old_fraction;
    return (*this);
  }
  fraction& operator -= (int x) {
    (*this) = (*this) - fraction(x, 1);
    return (*this);
  }    
  fraction& operator *= (const fraction& old_fraction) {
    (*this) = (*this) * old_fraction;
    return (*this);
  }
  fraction& operator *= (int x) {
    (*this) = (*this) * fraction(x, 1);
    return (*this);
  }
  fraction& operator /= (const fraction& old_fraction) {
    (*this) = (*this) / old_fraction;
    return (*this);
  }
  fraction& operator /= (int x) {
    (*this) = (*this) / fraction(x, 1);
    return (*this);
  }
  friend fraction operator + (const fraction& op1, const fraction& op2);
  friend fraction operator + (const fraction& op1, int op2);
  friend fraction operator + (int op1, const fraction& op2);
  friend fraction operator - (const fraction& op1, const fraction& op2);
  friend fraction operator - (const fraction& op1, int op2);
  friend fraction operator - (int op1, const fraction& op2);
  friend fraction operator * (const fraction& op1, const fraction& op2);
  friend fraction operator * (const fraction& op1, int op2);
  friend fraction operator * (int op1, const fraction& op2);
  friend fraction operator / (const fraction& op1, const fraction& op2);
  friend fraction operator / (const fraction& op1, int op2);
  friend fraction operator / (int op1, const fraction& op2);
  friend std::ostream& operator << (std::ostream& out_file,
                                    const fraction& r);
  friend std::istream& operator >> (std::istream& in_file,
                                    fraction& r);
};

inline fraction operator + (const fraction& op1, const fraction& 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 = fraction::gcd(n, d);
  return fraction(n / t, d / t);
}
inline fraction operator + (const fraction& op1, int op2) {
  return op1 + fraction(op2, 1);
}  
inline fraction operator + (int op1, const fraction& op2) {
  return fraction(op1, 1) + op2;
}
inline fraction operator - (const fraction& op1, const fraction& 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 = fraction::gcd(n, d);
  return fraction(n / t, d / t);
}
  
inline fraction operator - (const fraction& op1, int op2) {
  return op1 - fraction(op2, 1);
}
inline fraction operator - (int op1, const fraction& op2) {
  return fraction(op1, 1) - op2;
}
inline fraction operator * (const fraction& op1, const fraction& 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 = fraction::gcd(n, d);
  return fraction(n / t, d / t);
}
inline fraction operator * (const fraction& op1, int op2) {
  return op1 * fraction(op2, 1);
}
inline fraction operator * (int op1, const fraction& op2) {
  return fraction(op1, 1) * op2;
}
inline fraction operator / (const fraction& op1, const fraction& op2)
{
  int d2 = op2.d;
  if (d2 == 0)
    throw zero_div_err("division by zero");
  int n2 = op2.n;
  
  return op1 * fraction(d2, n2);
}
inline fraction operator / (const fraction& op1, int op2) {
  return op1 / fraction(op2, 1);
}
inline fraction operator / (int op1, const fraction& op2) {
  return fraction(op1, 1) / op2;
}
inline std::ostream& operator << (std::ostream& out_file, const fraction& 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, fraction& r);
#endif  /* __fraction_h__ */

fraction.cpp

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

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

  r = fraction();

  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);
    if (d == 0)
      throw zero_div_err("division by zero");
    t = fraction::gcd(n, d);
    r.n = n / t;
    r.d = d / t;
  }
  else
    in_file.setstate(std::ios::failbit);
  
  return (in_file);
}

test_fraction.h

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

int main(int argc, char *argv[])
{
  fraction r1(1, 3);
  fraction r2(1, 2);
  fraction 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): ";
  try {
    std::cin >> r3;
  }
  catch (zero_div_err& err) {
    std::cerr << "ZeroDivisionError: " << err.what << std::endl;
  }
  catch (...) {
    std::cerr << "Error: Unexpected exception occurred" << std::endl;
  }

  try {
    fraction r4(10, 0);
  }
  catch (zero_div_err& err) {
    std::cerr << "ZeroDivisionError: " << err.what << std::endl;
  }
  catch (...) {
    std::cerr << "Error: Unexpected exception occurred" << std::endl;
  }
  
  return (0);
}

Makefile

CC=g++
CFLAGS=-g -Wall
all: test_fraction

test_fraction: test_fraction.cpp fraction.o fraction.h
 ${CC} ${CFLAGS} -o test_fraction test_fraction.cpp fraction.o

fraction.o: fraction.cpp fraction.h
 ${CC} -c -o fraction.o fraction.cpp

clean:
 rm test_fraction

入出力結果(Terminal)

$ make && ./test_fraction
g++ -g -Wall -o test_fraction test_fraction.cpp fraction.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/0
ZeroDivisionError: division by zero
ZeroDivisionError: division by zero
$

0 コメント:

コメントを投稿