// 1.2: funzioni template
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
template<class T> T *arraycopy(unsigned int dsize, T *src, unsigned int ssize) {
unsigned int largest = dsize > ssize ? ssize : dsize;
T *p;
if(!dsize)
return NULL;
//cout << "size " << dsize << ", source " << ssize << ", largest " << largest << endl;
p = new T[dsize + 1];
for(int i = 0; i < largest; ++i) {
// cout << "p[" << i << "] = src[" << i << "]\n";
p[i] = src[i];
}
return p;
}
class StackException {
private:
const char *err;
public:
// Metodi pubblici
const char *get_err() { return err; };
// Costruttori e distruttore
StackException(const char *p)
: err(p) { }
};
template<class T>class Stack {
private:
// Membri privati
T *v;
unsigned int vsize;
// Metodi privati
void deallocate() {
if(v) {
cout << "v era " << v << endl;
delete v;
v = NULL;
}
}
public:
// Metodi pubblici
// Push
void push(const T &n) {
v = arraycopy(vsize + 1, v, vsize);
v[vsize] = n;
vsize++;
}
// Pop
T pop() {
if(!vsize)
throw StackException("stack underflow");
T r(v[vsize - 1]); // copia l'oggetto prima della distruzione
v = arraycopy(vsize - 1, v, vsize);
vsize--;
return r;
}
// Size
unsigned int size() {
return vsize;
}
// Operatori
const Stack &operator=(const Stack ©) {
if(© == this)
return *this;
deallocate();
vsize = copy.vsize;
v = arraycopy(copy.vsize, copy.v, copy.vsize);
}
T &operator[](unsigned int i) {
if(i >= vsize)
throw StackException("index out of range");
return v[i];
}
// Costruttori e distruttore
Stack()
: v(NULL), vsize(0) { }
Stack(const Stack<T> ©)
: vsize(copy.vsize) {
v = arraycopy(copy.vsize, copy.v, copy.vsize);
}
~Stack() {
deallocate();
}
};
void showcmd() { }
int main() {
Stack< Stack<int> > stackarray; // Stack di stack di interi
bool done(false); // booleano per uscire dal while principale
char line[256]; // buffer per contenere l'input
char *cmd, *arg; // puntatori per memorizzare il comando e l'argomento
unsigned int s(0); // intero che selezione lo stack che stiamo usando in stackarray
cout << "Welcome to Stack example\nType help to get some help, quit to quit\n\n";
while(!done) {
try {
cout << "Stack: > ";
cin.getline(line, 256);
cmd = line;
if(arg = strchr(line, ' ')) {
*arg = '\0';
++arg;
}
// cout << "Command: *" << cmd << "*, arg *" << arg << "*\n";
if(!strcmp(cmd, "quit")) { // quit!
done = true;
} else if (!strcmp(cmd, "help")) {
showcmd();
} else if (!strcmp(cmd, "create")) {
stackarray.push(Stack<int>());
} else if (!strcmp(cmd, "destroy")) {
stackarray.pop();
} else if (!strcmp(cmd, "show")) {
for(int i = 0; i < stackarray.size(); ++i) {
cout << "> Stack " << (s == i ? "<*>" : "") << i << " (" << stackarray[i].size() << " elements) { ";
for(int j = 0; j < stackarray[i].size(); ++j)
cout << stackarray[i][j] << (j != stackarray[i].size() - 1 ? ", " : " ");
cout << "}" << endl;
}
} else if (!strcmp(cmd, "push")) {
if(!arg)
cerr << "Error: push command requires an argument" << endl;
else {
cout << "> Invoking PUSH on current stack " << s << " with argument " << atoi(arg) << endl;
stackarray[s].push(atoi(arg));
}
} else if (!strcmp(cmd, "pop")) {
cout << "> Invoking POP on current stack " << s << endl;
stackarray[s].pop();
} else if (!strcmp(cmd, "select")) {
if(!arg)
cerr << "Error: select command requires an argument" << endl;
else {
cout << "> Selecting " << atoi(arg) << " stack\n";
s = atoi(arg);
stackarray[s].size(); // Prova l'accesso al metodo size per vedere se abbiamo un indice corretto
}
} else if (!*cmd)
continue;
else {
cerr << "Error: unknown command " << cmd << endl;
}
} catch(StackException e) {
cerr << "Error: Exception catch'd: " << e.get_err() << endl;
cerr << "Error: recovery from error, selecting stack 0" << endl;
s = 0;
}
}
}