模板新手
Template novice
我正在编写一个程序,该程序涉及使用模板来评估后缀表达式。我不允许以任何方式修改代码;可以说,只填空白(大部分已经填好了,但错误不断出现)。话虽如此:
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",这可能会导致问题。。。
最后,在您的源代码中没有模板专门化,也没有专门化文件。然而,模板专业化确实存在,而且可能不是您所期望的。更多信息请点击此处
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 我是c ++的新手,你能解释一下在这种情况下的指针吗
- 我是 c++ 的新手.学习基本知识后,我想做井字游戏.对于印刷板,我在下面写代码,但它显示错误
- 我是编程新手
- C++新手,想知道如何使用VS code 2019播放音频文件
- C++功能泄漏内存,我是C++新手,不确定如何解决
- 如何正确解析子字符串,以便它们对我的新手计算器有效?
- 我是C++新手,我想知道,为什么在c ++中使用纯虚函数?为什么要使用纯虚函数?
- 结构新手,我对如何从 void 函数中返回值并将其放入另一个函数感到困惑
- 如何在使用 ItemType 的模板类时将新节点插入二叉树 c++.(我是 c++ 的新手)
- 我是 C++ 的新手,我试图调用 make 一个以 2 个类作为其参数的类构造函数
- 作为一个C++新手,我遇到了麻烦
- 如何一步一步地正确解释此代码?(编程新手)
- 什么是"MFC Dialog Extension"?(Windows/C++ 新手 - Linux 背景)
- 我是 c++ 的新手,有没有一种算法可以找到 3d 数组中最接近的 0 的距离?
- C++浮点数与双胞胎设置精度奇数(新手)
- C++新手的类成员函数
- 编码新手需要有关 if 语句的帮助
- 我是 c++ 编程的新手,我一直在做以下任务:
- C++的新手试图弄清楚类约定