<< "P to process a PO, or Q to quit.\n";

    while (cin >> ch && std::toupper(ch) != 'Q')

    {

        while (cin.get() != '\n')

            continue;

        if (!std::isalpha(ch))

        {

            cout << '\a';

            continue;

        }

        switch(ch)

        {

            case 'A':

            case 'a': cout << "Enter a PO number to add: ";

                      cin >> po;

                      if (st.isfull())

                          cout << "stack already full\n";

                      else

                          st.push(po);

                      break;

            case 'P':

            case 'p': if (st.isempty())

                          cout << "stack already empty\n";

                      else {

                          st.pop(po);

                          cout << "PO #" << po << " popped\n";

                          break;

                      }

        }

        cout << "Please enter A to add a purchase order,\n"

             << "P to process a PO, or Q to quit.\n";

    }

    cout << "Bye\n";

    return 0;

}

Here’s a sample run of the program in Listing 14.14:

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

A

Enter a PO number to add: red911porsche

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

A

Enter a PO number to add: blueR8audi

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

A

Enter a PO number to add: silver747boeing

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

P

PO #silver747boeing popped

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

P

PO #blueR8audi popped

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

P

PO #red911porsche popped

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

P

stack already empty

Please enter A to add a purchase order,

P to process a PO, or Q to quit.

Q

Bye

A Closer Look at the Template Class

You can use a built-in type or a class object as the type for the Stack class template. What about a pointer? For example, can you use a pointer to a char instead of a string object in Listing 14.14? After all, such pointers are the built-in way for handling C-style strings. The answer is that you can create a stack of pointers, but it won’t work very well without major modifications in the program. The compiler can create the class, but it’s your task to see that it’s used sensibly. Let’s see why such a stack of pointers doesn’t work very well with Listing 14.14, and then let’s look at an example where a stack of pointers is useful.

Using a Stack of Pointers Incorrectly

Let’s quickly look at three simple, but flawed, attempts to adapt Listing 14.14 to use a stack of pointers. These attempts illustrate the lesson that you should keep the design of a template in mind and not just use it blindly. All three examples begin with this perfectly valid invocation of the Stack template:

Stack st; // create a stack for pointers-to-char

Version 1 then replaces

string po;

in listing 14.14 with

char * po;

The idea is to use a char pointer instead of a string object to receive the keyboard input. This approach fails immediately because merely creating a pointer doesn’t create space to hold the input strings. (The program would compile, but it would quite possibly crash after cin tried to store input in some inappropriate location.)

Version 2 replaces

string po;

with

char po[40];

This allocates space for an input string. Furthermore, po is of type char *, so it can be placed on the stack. But an array is fundamentally at odds with the assumptions made for the pop() method:

template

bool Stack::pop(Type & item)

{

    if (top > 0)

    {

        item = items[--top];

        return true;

    }

    else

        return false;

}

First, the reference variable item has to refer to an lvalue of some sort, not to an array name. Second, the code assumes that you can assign to item. Even if item could refer to an array, you can’t assign to an array name. So this approach fails, too.

Version 3 replaces

string po;

with

char * po = new char[40];

This allocates space for an input string. Furthermore, po is a variable and hence compatible with the code for pop(). Here, however, you come up against the most fundamental problem: There is only one po variable, and it always points to the same memory location. True, the contents of the memory change each time a new string is read, but every push operation puts exactly the same address onto the stack. So when you pop the stack, you always get the same address back, and it always refers to the last string read into memory. In particular, the stack is not storing each new string separately as it comes in, and it serves no useful purpose.

Using a Stack of Pointers Correctly

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги