C++类模板
待更!
egg1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | // // stacktp.hpp // // Created by Min Zhu on 16/10/6. // Copyright © 2016年 Min Zhu. All rights reserved. // #ifndef stacktp_hpp #define stacktp_hpp #include <stdio.h> template < class Type> class Stack { private : enum {MAX = 10}; // constant specific to class Type items[MAX]; // holds stack items int top; // index for top stack item public : Stack(); bool isempty(); bool isfull(); bool push( const Type & item); // add item to satck bool pop(Type & item); // pop top into item }; template < class Type> Stack<Type>::Stack() { top = 0; }; template < class Type> bool Stack<Type>::isempty(){ return top == 0; } template < class Type> bool Stack<Type>::isfull(){ return top == MAX; }; template < class Type> bool Stack<Type>::push( const Type & item){ if (top < MAX){ items[top++] = item; return true ; } else return false ; } template < class Type> bool Stack<Type>::pop(Type & item){ if (top > 0){ item = items[--top]; return true ; } else return false ; } #endif /* stacktp_hpp */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | // // stacktp.cpp // // Created by Min Zhu on 16/10/6. // Copyright © 2016年 Min Zhu. All rights reserved. // #include "stacktp.hpp" #include <iostream> #include <string> #include <cctype> using namespace std; int main(){ Stack<string> st; // create an empty stack char ch; string po; cout << "Please enter A to add apurchase order,\n" << "P to process a PO, or Q to quit.\n" ; while (cin >> ch && toupper (ch) != 'Q' ){ while (cin.get() != '\n' ) continue ; if (! 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; } |
运行结果(Xcode):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | Please enter A to add apurchase 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 Program ended with exit code: 0 |
深入探讨模板类
可以使用char指针替换上面程序中的string对象吗?毕竟,这种指针是处理c风格字符串的内置方式。答案是可以创建指针栈,不过必须对程序包进行重大修改。
1.不正确地使用指针栈
设计模板时应牢记一些教训,切忌盲目使用模板。以下列举3个试图对上面程序eg1进行修改,使之使用指针栈的简单(但有缺陷的)示例。它们都以完全正确的Stack<Type>模板为基础:Stack<char *> st;
版本1,将eg1中的string po;替换为char * po;
目的是用char指针而不是string对象来接收键盘输入。这种方法是失败的:因为仅仅创建指针而没有创建用于保存输入字符串的空间(程序将通过编译,但在cin试图将输入保存在某些不合适的内存单元中时崩溃)
版本2,将string po;替换为char po[40];
这为输入的字符串分配了空间。另外,po的类型为char *,因此可以放在栈中,不过数组与pop()方法的假设相冲突:
1 2 3 4 5 6 7 8 9 | template < class Type> bool Stack<Type>::pop(Type & item){ if (top > 0){ item = items[--top]; return true ; } else return false ; } |
首先,引用变量必须引用某种类型的左值,而不是数组名。其次,代码假设可以给item赋值,即使item能够引用数组,也不能为数组名赋值。故此法失效。
版本3,将string po;替换为char * po = new char[40];
这为输入的字符串分配了空间。另外,po的类型为变量,因此与pop()的代码兼容。然而问题是:只有一个pop变量,它总是指向相同的内存单元。在每当读取新字符串时,内存的内容都将发生改变,而每次执行压入操作时,加入到栈中的地址都相同。则对栈执行弹出操作时,得到的地址总是相同的,它总是指向读入的最后一个字符串。具体就是栈并未保存每一个新字符串,因而没有什么用途。
2.正确地使用指针栈
使用指针栈的方法之一是,让调用程序提供一个指针数组,其中每个指针指向不同的字符串。栈的任务是管理指针,而不是创建指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | //stcktp1.h -- modified Stack template #ifndef STCKTP1_H_ #define STCKTP1_H_ template < class Type> class Stack{ private : enum {SIZE = 10}; int stacksize; Type * items; int top; public : explicit Stack( int ss = SIZE); Stack( const Stack & st); ~Stack(){ delete [] items; } bool isempty(){ return top == 0; } bool isfull(){ return top == stacksize; } bool push( const Type & item); // add item to stack bool pop(Type & item); // pop top into item Stack & operator=( const Stack & st); }; template < class Type> Stack<Type>::Stack( int ss) :stacksize(ss), top(0){ items = new Type [stacksize]; } template < class Type> Stack<Type>::Stack( const Stack & st){ stacksize = st.stacksize; top = st.top; items = new Type [stacksize]; for ( int i = 0; i < top; i++){ items[i] = st.items[i]; } } template < class Type> bool Stack<Type>::push( const Type & item){ if (top < stacksize){ items[top++] = item; return true ; } else return false ; } template < class Type> bool Stack<Type>::pop(Type & item){ if (top > 0){ item = items[--top]; return true ; } else return false ; } template < class Type> Stack<Type> & Stack<Type>::operator=( const Stack<Type> & st){ if ( this == &st) return * this ; delete [] items; stacksize = st.stacksize; top = st.top; items = new Type [stacksize]; for ( int i = 0;i< top; i++) { items[i] = st.items[i]; } return * this ; } #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <iostream> #include <cstdlib> // for rand().srand() #include <ctime> // for time() #include "stcktp1.h" using namespace std; const int Num = 10; int main(){ srand ( time (0)); //randomize rand() cout << "Please enter stack size:" ; int stacksize; cin >> stacksize; //create an empty stack with stacksize slots Stack< const char *> st(stacksize); //in basket const char * in[Num] = { " 1: Hank Gilgamesh" , " 2: Kiki Ishatar" , " 3: Betty Rocker" , " 4: Ian Flagrant" , " 5: Wolfgang Kibble" , " 6: Portia koop" , " 7: Joy Almondo" , " 8: Xaverie Paprika" , " 9: Juan Moore" , "10: Misha Mache" }; //out basket const char * out[Num]; int processed = 0; int nextin = 0; while (processed < Num){ if (st.isempty()) st.push(in[nextin++]); else if (st.isfull()) st.pop(out[processed++]); else if ( rand () % 2 && nextin < Num) st.push(in[nextin++]); else st.pop(out[processed++]); } for ( int i = 0; i < Num; i++){ cout << out[i] << endl; } cout << "Bye\n" ; return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2015-10-05 leetcode:Search a 2D Matrix(数组,二分查找)
2015-10-05 实时操作系统与分时操作系统
2015-10-05 区别:并发与并行