0

I'm trying to implement an observer pattern that keeps track of uppercase letters in a line of text the user enters. Whenever there is an uppercase letter the observers are notified. It compiles fine and when I run it and enter a line of text with no uppercase letters it's ok, but then when there are uppercase letters a window comes up saying the program has stopped working. Since this occurs when i enter an uppercase letter I'm thinking the problem is somewhere in my watch method of the UpperCaseMonitor class. Could someone please help with this any other problems there might be with my code. Thank you.

#include <iostream>
#include <vector>
#include <list>
#include <cctype>
using namespace std;

class Observer;

//===========================================================================
class Observable
{
  public:
    virtual void attach(Observer*)  = 0;
    virtual void detach(Observer*)  = 0;
    virtual void notify()           = 0;

    // Can we get rid of these?
    virtual char get_state()     = 0;
    virtual void set_state(char) = 0;
};

class Observable;

//===========================================================================
class Observer
{
  public:
    virtual void update(Observable*) = 0;
};



//Objects of this type maintain a state whose value is an upper-case character. 
//Objects of this type can be observed by objects that are interested in this object's state.
class UpperCaseMonitor : public Observable 
{
public:
	void attach(Observer*);  //Add the parameter to the list of objects that are observing this object
	void detach(Observer*); //Remove the parameter from the list of objects that are observing this object
    virtual void notify(); //Performs the notify-type behavior of the observer pattern
	
	virtual char get_state()    {return _state; } //Usual access-type behavior
	virtual void set_state(char new_state) {_state = new_state; notify();} //Usual mutator-type behavior
	void watch(char); //If the parameter is an uppercase character the object's state becomes the value of the parameter.

private:
	vector<Observer*> _observers;
	int _state;
};
//An object of this type maintains a count only of the state changes of the object it observes. 
class CountingObserver : public Observer
{
public:
	CountingObserver(UpperCaseMonitor *);
	CountingObserver();
	~CountingObserver();
	virtual void update(Observable*);//Respond to a change of state in the object being observed

	void show_data();//Output a brief message and the maintained value
//private:
	UpperCaseMonitor *_subject;
	int count;
};
//An object of this type stores all states the object it observes has had (since it registered with the object it observed). 
class AccumulatingObserver : public Observer
{
public:
	AccumulatingObserver(UpperCaseMonitor *);
	AccumulatingObserver();
	~AccumulatingObserver();
	virtual void update(Observable*);//Respond to a change of state in the object being observed

	
//private:
	UpperCaseMonitor *_subject;
	void show_data();//Output a brief message and the maintained values in sequence starting with the first. 
};
void process_input(char chr);


int main(){
	// Monitor for uppercase chars
    UpperCaseMonitor     uc_monitor;
    
    // Want to be notified when there's an upper case char
    CountingObserver     observer1;
    AccumulatingObserver observer2;

    // Get registered
    uc_monitor.attach(&observer1);
    uc_monitor.attach(&observer2);

    // Prompt
    cout << "Enter some text, type ^d when done.\n";

    // Process text
    char chr;
    while (cin.get(chr))
    {
        uc_monitor.watch(chr);
        process_input(chr);
    }

    // See what observers know
    observer1.show_data();
    observer2.show_data();



}
void process_input(char chr)
{
    // Maybe do something with the input
}

void UpperCaseMonitor::attach(Observer* obs)
{
	_observers.push_back(obs);
}
void UpperCaseMonitor::detach(Observer* obs)
{
	int count = _observers.size();
	int i;

	for(i = 0; i < count; i++)
	{
		if(_observers[i] == obs)
		break;
	}
	if(i < count)
		_observers.erase(_observers.begin() + i);
}
void UpperCaseMonitor::notify()
{
	int count = _observers.size();

 for (int i = 0; i < count; i++)
   (_observers[i])->update(this); 
}
void UpperCaseMonitor::watch(char chr)
{
	if (isupper(chr))
	{
		set_state(chr);
		
	}
}
CountingObserver::CountingObserver(UpperCaseMonitor *s)
{
 _subject = s;
 _subject->attach(this);
}
CountingObserver::CountingObserver()
{

}
CountingObserver::~CountingObserver()
{
_subject->detach(this);
}
void CountingObserver::update(Observable* ChangedState)
{
  if(ChangedState = _subject)
	  show_data();
}
void CountingObserver::show_data()
{
	char value = _subject->get_state();

	count += 1;

	cout << "Number of state changes is " << count << " and most recent state change is " << value << endl;
}
AccumulatingObserver::AccumulatingObserver(UpperCaseMonitor *s)
{
 _subject = s;
 _subject->attach(this);
}
AccumulatingObserver::AccumulatingObserver()
{

}
AccumulatingObserver::~AccumulatingObserver()
{
_subject->detach(this);
}
void AccumulatingObserver::update(Observable* ChangedState)
{
  if(ChangedState = _subject)
	  show_data();
}
void AccumulatingObserver::show_data()
{
	char value = _subject->get_state();

	list<char> charList;
   for( int i=0; i < 10; i++ ) {
     charList.push_front(value);
   }
   
   cout << "Maintained states: " << endl;
   // Display the list
   list<char>::iterator theIterator;
   for( theIterator = charList.begin(); theIterator != charList.end(); theIterator++ ) {
     cout << *theIterator;
   }            



	

	
}
2
Contributors
1
Reply
2
Views
6 Years
Discussion Span
Last Post by template<>
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.