Thread: Please help me to convert a simple C++ program into an object-oriented one.

  1. #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;
    }

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    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.

    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).

Popular pages Recent additions subscribe to a feed

Similar Threads

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