Fibonacci series

Hamrick 0 Tallied Votes 155 Views Share

A simple solution that prints the first n values in the fibonacci series up to the limit of an unsigned long. The program takes either command line arguments or interactive input for n and has code in place to make the program more flexible, like printing to a file.

#include <cstdlib>
#include <iostream>
#include <limits>
#include <sstream>
#include <stdexcept>

using namespace std;

/// <summary> Make sure that two values can be summed without overflow. </summary>
template <class T>
bool CanSum( T a, T b ) {
  // If the difference of the largest value of T and a
  // is less than b, the addition will overflow.
  return numeric_limits<T>::max() - a >= b;
}

/// <summary> Find the next Fibonacci value, and update a and b. </summary>
template <class T>
T NextInSequence( T& a, T& b ) {
  T next = a + b;

  b = a;
  a = next;

  return next;
}

/// <summary> Print the first n values of the Fibonacci series. </summary>
template <class CharT>
void FibonacciSequence( basic_ostream<CharT>& stream, int n ) {
  unsigned long a = 0;
  unsigned long b = 1;

  for ( int i = 0; i < n && CanSum( a, b ); ++i ) {
    cout<< NextInSequence( a, b ) <<"\n";
  }
}

/// <summary> Get the next value of type T from the stream. </summary>
/// <parameter name="isConsole"> True if the stream is a console. </parameter>
/// <returns> The input item or T's default value on eof. </returns>
template <class T, class CharT>
T GetNextItem( basic_istream<CharT>& stream, bool isConsole ) {
  T item = T();

  while ( !( cin >> item ) && !cin.eof() ) {
    if ( !isConsole ) {
      // Input is automated. All we can do is error.
      throw runtime_error( "Invalid item type." );
    } else {
      // Input is interactive. Get the user to recover.
      stream.clear();
      stream.sync();
      cerr<<"Invalid item type. Try again> ";
    }
  }

  return item;
}

const int INVALID_INDEX = -1;

int main( int argc, char *argv[] ) {
  // The index of the Fibonacci number to stop at.
  int n = INVALID_INDEX;

  if ( argc >= 2 ) {
    // Try to get the command line index first.
    stringstream( argv[1] ) >> n;
  }
  
  if ( n == INVALID_INDEX ) {
    // If there's no command line index or the command line
    // didn't have a valid index, get it interactively.
    cout<<"Fibonacci numbers to generate> ";
    n = GetNextItem<int>( cin, true );
  }

  if ( cin.good() ) {
    // Only run the sequence if there were no errors or eof.
    FibonacciSequence( cout, n );
  }

  return 0;
}