Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Background: The purpose of this assignment is to practice dealing with exception

ID: 3760673 • Letter: B

Question

Background:

The purpose of this assignment is to practice dealing with exception handling and textual data. Exception handling is a very important part of being an object-oriented programming. Rather returning some kind of int return value every time you tickle an object, C++ programmers expect methods to focus on their task at hand. If something bad happens, C++ programmers expect methods to throw exceptions. When caught, exceptions can be processed. When uncaught, they cause a program to terminate dead in its tracks. The typical pattern in this course is to have class code throw exceptions and driver code catch them. Because of exceptions, when writing client driver code, our try blocks will not be polluted with error processing statements. Our other topic in this unit is recursion. I am trying to give you an assignment where you get some practice thinking recursively.

Project 1: Exception Mailbox

The purpose of this assignment is to work with exceptions. As you may recall, I have provided you with a sample class named Mailbox which has been diagrammed below. I'd like you to enhance this class so that invoking its methods or operators potentially throw exceptions, rather than just printing error messages to cout. Currently, our favorite exception class is std::logic_error. You can create a logic_error by passing a string value to its constructor. Officially, you should also say #include <stdexcept> to begin working with logic_error, but Visual Studio (being a badly behaved child...) let's you get away with it.

Although the sample driver code might not code for all these circumstances, I would like you to throw exceptions whenever:

a negative number is potentially stored in myContents (due to calls to operator - or negative values being sent to deliverMail)

a negative number is potentially stored in mySize (due to calls to operator - or setSize)

having a myContents that exceeds mySize (due to calls to operator + or deliverMail or setSize)

So carefully wind your way thru all the operators and methods of the class ensuring that logic_error gets thrown in each of these circumstances.

HINT: Recall that you can create a logic_error by passing a string message. For example,

  std::logic_error error( "Bad News" );

While not required with Visual Studio, please #include <stdexcept> when working with this class. Linux fans will require this include; its optional for Windows users but wont hurt anything if you do it. Here is a class diagram for logic_error. As I said, it already exists so please make use of it.

Project 2: Adder

The goal of this program is to practice using recursion. The Adder class performs the mathematical operation a + b in two ways: one is iterative (using loops or control flow) and one is recursive (gets to call itself over and over again). You might not think that addition can be implemented using recursion, but if you follow the cases shown below, it can be done recursively:

BASE CASE: if ( a == 0 ) return( b );
BASE CASE: if ( b == 0 ) return( a );
RECURSIVE CASE: return( 2 + RecursiveAPlusB( a - 1, b -1 ) );

HINT: You'll probably need to create some additional methods...

Explanation / Answer

class TDriver: public HandleObject {

public:

        // Constructor and destructor.

        TDriver();

        ~TDriver();

OSErr   iacOpen(ParmBlkPtr oParmBlock);

    OSErr   iacPrime(ParmBlkPtr pParmBlock);

    OSErr   iacControl(ParmBlkPtr cntlParmBlock);

    OSErr   iacStatus(ParmBlkPtr sParmBlock);

    OSErr   iacClose(ParmBlkPtr cParmBlock);

   

private:

    short       RegisterApp(IACRecord   *anIACPtr);

    short       SendMessage(IACRecord   *anIACPtr);

    short       ReceiveMessage(IACRecord    *anIACPtr);

    short       UnregisterApp(IACRecord *anIACPtr);

   

    void        WhosThere(IACRecord *anIACPtr);

    Boolean AnyMessagesForMe(IACRecord *anIACPtr);

   

    TMessPtr    GetMessage(short signature);

    void        SetMessage(short index, TMessPtr    aMsgPtr);

    char        *GetAppName(short signature);

    void        SetAppName(short signature, char *anAppName);

   

    char        fAppNameArray[kMaxApps] [255];

    TMessPtr    fMessageArray[kMaxMessages];

};

from TMessage.h

class TMessage {

public:

        TMessage(char *message, short senderSig, short receiverSig);

        ~TMessage();

    Boolean IsMessageForMe(short sigOfRequestor);

    Boolean IsMessageForMe(short sigOfRequestor, short *senderSig,

                     char *messageString);

   

private:

    short       GetSenderSig();

    void        SetSenderSig(short signature);

    short       GetReceiverSig();

    void        SetReceiverSig(short signature);

    char        *GetMessageString();

    void        SetMessageString(char *msgString);

    short       fSenderSig;

    short       fReceiverSig;

    char        fMessageString[255];

};

short

TDriver::RegisterApp(IACRecord *anIACPtr)

{

short       i = 0;

short       canDo = kNoMore;

while ((i < kMaxApps) && (canDo == kNoMore))

    {

    if((this->GetAppName(i))[0] == kZeroChar)

        {

        canDo = kNoErr;

        anIACPtr->mySignature = i;

        this->SetAppName(i,anIACPtr->appName);

        }

    i++;

    }

return (canDo);

} // TDriver::RegisterApp

short

TDriver::SendMessage(IACRecord *anIACPtr)

{

TMessPtr    aMsgPtr;

short       canDo = kNoMore;

short       i = 0;

aMsgPtr = new TMessage(anIACPtr->messageString,

        anIACPtr->mySignature, anIACPtr->partnerSig);

if(aMsgPtr)

    {

    while ((i < kMaxMessages) && (canDo == kNoMore))

        {

        if(this->GetMessage(i) == nil)

            {

            this->SetMessage(i, aMsgPtr);

            canDo = kNoErr;

            }

        i++;

        }

    if (canDo == kNoMore)

        delete aMsgPtr;

    } // if aMsgPtr

else

    canDo = kMsgMemErr;

return (canDo);    

} // TDriver::SendMessage

short

TDriver::ReceiveMessage(IACRecord *anIACPtr)

{

TMessPtr        aMsgPtr;

short           sender;

char            *bufP = nil;

if(this->AnyMessagesForMe(anIACPtr))

    {

    aMsgPtr = this->GetMessage(anIACPtr->actualCount);

    (void) aMsgPtr->IsMessageForMe

        (anIACPtr->mySignature,&sender,bufP);  

    anIACPtr->partnerSig = sender;

    tseStrCpy(anIACPtr->messageString,bufP);

    tseStrCpy(anIACPtr->appName,

        this->GetAppName(anIACPtr->partnerSig));

    this->SetMessage(anIACPtr->actualCount,nil);

        delete aMsgPtr;

        return (kYesMessagesForMe);

        }

else

        return(kNoMore);

} // TDriver::ReceiveMessage

short

TDriver::UnregisterApp(IACRecord *anIACPtr)

{

char        zeroChar = kZeroChar;

// Gotta delete those suckers.

while (this->ReceiveMessage(anIACPtr) == kYesMessagesForMe) ;

// Zero the name so others can play.

this->SetAppName(anIACPtr->mySignature,&zeroChar);

return (kNoErr);

} // TDriver::UnregisterApp

void

changeDRVRSlot(short slot)

{

Handle      theDRVR;

short       err, refNum;

char        *name, DRVRname[256];

short       DRVRid;

ResType     DRVRType;

name = "p.TimDriver";

if(slot != 0) {

    theDRVR = GetNamedResource('DRVR', name);

    GetResInfo(theDRVR, &DRVRid, &DRVRType, &DRVRname);

    SetResInfo(theDRVR, slot, 0L);

   

    err = OpenDriver(name, &refNum);

    if(err == noErr)

        {

        /* Detach the resources from the resource map. */

        DetachResource(theDRVR);

       

        }

theDRVR = GetNamedResource('DRVR', name);

    SetResInfo(theDRVR, DRVRid, nil);

    }

}