JMU
Exceptions in C++
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Motivation
Questions and Observations
The try-catch Statement
The try-catch Statement (cont.)
The try-catch Statement (cont.)

Writing an Exception Class - The Specification

cppexamples/exceptions/NumberFormatException.h
        /**
 * A NumberFormatException can be thrown by a function that is
 * attempting to convert a string (or string-like object) to a
 * number.
 *
 * @author  Prof. David Bernstein, James Madison University
 */

#ifndef edu_jmu_cs_NumberFormatException_h
#define edu_jmu_cs_NumberFormatException_h

class NumberFormatException {
 public:
  // The character causing the problem
  int position;

  /**
   * Default Constructor
   */
  NumberFormatException();

  /**
   * Explicit Value Constructor
   *
   * @param i   The position in the string that caused the problem
   */
  explicit NumberFormatException(int i);
};

#endif
        
The try-catch Statement (cont.)

Writing an Exception Class - The Implementation

cppexamples/exceptions/NumberFormatException.cpp
        /**
 * A NumberFormatException can be thrown by a function that is
 * attempting to convert a string (or string-like object) to a
 * number.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */

#include "NumberFormatException.h"

NumberFormatException::NumberFormatException() {
  position = -1;
}

NumberFormatException::NumberFormatException(int i) {
  position = i;
}
        
The try-catch Statement (cont.)

Using an Exception Class in Another Class - The Specification

cppexamples/exceptions/StringConverter.h
        /**
 * A utility class for converting character arrays into numbers
 *
 * @author  Prof. David Bernstein, James Madison University
 */
#ifndef edu_jmu_cs_StringConverter_h
#define edu_jmu_cs_StringConverter_h

#include "NumberFormatException.h"
#include <string.h>

class StringConverter {
 public:
  /**
   * Convert a character array to a double.
   *
   * @param s   Pointer to the character array
   * @return    The numeric "value" of the string
   * @throws    NumberFormatException if the string cannot be converted
   */
  static double toDouble(const char *s);
};

#endif
        
The try-catch Statement (cont.)

Using an Exception Class in Another Class - The Implementation

cppexamples/exceptions/StringConverter.cpp
        #include "StringConverter.h"

double StringConverter::toDouble(const char *s) {
  double sign, multiplier, value;
  int decimalIndex, endIndex, i, length, startIndex;

  length = strlen(s);

  // Ignore leading spaces
  //
  startIndex = 0;
  while (s[startIndex] == ' ') {
    startIndex++;
  }

  // Ignore trailing space
  //
  endIndex = length - 1;
  while (s[endIndex] == ' ') {
    endIndex--;
  }

  // Handle inital - or +
  //
  sign = 1.0;
  if (s[startIndex] == '-') {
    sign = -1.0;
    startIndex++;
  } else if (s[startIndex] == '+') {
    sign = 1.0;
    startIndex++;
  }

  // Find the (first) decimal point (if there is one)
  //
  decimalIndex = -1;
  for (i = startIndex; i <= endIndex; i++) {
    if (s[i] == '.') {
      decimalIndex = i;
      break;
    }
  }
  if (decimalIndex < 0)
    decimalIndex = endIndex + 1;

  // See if all of the remaining characters are digits.
  // If not, throw a NumberFormatException
  //
  for (i = startIndex; i <= endIndex; i++) {
    if ((i != decimalIndex) && (s[i] < '0' || s[i] > '9')) {
      throw NumberFormatException(i);
    }
  }

  // Calculate the value of the number
  //
  value = 0.0;

  // First work to the left of the decimal place
  //
  multiplier = 1.00;
  for (i = decimalIndex - 1; i >= startIndex; i--) {
    value += static_cast<double>(s[i] - '0') * multiplier;
    multiplier *= 10.0;
  }

  // Now work to the right of the decimal place
  //
  multiplier = 0.10;
  for (i = decimalIndex + 1; i <= endIndex; i++) {
    value += static_cast<double>(s[i] - '0') * multiplier;
    multiplier /= 10.0;
  }

  value = sign * value;

  return value;
}
        
The try-catch Statement (cont.)

Using an Exception Class- Use

cppexamples/exceptions/Driver.cpp
        /**
 * An example that uses a NumberFormatException
 *
 * @author  Prof. David Bernstein, James Madison University
 */
#include <iostream>
#include "StringConverter.h"
using namespace std;

/**
 * The entry point of the example
 */
int main(void) {
  char s[80];
  double d;

  cout << "Enter a number (or ^Z): ";
  while ((cin >> s) && (!cin.eof())) {
    // Try to convert s into a double
    //
    try {
      d = StringConverter::toDouble(s);
      cout << "\nYou entered: " << d << "   Nice job!" << "\n\n";

      // Proceed accordingly if a
      // NumberFormatException is thrown
      //
    } catch (NumberFormatException &nfe) {
      cout << endl << "Invalid charcter at position: " << nfe.position << endl;

      cout << endl << "Invalid character is:         " << s[nfe.position]
           << endl;

      cout << "Try again!" << endl;
    }
    cout << "Enter a number (or ^Z): ";
  }
}

        
Overuse
Standardization