I'm writing an Observer Pattern program that uses an UpperCaseMonitor subject or concrete subject to monitor when there is an uppercase letter in a line of text entered by the user. Everything seems to work fine until i try to access the state changes to keep count, store, and print out in the the "show_data()" methods of the CountingObserver and AccumulatingObserver classes. Whenever an uppercase letter is entered a window comes up saying the program has stopped running, so I know it's some kind of run-time error. After debugging it I'm pretty sure the error is in the "char value = _subject->get_state();" statement, but I can't figure out what to change to fix the problem. When I comment out that line in the show_data() methods the program will run, but I need it or some other way to access the states so I can store and output them. My code is below.

#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;
	char _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 state_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)
{ state_count = 0;
 _subject = s;
 _subject->attach(this);
}
CountingObserver::CountingObserver()
{
  state_count = 0;
}
CountingObserver::~CountingObserver()
{
_subject->detach(this);
}
void CountingObserver::update(Observable* ChangedState)
{
  if(ChangedState = _subject)
	  show_data();
}
void CountingObserver::show_data()
{
	
	 char value = _subject->get_state();

	state_count += 1;

	cout << "Number of state changes is " << state_count << " and most recent state change is " << endl; //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;
   }            



	

	
}

Recommended Answers

All 3 Replies

Lines 163 and 190 don't do what you want them to do. Besides, the way you set up your constructors, the _subject is uninitialized.

Lines 163 and 190 don't do what you want them to do. Besides, the way you set up your constructors, the _subject is uninitialized.

Is there any way you could help me change it to to fix the problem, I've been trying to fix it for two days and I need to have it finished soon. I would really appreciate it.

Hint #1: '=' and '==' are really different.
Hint #2: You have two constructors for CountingObserver. Which one is called at line 86?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.