C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 12-30-2007, 09:45 AM   #1
Registered User
 
Join Date: Dec 2007
Posts: 1
Please help me to convert a simple C++ program into an object-oriented one.

Hi all,

I’ve been given told to convert a standard C++ program into an object-oriented one, using the principals of polymorphism, encapsulation and inheritance. Our lecturer covered all three principals in one 45 minute slot. I’m completely stuck and would be grateful for any help.

The standard C++ program accepts data values and filter values from the user. It then multiplies these values together using a simple algorithm and prints the output to the screen. The standard program is shown below.

I haven’t made much of a start as I’m unsure how to allocate the classes. I’ve allocated one class to the TheFilter structure with its associated data and functions, and another to the TheData structure.

I hate to admit defeat, but I’ve never programmed using an object-oriented approach and I’ve only been studying C++ for a couple of months. Please help!

Thanks in advance.

Zeke

Standard C++ program follows:

Code:
// Purpose
// A program to demonstrate the application of a simple digital filter
// 
// Overview
// A sequence of data items and digital filter values need to be entered by the
// user. The application of the filter to the data involves a simple convolution 
// operation. The filtered data are stored separately. 
//
// Example
//  before filtering: 
//   data_in = [0 1 3 6 3 1 0]
//   filter = [-0.5 1 -0.5]
//  after filtering:
//   data_out = [-0.5 -0.5 3 -0.5 -0.5]
//  where
//   data_out[0]=data_in[0]*filter[0]+data_in[1]*filter[1]+data_in[2]*filter[2]
//   data_out[1]=data_in[1]*filter[0]+data_in[2]*filter[1]+data_in[3]*filter[2]
//   data_out[2]=data_in[2]*filter[0]+data_in[3]*filter[1]+data_in[4]*filter[2]
//   data_out[3]=data_in[3]*filter[0]+data_in[4]*filter[1]+data_in[5]*filter[2]
//   data_out[4]=data_in[4]*filter[0]+data_in[5]*filter[1]+data_in[6]*filter[2]
//
// The program checks the following
// 1. The data and filter values must have been entered before the filter is 
//    applied
// 2. The filter is not applied if the number of filter values is greater than
//    the number of input data values
// 3. The data and filter values must have been entered and the filter applied 
//    before the filtered data can be displayed
#include <iostream>
using namespace std;
 
// the data values and the filter
struct TheFilter {
  double* Values;   // the filter values
  unsigned long Length;  // number of filter values
  bool Valid;   // true if the filter values have been Valid by the user
};

struct TheData {
  double* Values;  // holds the data to be filtered
  unsigned long Length;  // number of data values
  bool Valid;   // true if the data values have been Valid by the user
};

// function return values
enum {OK,FILTER_TOO_LONG};

// function prototypes
void EnterData(TheData&);
void EnterFilter(TheFilter&);
int ApplyFilter(TheFilter, TheData, TheData&);
void DisplayData(TheFilter, TheData, TheData);
 
// Control the principal operations of the program
// Arguments: None
// Returns: 0 on completion
int main()
{
  // define the filter and its initial values
  TheFilter Filter = {0,0,false};

  // define the original data and its initial values
  TheData OriginalData = {0,0,false};

  // define the filtered data and its initial values
  TheData FilteredData = {0,0,false};

  char UserInput;

  // loop until the user wishes to exit
  while (1) {
    
    // show the menu of options
    cout << endl;
    cout << "Filter Menu" << endl;
    cout << "-----------" << endl;
    cout << "1. Enter data for filtering" << endl;
    cout << "2. Enter filter values" << endl;
    cout << "3. Apply filter" << endl;
    cout << "4. Display filtered data" << endl;
    cout << "5. Exit from the program" << endl << endl;
    
    // get the user's choice
    cout << "Enter your option: ";
    cin >> UserInput;
    cout << endl;
    
    // act on the user's input
    switch(UserInput) {
      case '1':
        EnterData(OriginalData);
        FilteredData.Valid = false;
        break;

      case '2':
        EnterFilter(Filter);
        FilteredData.Valid = false;
        break;      
 
      case '3':
        if (Filter.Valid == true && OriginalData.Valid == true &&
            FilteredData.Valid == false) {
          if (ApplyFilter(Filter,OriginalData,FilteredData) == FILTER_TOO_LONG) {
             cout << "The filter must not be longer than the data" << endl;
          }
          else {
            FilteredData.Valid = true;
            cout << "Filter applied" << endl;
          }
        }
        break;

      case '4':
        if (Filter.Valid == true && OriginalData.Valid == true &&
            FilteredData.Valid == true) {
          DisplayData(Filter,OriginalData,FilteredData);
        }
	 else {
	    cout << "Data have not yet been filtered" << endl;
	 }
        break;

      case '5':
        delete [] Filter.Values;
        delete [] OriginalData.Values;
        delete [] FilteredData.Values;
        return 0;
        break;

      default:
        cout << "Invalid entry" << endl << endl;
        break;
    }
  }
}

// Allow the user to enter the data to be filtered
// Arguments:
//   (1) the structure containing the input data
// Returns: nothing
// 
void EnterData(TheData& GetData)
{  
  // initialize the data structure that holds the data to be filtered, including getting
  // the number of data values from the user
  delete [] GetData.Values;
  cout << "How many data values do you wish to enter: ";
  cin >> GetData.Length;
  GetData.Valid = true;

  // allocate memory to the data
  GetData.Values = new double[GetData.Length];
  if (GetData.Values == 0) {
    cout << "Unable to allocate sufficient memory" << endl;
    exit(1);
  }

  // obtain all of the data values
  cout << endl;
  cout << "Enter the data values" << endl;
  cout << "---------------------" << endl;
  for (unsigned long CountData = 0; CountData < GetData.Length; CountData++) {
    cout << "Enter value " << CountData+1 << ": ";
    cin >> GetData.Values[CountData];
  }
}

// Allow the user to enter the filter values
// Arguments:
//   (1) the structure of the filter to be defined
// Returns: nothing
// 
void EnterFilter(TheFilter& GetFilter)
{  
  // initialize the data structure that holds the filter, including getting the number of
  // filter values from the user
  delete [] GetFilter.Values;
  cout << "How many data values do you wish to enter: ";
  cin >> GetFilter.Length;
  GetFilter.Valid = true;

  // allocate memory to the filter values
  GetFilter.Values = new double[GetFilter.Length];
  if (GetFilter.Values == 0) {
    cout << "Unable to allocate sufficient memory" << endl;
    exit(1);
  }

  // obtain all of the filter values
  cout << endl;
  cout << "Enter the filter values" << endl;
  cout << "-----------------------" << endl;
  for (unsigned long CountData = 0; CountData < GetFilter.Length; CountData++) {
    cout << "Enter value " << CountData+1 << ": ";
    cin >> GetFilter.Values[CountData];
  }
}

// Apply the filter to the input data and store in the filtered data structure
// Arguments:
//   (1) the structure of the filter to be applied
//   (2) the structure containing the data to be filtered
//   (3) the structure to hold the filtered data
// Returns: OK - if the filter is applied
//          FILTER_TOO_LONG - the filter is longer than the data 
//  
int ApplyFilter(TheFilter Filter, TheData DataIn, TheData& DataOut)
{  
  // return an error if the filter is longer than the data
  if (Filter.Length > DataIn.Length) return FILTER_TOO_LONG;

  // initialize the data structure that holds the filtered data
  delete [] DataOut.Values;
  DataOut.Length = DataIn.Length - Filter.Length + 1;

  // get memory for the filtered data
  DataOut.Values = new double[DataOut.Length];
  if (DataOut.Values == 0) {
    cout << "Unable to allocate sufficient memory" << endl;
    exit(1);
  }

  // apply the filter to the data
  for (unsigned long CountData = 0; CountData < DataOut.Length; CountData++) {
    DataOut.Values[CountData] = 0.0; 
    for (unsigned long CountFilter = 0; CountFilter<Filter.Length; CountFilter++) {
      DataOut.Values[CountData] += DataIn.Values[CountData+CountFilter] *
                                   Filter.Values[CountFilter]; 
    }
  }

  return OK;
}


// Display input data, filter values and output data
// Arguments:
//   (1) the structure of the filter to be applied
//   (2) the structure containing the data to be filtered
//   (3) the structure that holds the filtered data
// Returns: nothing
// 
void DisplayData(TheFilter Filter, TheData DataIn, TheData DataOut)
{  
  // display all of the input data values
  cout << endl;
  cout << "The input data values" << endl;
  cout << "---------------------" << endl;
  cout << "[ ";
  for (unsigned long CountData = 0; CountData < DataIn.Length; CountData++) {
    cout << DataIn.Values[CountData] << " ";
  }
  cout << "]" << endl;
    
  // display all of the filter values
  cout << endl;
  cout << "The filter values" << endl;
  cout << "-----------------" << endl;
  cout << "[ ";
  for (unsigned long CountData = 0; CountData < Filter.Length; CountData++) {
    cout << Filter.Values[CountData] << " ";
  }
  cout << "]" << endl;
    
  // display all of the data output values
  cout << endl;
  cout << "The data output values" << endl;
  cout << "----------------------" << endl;
  cout << "[ ";
  for (unsigned long CountData = 0; CountData < DataOut.Length; CountData++) {
    cout << DataOut.Values[CountData] << " ";
  }
  cout << "]" << endl;
}
zekesteer is offline   Reply With Quote
Old 12-30-2007, 10:08 AM   #2
The larch
 
Join Date: May 2006
Posts: 3,086
The Filter class is probably supposed to have an apply method, and a private collection of values. The apply method would check if the collection of numbers entered is valid (larger than number of filter values) and perhaps return false otherwise.

For dynamic arrays I would use std::vector.

The inheritance requirement would probably be satisfied if you defined a FilterBase class with abstract apply method and derived Filter from it.

Polymorphism would be used if you allocated a Filter object and assigned the pointer to a base pointer.

All in all it might look like this:
Code:
class FilterBase
{
    public:
        virtual ~FilterBase();
        virtual void ReadFilters() = 0;
        virtual bool Apply(const std::vector<double>& DataIn, std::vector<double>& DataOut) const = 0;
};

class Filter: public FilterBase
{
    public:
        void ReadFilters();
        bool Apply(const std::vector<double>& DataIn, std::vector<double>& DataOut) const;
    private:
        std::vector<double> filters;
};

int main()
{
    FilterBase* filter = new Filter;
    //...
}
You might also write a std::vector wrapper class for the data, although std::vector already is a class that follows the principles of encapsulation and has everything to act as a suitable container.
__________________
I might be wrong.

Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
Quoted more than 1000 times (I hope).
anon is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
new to object oriented!!!! salmanriaz C++ Programming 2 03-12-2009 07:43 AM
Need help with simple, simple program. LightsOut06 C Programming 5 09-01-2005 08:31 PM
Problem with simple XOR program spike_ C++ Programming 8 08-17-2005 12:09 AM
Simple Timer, Call external program, bliss C++ Programming 2 06-02-2005 11:21 PM
Simple Program not working right (in C) DruzeTito C Programming 5 06-01-2002 10:14 PM


All times are GMT -6. The time now is 02:05 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22