模板新手

Template novice

本文关键字:新手      更新时间:2023-10-16

我正在编写一个程序,该程序涉及使用模板来评估后缀表达式。我不允许以任何方式修改代码;可以说,只填空白(大部分已经填好了,但错误不断出现)。话虽如此:

1) 模板头、模板专用化和主程序文件都是独立的。如何在主程序中实现模板?我已经在头文件末尾使用#include作为专业化的替代。

2) 固定

3) 在专用化文件中,我需要使用命名空间std使用上面的#include"templateheader.h",还是只将template放在每个函数之上?我将在下面发布一个我现在拥有的示例。

两个星号标出了我们必须填空的地方。如果它只是一条线的一部分,那么它的每一边都有一颗星。

堆叠类型.h

#pragma once**
//   Catherine Stringfellow and Trey Brumley
//   A Stack is a ???**
//   Class specification for Stack ADT in file StackType.h
using namespace std;
static const int MAXITEMS = 50;
template <class stack>**
class StackType
{
  public:
    // Class constructors
    StackType();
    StackType (const StackType & other);
    void makeEmpty();
    // Function:  Sets stack to an empty state.
    // Post: Stack is empty.
    bool isFull() const;
    // Function: Determines whether the stack is full.
    // Pre:  Stack has been initialized.
    // Post: Function value = (stack is full)
    bool isEmpty() const;
    // Function: Determines whether the stack is empty.
    // Pre:  Stack has been initialized.
    // Post: Function value = (stack is empty)
    void push(*stack* item);
    // Function: Adds newItem to the top of the stack.
    // Pre:  Stack has been initialized.
    // Post: If (stack is full), PushOnFullStack exception is thrown;
    //       otherwise, newItem is at the top of the stack.
    void pop(*stack* & item);
    // Function: Removes top item from the stack and returns it in item.
    // Pre:  Stack has been initialized.
    // Post: If (stack is empty), PopOnEmptyStack exception is thrown;
    //       otherwise, top element has been removed from stack.
    //       item is a cop of the removed item.
    int getStackNum ();
    //Function: returns the number of items in the stack
    //Pre: Stack has been initialized
    //Post: Returns the number of items in the stack
private:
    int top;
    stack items[MAXITEMS];  //statically allocated array
};
#include "stackType.cpp";**

stackType.cpp

// Catherine Stringfellow and Trey Brumley
// File: StackType.cpp
// Templated member function implementations for class StackType. 
// This is the statically allocated array-based stack.
#include "stack"**
using namespace std;
template <class stack>**
StackType *StackType<stack>*::StackType()
{
  top = -1;
}
template <class stack>**
StackType *StackType<stack>*::StackType (const StackType & other)
{
  top = other.top;
  for (int i=0; i < top; i++)
      items[i] = other.items[i];
}
template <class stack>**
StackType*<stack>*::makeEmpty()
{
  top = -1;
}
template <class stack>**
*bool StackType<stack>*::isEmpty() const
{
  return (top == -1);
}
template <class stack>**
bool StackType*<stack>*::isFull() const
{
  return (top == MAXITEMS-1);
}
template <class stack>**
StackType*<stack>*::push(StackType newItem)
{
  if( !isFull() )
  {
    top++;
    items[top] = newItem;
  }
}
template <class stack>**
StackType*<stack>*::pop( & item)
{
  if( !isEmpty() )
  {
    item = items[top];
    top--;
  }
}
template <class stack>**
int StackType*<stack>*::getStackNum ()
{
   return top+1;  
}

/*  Erik Malone and Catherine Stringfellow and Trey Brumley                 Date: December-5-2013
    File: prog5.cpp
    Program Specifications
       Narrative:   Program that evaluates and converts postfix expressions.
       Interface:
          Introductory Screen:
               "Postfix Calculator and Converter"
          Exit Screen:
               "Goodbye..."
          Input: 
                numbers in expressions should be separated by a space.
                (from keyboard, see attached)
          Output: 
                (all to screen, see attached)   
       Constants: 
          STACK_MAX
*/
#include "stack"**
#include <string>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstdlib>
#include <cctype>
int getValidChoice ();
/* purpose: get valid option choice from menu
   prereq: NONE
   postcond: int (for a valid choice returned)
*/
void readString(string& s);
/* purpose: Reads a line into a string
   recieves: string <s>
   returns: NONE
*/
void printString(const string& s);
/* purpose: Prints a string
   recieves: const string <s>
   returns: NONE
*/
void convertPostfix(string& post, string& result);
/* purpose: converts a prefix expression to infix
   recieves: string <post>, string <result>
   returns: NONE
*/
void convert(StackType & s, char ch);
/* purpose: pops two operands off a string stack and pushes the result
   recieves: string <post>, char <ch>
   returns: NONE
*/
void evalPostfix(string& post, double& answer);
/* purpose: calculates the value of the prefix expression
   recieves: string <post>, double <answer>
   returns: NONE
*/
void evaluate(StackType & s, char ch);
/* purpose: pops two operands off a double stack and pushes the result
   recieves: Stack <s>, char <ch>
   returns: NONE
*/
void error(int m);
//prints an error message, based on int parametet
//print the introduction and exit screens
void intro();
void outro();
void main()
{                   
    string post;
    double answer;
    int choice;
    //intro screen  
    intro();
    //while user wants to continue
    choice = getValidChoice();
    while (choice != 3) {
        //switch menu options
       switch (choice)                          
        {
        case 1: 
            cout<<"Please enter a postfix expression: ";
            readString(post);
            if (post == "")                             //error if string empty 
                error(1);
            else
            {
                evalPostfix(post, answer);
                printString(post);
                cout<<" = "<<answer<< endl << endl;
            }
            break;
        case 2:
            cout<<"Please enter a postfix expression: ";
            readString(post);
            if (post == "")
                error(1);
            else
            {   string tempString = "";
                convertPostfix(post, tempString);
                cout<<"Postfix expression: ";
                printString(post);
                cout<<"nEpression converted to infix: "<<tempString << endl<<endl;
            }
            break;
            default:    //if choice is not recognized print error
              error(3);
      } //end switch
       choice = getValidChoice();
    } //end while
    outro();    
    //exit screen on return
    system("pause");
}
int getValidChoice ()
{                                                       
    int choice;
    //display menu options
    cout<<" Options                               n";
    cout<< "  (1) Evaluate postfix expression  " << endl;
    cout<< "  (2) Convert postfix to infix   " << endl;
    cout<< "  (3) Quit      " << endl;
    //get menu option
    cout<<"Enter option: ";
    cin>>choice;
    cout <<endl;
    //validate menu option
    while ((choice < 1) || (choice > 3)) {
        cout << "Enter a value between 1 and 3: ";
        cin >> choice;
    }
    return choice;
}
void printString(const string& s)
{
    if (s.empty()) 
        cout<<"Empty";                                  //if string is empty print "empty"
    else
        cout<<s;
}
void readString(string& s)
{
    char temp[40];
    cin.ignore(80,'n');                                //clear buffer
    cin.getline(temp, 40);                              //copy line to string
    s = temp;
}
void evalPostfix(string& post, double& answer)
{
    int index = 0, total = 0;                   
    double tempDbl;
    bool negative = false;              //to detect negative signs
    StackType s;                        //declare a stack of doubles 
    //loop index until end of string
    while (index < (int) post.length())                     
    {
        //pass over spaces in string
        while (isspace(post[index]))                    
            index++ ;   
        //if operator evaluate incrementing index
        if (!isdigit(post[index]) && 
            !((index+1 < (int) post.length()) && 
              (post[index] == '-' && isdigit(post[index+1]))))
        //if (!isdigit(post[index]))
            evaluate(s, post[index++]);                 
        else
        {   //if number, checks for negative sign
            if (post[index] == '-')                     
            {
                index++;
                negative = true;
            }
            //add up the digits from string
            while ((post[index] >= '0') && (post[index] <= '9'))
                total = (total * 10) + (post[index++] - '0');
            //if there was a negative sign, negate total
            if (negative)                               
            {
                total = total * -1;
                negative = false;
            }
            //push number onto stack
            s.push(total);                              
            total = 0;  
        }
        index++;
    }
    //pop answer from stack
    s.pop(tempDbl);                                     
    answer = tempDbl;
}
void evaluate(StackType  & s, char ch)
{
    double op1, op2;                                    
    //check if empty before popping operands
    if (!s.isEmpty())                                   
    {
        s.pop(op2);
        if (!s.isEmpty())
        {
            s.pop(op1);
            //push result
            switch(ch)                                  
            {
            case '+':
                s.push(op1 + op2);                      
                break;
            case '-':
                s.push(op1 - op2);
                break;
            case '*':
                s.push(op1 * op2);
                break;
            case '/':
                s.push(op1 / op2);
                break;
            default:
                return;
            }
        }
    }
}
void convertPostfix(string& post, string& result)
{
    int index = 0;
    string tempString;
    StackType s;  //declare a stack of strings
    //loop index until end of string
    while (index < (int) post.length())                     
    {
        //pass over spaces in string
        if (isspace(post[index]))                       
            index++ ;   
        //if operator convert incrementing index
        if (!isdigit(post[index]) && 
            !((index+1 < (int) post.length()) && 
              (post[index] == '-' && isdigit(post[index+1]))))
        //if (!isdigit(post[index]))
            convert(s, post[index++]);                  
        else
        {
            //clear string
            tempString.erase();                         
            //concatenate numbers to string
            while (!isspace(post[index]))               
                tempString = tempString + post[index++];
            //push string onto stack
            s.push(tempString);                         
        }
        index++;
    }
    //pop resulting string from stack
    s.pop(result);                                      
}
void convert(StackType  & s, char ch)
{
    string op1, op2, tempString;
    //check if empty before popping
    if (!s.isEmpty())                                   
    {
        s.pop(op2);
        if (!s.isEmpty())
        {
            s.pop(op1);
            //constructing string for result
            tempString = tempString + "( ";             
            tempString = tempString + op1;              
            //concatenate sign to string
            switch(ch)                                  
            {
            case '+':   
                tempString = tempString + " + ";        
                break;
            case '-':
                tempString = tempString + " - ";
                break;
            case '*':
                tempString = tempString + " * ";
                break;
            case '/':
                tempString = tempString + " / ";
                break;
            default:
                return;
            }
            //adding rest of the string
            tempString = tempString + op2;              
            tempString = tempString + " )";
            //push resulting string onto stack
            s.push(tempString);                         
        }
    }
}
void error(int m)
{
    system("cls");          //clear screen
    cout<<"a";             //system beep
    //displays error message according to parameter passed
    switch (m)                                          
    {
    case -1:
        cout<<"INTERNAL ERROR";
        break;
    case 1:
        cout<<"ERROR - Postfix expression empty.";
        break;
    case 3:
        cout<<"ERROR - invalid entry."; 
        break;
    default:
        cout <<"UNKNOWN ERROR.";
    }
    cout << endl << endl;
}
void intro()
{
    system("cls");                                      //clear screen
    //displays welcome message
    cout<<"Postfix Calculator and Converternn";
}
void outro()
{
    cout<<"Goodbye...nn";                             //display exit message
}

对于2),它必须是std::string,或者你可以说

using std::string;

using namespace std;

然后你就可以说字符串了。我推荐前者,除非你从std::中提取了很多东西

其他琐事:

  • 将头文件命名为"stack.h"
  • 您不需要stack.cpp,只需实现stack.h中的函数,例如

    模板类堆栈{…。void doSomething(ElementType&object){…}…。};

这往往更干净。你也可以不按行操作,但它仍然需要在同一个文件中,如果你不按行执行,你需要在每个函数前面加上模板关键字

  • 您可能希望为模板参数选择一个比"stack"更具描述性的名称

您应该将类的名称与模板参数的名称进行切换,这样会更有意义。这将成为

template <typename StackType>
class Stack 
{
...
};

例如

void push(stack item);

将是

void push(StackType item);

1) 您可以将方法的声明和定义放在单独的文件中,但您需要像以前一样在末尾包含它们,但我建议您将stack.cpp重命名为stack.inl(.inl表示内联)或其他名称。

3) 如果你使用两个像上面一样的文件,就不需要在stack.cpp/inl中包含stack.h。使用名称空间std要小心,因为包含stack.h的每个人都将"使用名称空间std",这可能会导致问题。。。

最后,在您的源代码中没有模板专门化,也没有专门化文件。然而,模板专业化确实存在,而且可能不是您所期望的。更多信息请点击此处