понедельник, 27 июня 2011 г.

Исключения

Собственный класс исключения CastException с перегруженным оператором << для записи в объект исключения и несколько примеров его использования.
#include <climits>
#include <cstring>
#include <exception>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::exception;
using std::string;

class CastException: public exception {
 protected:
  string message;
 public:
  virtual ~CastException () throw() {}

  virtual const char* what() const throw() {
    return message.c_str();
  }

  CastException& operator<< (const char* str) {
    message.append(str);
    return *this;
  }

  CastException& operator<< (const string str) {
    message += str;
    return *this;
  }
};

class TooBigStringException: public CastException {
 public:
  TooBigStringException() {
    message.append("Too big string!");
  }
};

class TooBigCharTypeException: public CastException {
 public:
  TooBigCharTypeException() {
    message.append("Too big CharType!");
  }
};

class IncorrectSymbolException: public CastException {
 public:
  IncorrectSymbolException() {
    message.append("Incorrect symbol!");
  }
};

class OverflowException: public CastException {
 public:
  OverflowException() {
    message.append("Overflow!");
  }
};

class InvalidValueException: public CastException {
 public:
  InvalidValueException() {
    message.append("Invalid value!");
  }
};

template <typename CharType>
inline char CharFromString(const CharType* data, size_t len) {
  if (len > 1) {
    throw TooBigStringException();
  }
  if (sizeof(CharType) > sizeof(char)) {
    throw TooBigCharTypeException();
  }
  return static_cast<char>(*data);
}

bool addition_is_safe(int a, int b) {
  return INT_MAX - b >= a;
}

bool multiplication_is_safe(int a, int b) {
  return INT_MAX / b >= a;
}

template <typename CharType>
inline int IntFromString(const CharType* data, size_t len) {
  int res = 0;
  for (size_t i = 0; i < len; ++i) {
    if (static_cast<char>(data[i]) < '0' || static_cast<char>(data[i]) > '9') {
      throw IncorrectSymbolException();
    }
    if (!multiplication_is_safe(res, 10)) {
      throw OverflowException();
    }
    res *= 10;
    if (!addition_is_safe(res, static_cast<char>(data[i]) - '0')) {
      throw OverflowException();
    }
    res += static_cast<char>(data[i]) - '0';
  }
  return res;
}

bool addition_is_safe(long long a, long long b) {
  return LLONG_MAX - b >= a;
}

bool multiplication_is_safe(long long a, long long b) {
  return LLONG_MAX / b >= a;
}

template <typename CharType>
inline long long LongLongFromString(const CharType* data, size_t len) {
  long long res = 0;
  for (size_t i = 0; i < len; ++i) {
    if (static_cast<char>(data[i]) < '0' || static_cast<char>(data[i]) > '9') {
      throw IncorrectSymbolException();
    }
    if (!multiplication_is_safe(res, 10LL)) {
      throw OverflowException();
    }
    res *= 10;
    if (!addition_is_safe(res, static_cast<long long>(data[i]) - '0')) {
      throw OverflowException();
    }
    res += static_cast<long long>(data[i]) - '0';
  }
  return res;
}

template <typename CharType>
inline bool BoolFromString(const CharType* data, size_t len) {
  if (len == 1) {
    if (*data == '0') {
      return false;
    } else if (*data == '1') {
      return true;
    } else {
      throw IncorrectSymbolException();
    }
  } else if (len == 4 && strncmp(data, "true", 4) == 0) {
    return true;
  } else if (len == 5 && strncmp(data, "false", 5) == 0) {
    return false;
  } else {
    throw InvalidValueException();
  }
}

int main() {
  cout << "From \"a\" to char: ";
  try {
    cout << CharFromString<char>("a", 1) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }
  cout << "From \"ab\" to char: ";
  try {
    cout << CharFromString<char>("ab", 2) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }

  cout << "From 42 to int: ";
  try {
    cout << IntFromString<char>("42", 2) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }
  cout << "From 2147483648 (INT_MAX + 1) to int: ";
  try {
    cout << IntFromString<char>("2147483648", 10) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }

  cout << "From 7500 to long long: ";
  try {
    cout << LongLongFromString<char>("7500", 4) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }
  cout << "From \"STR_NOT_NUM\" to long long: ";
  try {
    cout << LongLongFromString<char>("STR_NOT_NUM", 11) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }

  cout << "From \"true\" to bool: ";
  try {
    cout << BoolFromString<char>("true", 4) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }
  cout << "From \"1234\" to bool: ";
  try {
    cout << BoolFromString<char>("1234", 4) << endl;
  } catch (CastException& ex) {
    cout << ex.what() << endl;
  }
  return 0;
}

Комментариев нет:

Отправить комментарий