template <class T>
struct stkNode
{
BinTreeNode<T> *ptr;
enum tag {R,L}tag;
stkNode(BinTreeNode<T> *N = NULL) : ptr(N),tag(L){}
};
template<class T>
void BinaryTree<T>::PostOrder(void(*visit)(BinTreeNode<T> *p))
{
SeqStack<stkNode<T> > S;
stkNode<T> w;
BinTreeNode<T> *p = root;
do
{
while (p != NULL)
{
w.ptr = p;
w.tag = w.L;
S.Push(w);
p = p->leftChild;
}
bool continuel = true;
while (!S.IsEmpty() && continuel)
{
S.Pop(w);
p = w.ptr;
switch (w.tag)
{
case w.L: //---------------this line--------------------------
w.tag = w.R;
S.Push(w);
continuel = false;
p = p->rightChild;
break;
case w.R: // -----------and this line-------------
visit(p);
break;
}
}
} while (!S.IsEmpty());
}
When i compile it on Devc++, it will be an error looks like:
[Error] '.' cannot appear in a constant-expression.
But when i compile it on Visual Studio 2015,the error will not happen.
Why??????
-----------update my problem--------------------
such as
#include <iostream>
using namespace std;
struct exp
{
char ch;
enum dir{
L,R
}direction;
exp(char name,dir d){
ch = name;
direction = d;
}
};
int main()
{
exp t('a',exp.L); //this line
return 0;
}
it was the same
The problem is that i access method of enum wrongly....
The right Code is:
template<class T>
void BinaryTree<T>::PostOrder(void(*visit)(BinTreeNode<T> *p))
{
SeqStack<stkNode<T> > S;
stkNode<T> w;
BinTreeNode<T> *p = root;
do
{
while (p != NULL)
{
w.ptr = p;
w.tag = w.L;
S.Push(w);
p = p->leftChild;
}
bool continuel = true;
while (!S.IsEmpty() && continuel)
{
S.Pop(w);
p = w.ptr;
switch (w.Tag)
{
case stkNode<T>::L:
w.tag = w.R;
S.Push(w);
continuel = false;
p = p->rightChild;
break;
case stkNode<T>::R:
visit(p);
break;
}
}
} while (!S.IsEmpty());
}
Related
I am getting this error message can anyone help me out.
I am getting the error code 'return' cannot convert from 'clsStack' to 'T' relating the two functions listed below.
Code is as follows
Class
template <class T>
class clsStack //this is the stack class that is used to handle the functions and any data that needs passing between functions
{
private:
clsStack* data;
int iTop;
int iSize;
void resize();
bool needToResize();
string sExpresion;
public:
void stack()
{
iSize = 5;
iTop = 0;
data = new clsStack[iSize];
}
void push(T item);
T peek();
T pop();
bool isEmpty();
};
The two functions I think the issue is related to
template <class T>
T clsStack<T>::peek() //this is used to look at the last number is the array
{
if (iTop <= 0)
throw out_of_range("Attempted to peek an empty stack. \n");
return data[iTop - 1];
}
template <class T>
T clsStack<T>::pop()
{
if (iTop <= 0)
throw out_of_range("Attempted to pop an empty stack. \n");
iTop++;
return data[iTop];
}
The main function where these functions are been called
int evaluate(string sExpresion)
{
clsStack<int> iValues;
clsStack<char> cOperators;
int iValue = 0;
int iPosition = 0;
bool bResult = false;
while (iPosition < sExpresion.length())
{
char cSpot = sExpresion[iPosition];
if (isDigit(cSpot))
{
iValue = (iValue * 10) + (int)(cSpot - '0');
}
else if (isOperator(cSpot))
{
if (cSpot == '(')
{
cOperators.push(cSpot);
iValue = 0;
}
if (cSpot == '-')
{
cOperators.push(cSpot);
iValue = 0;
}
else if (iValues.isEmpty() && cOperators.peek() == '-')
{
int iPrevValue = iValues.pop();
int iPrevOperator = cOperators.pop();
iPrevValue = operation(iValue, iPrevValue, iPrevOperator);
iValues.push(iPrevValue);
cOperators.push(cSpot);
}
else if (iValues.isEmpty())
{
iValues.push(iValue);
cOperators.push(cSpot);
iValue = 0;
}
else if (cSpot == ')')
{
iValues.push(iValue);
while (cOperators.peek() != '(')
{
cSpot = cOperators.pop();
iValue = iValues.pop();
int iPrev = iValues.pop();
iValue = operation(iPrev, iValue, cSpot);
iValues.push(iValue);
}
cOperators.pop();
iValues.pop();
}
else
{
int iPrevValue = iValues.pop();
int iPrevOperator = cOperators.pop();
iPrevValue = operation(iPrevValue, iValue, iPrevOperator);
iValues.push(iPrevValue);
cOperators.push(cSpot);
iValue = 0;
}
}
iPosition++;
}
while (!cOperators.isEmpty())
{
int iPrev = iValues.pop();
char cSpot = cOperators.pop();
iValue = operation(iPrev, iValue, cSpot);
bResult = true;
}
return (sExpresion, iValue, bResult);
}
Any help is much apricated.
As the title says I am trying to implement Set ADT on a Hashtable with independent lists. The thing is I don't know where I'm wrong.
The code I am about to post is taken from a bigger project and I took just the esential parts of it to show you.
SetADT.h:
#pragma once
#pragma once
#include <stdio.h>
#define CAPACITY 10
using namespace std;
template <typename TElement>
class IteratorSet;
template<typename TElement>
class Set {
class Nod {
public:
TElement element;
Nod* next;
};
public:
Set();
void add(TElement element);
int size();
void sterge(TElement element);
bool cauta(TElement element);
friend class IteratorSet<TElement>;
IteratorSet<TElement> iterator() { return IteratorSet<TElement>(this); }
private:
int dimensiune;
typename Set<TElement>::Nod* prim;
int max;
Nod** table;
int hashFunction(TElement element) { return element.hashCode() % max; }
Nod* set;
};
template<typename TElement>
Set<TElement>::Set()
{
max = CAPACITATE;
table = new Nod*[max];
for (int i = 0; i < max; i++)
table[i] = NULL;
}
template <typename TElement>
void Set<TElement>::add(TElement element)
{
int pozitie = hashFunction(element);
Nod* curent = table[pozitie];
while (curent != NULL && !(element == curent->element))
curent = curent->next;
if (curent != NULL)
return;
else
{
Nod* n = new Nod;
n->element = element;
n->next = table[pozitie];
table[pozitie] = n;
}
dimensiune++;
}
template <typename TElement>
int Set<TElement>::size()
{
return dimensiune;
}
template <typename TElement>
void Set<TElement>::sterge(TElement element)
{
int pozitie = hashFunction(element);
Nod* curent = table[pozitie];
if (table[pozitie] == NULL)
return;
if (table[pozitie]->element == element)
{
Nod* deSters = table[pozitie];
table[pozitie] = table[pozitie]->next;
delete deSters;
dimensiune--;
return;
}
Nod* elem = table[pozitie];
while (elem->next != NULL && (elem->next->element) == element)
elem = elem->next;
if (elem->next != NULL)
{
Nod* deSters = elem->next;
elem->next = elem->next->next;
delete deSters;
dimensiune--;
}
}
template <typename TElement>
bool Set<TElement>::cauta(TElement element)
{
int pozitie = hashFunction(element);
Nod* curent = table[pozitie];
while (curent != NULL && !(element == curent->element))
curent = curent->next;
if (curent != NULL)
{
return true;
}
return false;
}
template<typename TElement>
class IteratorSet {
public:
IteratorSet(Set<TElement>* m);
void next();
bool valid();
TElement element();
private:
Set<TElement>* Set;
typename Set<TElement>::Nod* crt;
};
template<typename TElement>
IteratorSet<TElement>::IteratorSet(Set<TElement>* mul) {
Set = mul;
crt = mul->prim;
}
template<typename TElement>
bool IteratorSet<TElement>::valid() {
return crt != NULL;
}
template<typename TElement>
TElement IteratorSet<TElement>::element() {
return crt->element;
}
template<typename TElement>
void IteratorSet<TElement>::next() {
crt = crt->next;
}
=======================================================
domain.h (names of Pizzas)
#include <string>
using namespace std;
class Pizza {
public:
Pizza(string namePizza) : namePizza(namePizza) {}
Pizza() : namePizza("") {}
string getName() const {
return namePizza;
}
int hashCode()
{
int sum = 0;
for (unsigned i = 0; i < str.length(); i++)
sum += str[i];
return sum;
}
bool operator == (Pizza& other) {
return namePizza == other.getName();
}
private:
string namePizza;
string str;
};
====================================================
main.cpp:
#include "SetADT.h"
#include <string>
#include <iostream>
#include "domain.h"
void show(Set<Pizza>* set) {
IteratorSet<string> it = set->iterator();
while (it.valid()) {
cout << "\t" << it.element().getName() << endl;
it.next();
}
}
int main()
{
Set<Pizza> set;
Pizza pizza1{ "diavola" };
Pizza pizza2{ "prosciuto" };
set.add(pizza1);
set.add(pizza2);
show(set);
return 0;
}
When I try to print the objects added to the Set it pops and error and the program stops.
I don't know anywhere else to look to find the problem.
Anyway, if the code sample isn't enough, here the complete project ( has parts of romanian in it )
http://www20.zippyshare.com/v/qKpEcZhr/file.html
The reason might be, for example, prim variable that you use in the iterator, that is initialized to an undefined value. However, code you posted is not compilable, i.e. there are other problems why your code is not working. Did not download your zip file.
I'm developing a container template class. This code needs to interface with existing C code and needs to stay binary compatible, so I can not use i.e. std::vector or similar.
The problem that I have is that it needs to support different allocation strategies, and I don't know how to provide the allocator as a template argument. I created an SSCCE to illustrate how far I got (which of course doesn't compile, because if it would, I wouldn't need to ask this question :)).
#include <iostream>
#include <cstring>
#include <type_traits>
typedef unsigned int uint_t;
typedef signed int int_t;
template <typename T, typename S, typename _allocator = _virtual>
class Container
{
public:
Container(S nItems = 0, S nMaxItems = 0, T *pArray = NULL)
{
mItems = nItems;
mMaxItems = nMaxItems;
mArray = pArray;
}
void adjustMalloc(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T));
mMaxItems += nClusterSize;
}
}
void adjustAligned(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)_aligned_realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), 16);
mMaxItems += nClusterSize;
}
}
void adjustVirtual(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = VirtualAlloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), MEM_RESERVE, PAGE_NOACCESS);
mMaxItems += nClusterSize;
}
}
void adjust(uint_t nClusterSize)
{
if (std::is_same<_allocator>::value == _virtual)
adjustVirtual(nClusterSize);
else if(std::is_same<_allocator>::value == _aligned)
adjustAligned(nClusterSize);
else if(std::is_same<_allocator>::value == _malloc)
adjustMalloc(nClusterSize);
else
{
// Cause a static compiler error, how?
}
}
bool add(T *pItem)
{
if(find(pItem) == NULL)
{
adjust(100);
mItems++;
return true; // added
}
return false;
}
T *find(T *pItem)
{
T *p = mArray;
for(S i = 0; i < mItems; i++, p++)
{
if(*p == *pItem)
return p;
}
return NULL;
}
private:
S mItems;
S mMaxItems;
T *mArray;
};
class Record
{
public:
bool operator==(const Record &oRecord)
{
if(Id != oRecord.Id)
return false;
if(strcmp(Name, oRecord.Name) != 0)
return false;
return true;
}
int Id;
char Name[10+1];
};
int main(int argc, char *argv[])
{
Record rec;
rec.Id = 0;
strcpy(rec.Name, "Test");
Container<Record, uint_t> records; // Default using malloc
records.add(&rec);
if(records.find(&rec) == NULL)
std::cerr << "Not found" << std::endl;
Container<Record, uint_t, _virtual> vrecords; // VirtualAlloc allocator used.
vrecords.add(&rec);
if(records.find(&rec) == NULL)
std::cerr << "Not found" << std::endl;
return 0;
}
I'm using Visual Studio 2010 so it's not 100% C++11.
The VirtualAlloc is provided just as (another) example and will not work as it is shown here.
I found a solution for my problem. However, I get warnings
warning C4127: conditional expression is constant
in the adjust() method for the if(std::is_same... and I was wondering if this is normal or if I can get rid of it, other than disabling it.
#include "stdafx.h"
#include "windows.h"
#include <iostream>
#include <cstring>
#include <type_traits>
#pragma warning (push)
//#pragma warning (disable : 4127)
typedef unsigned int uint_t;
typedef signed int int_t;
typedef struct { const static bool _virtual_allocator = true; } _virtual_type;
typedef struct { const static bool _aligned_allocator = true; } _aligned_type;
typedef struct { const static bool _malloc_allocator = true; } _malloc_type;
template <typename T, typename S, typename _allocator = _aligned_type>
class Container
{
public:
Container(S nItems = 0, S nMaxItems = 0, T *pArray = NULL)
{
mItems = nItems;
mMaxItems = nMaxItems;
mArray = pArray;
}
void adjustMalloc(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T));
mMaxItems += nClusterSize;
}
}
void adjustAligned(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)_aligned_realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), 16);
mMaxItems += nClusterSize;
}
}
void adjustVirtual(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)VirtualAlloc((LPVOID)mArray, (mMaxItems+nClusterSize)*sizeof(T), MEM_RESERVE, PAGE_NOACCESS);
mMaxItems += nClusterSize;
}
}
void adjust(uint_t nClusterSize)
{
if (std::is_same<_allocator, _virtual_type>::value)
adjustVirtual(nClusterSize);
else if(std::is_same<_allocator, _aligned_type>::value)
adjustAligned(nClusterSize);
else if(std::is_same<_allocator, _malloc_type>::value)
adjustMalloc(nClusterSize);
else
{
// Cause a static compiler error, how?
}
}
bool add(T *pItem)
{
if(find(pItem) == NULL)
{
adjust(100);
mItems++;
return true; // added
}
return false;
}
T *find(T *pItem)
{
T *p = mArray;
for(S i = 0; i < mItems; i++, p++)
{
if(*p == *pItem)
return p;
}
return NULL;
}
private:
S mItems;
S mMaxItems;
T *mArray;
};
#pragma warning (pop)
class Record
{
public:
bool operator==(const Record &oRecord)
{
if(Id != oRecord.Id)
return false;
if(strcmp(Name, oRecord.Name) != 0)
return false;
return true;
}
int Id;
char Name[10+1];
};
int main(int argc, char *argv[])
{
Record rec;
rec.Id = 0;
strcpy(rec.Name, "Test");
Container<Record, uint_t> mrecords;
mrecords.add(&rec);
if(mrecords.find(&rec) == NULL)
std::cerr << "Malloc Not found" << std::endl;
Container<Record, uint_t, _aligned_type> arecords;
arecords.add(&rec);
if(arecords.find(&rec) == NULL)
std::cerr << "Aligned Not found" << std::endl;
Container<Record, uint_t, _virtual_type> vrecords;
vrecords.add(&rec);
if(vrecords.find(&rec) == NULL)
std::cerr << "Virtual Not found" << std::endl;
return 0;
}
when I insert a new struct A with the '1' command (so I already have one or more struct A linked to one or more struct S), i lose the link of the previous struct A to their struct S.
For exaple:
command 1 and then command 3 : 2014 and command 4
Output:
year:2014
matricola:1
now command 1 and then command 3 : 2015 and command 4
Output:
year:2015
matricola:2
year:2014
no S struct
I hope that the example will be helpful
Here is the code:
#include <stdio.h>
#include <stdlib.h>
struct S
{
int matr;
struct S* next;
};
struct A
{
int year;
struct A *nextA;
struct S *nextS;
};
int years = 2013;
int matricola=0;
void insA(struct A**T);
void printA(struct A*T);
void insS(struct A **T);
void printS(struct A *T);
int main()
{
struct A *T=NULL;
int cmd,sc=0;
while(1)
{
printf("\n command:");
sc=scanf("%d",&cmd);
while(sc==0)
{
printf("\nerror:");
fflush(stdin);
sc=scanf("%d",&cmd);
}
if(cmd==1)
{
insA(&T);
}
if(cmd==2)
{
printA(T);
}
if(cmd==3)
{
insS(&T);
}
if(cmd==4)
{
printS(T);
}
}
return 0;
}
void insA(struct A**T)
{
struct A *new_p=(struct A*)malloc(sizeof(struct A));
if(new_p==NULL)
{
printf("Errore");
exit(0);
}
years++;
new_p->nextA=NULL;
new_p->nextS=NULL;
if((*T)==NULL)
{
(*T)=new_p;
}
else
{
new_p->nextA=(*T);
(*T)=new_p;
}
new_p->year=years;
}
void printA(struct A *T)
{
struct A *tmp=T;
while(tmp!=NULL)
{
printf("\n%d",tmp->year);
tmp=tmp->nextA;
}
return;
}
void insS(struct A **T)
{
int search,sc=0;
struct S* new_p=(struct S*)malloc(sizeof(struct S));
if(new_p==NULL)
{
printf("error");
exit(0);
}
new_p->next=NULL;
printf("\nyear in which to insert:");
sc=scanf("%4d",&search);
while(sc==0 || search > years || search <= 2013)
{
printf("\nerror:");
fflush(stdin);
sc=scanf("%4d",&search);
}
struct A*tmp=*T;
while(tmp!=NULL)
{
if(tmp->year==search)
{
matricola++;
if(tmp->nextS==NULL)
{
tmp->nextS=new_p;
}
else
{
new_p->next=tmp->nextS;
tmp->nextS=new_p;
}
}
tmp=tmp->nextA;
}
new_p->matr=matricola;
return;
}
void printS(struct A *T)
{
struct A *tmp=T;
struct S *s=tmp->nextS;
while(tmp!=NULL)
{
printf("\nyear:%d",tmp->year);
if(s==NULL)
{
printf("\nno S struct");
return;
}
else
{
while(s!=NULL)
{
printf("\nmatricola:%d",s->matr);
s=s->next;
}
}
tmp=tmp->nextA;
}
}
And this is my first post so I apologize for any errors .
After struggling to understand what you want to do I figured out your problem, you have to change your printS function.
void printS(struct A *T) {
struct A *tmp=T;
truct S *s = tmp->nextS;
while(tmp != NULL) {
printf("\nyear:%d", tmp->year);
if(s == NULL) {
printf("\nno S struct");
return ;
} else {
while(s != NULL) {
printf("\nmatricola:%d",s->matr);
s = s->next;
}
}
tmp = tmp->nextA;
}
}
Like this.
void printS(struct A *T) {
struct A *tmp=T;
while(tmp != NULL) {
struct S *s = tmp->nextS;
printf("\nyear:%d", tmp->year);
if(s == NULL) {
printf("\nno S struct");
return ;
} else {
while(s != NULL) {
printf("\nmatricola:%d",s->matr);
s = s->next;
}
}
tmp = tmp->nextA;
}
}
Because the struct S *s = tmp->nextS; have to be updated to the actual struct A in which you are, so it have to be inside the while loop, if you leave struct S *s = tmp->nextS; outside the while loop you will try to print the list of structs S that starts from your first struct A, and not the entire list of structs S starts from each struct A.
Note: As I said, try to avoid fflush(stdin); because if the argument don't point to an output stream the behavior is undefined.
Thought I'd use an Anderson tree for something. So I started porting to C++ the Julienne Walker version found here: http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_andersson.aspx
Now I have insertions working. But the problem is if I compile with optimisations it crashes. Even -O1 crashes it.
template <class Tv>
class AaTree
{
private:
template <typename Tdata>
struct AaNode
{
AaNode()
{
level = 0;
link[0] = 0L;
link[1] = 0L;
}
~AaNode()
{}
int level;
Tdata data;
AaNode<Tdata>* link[2];
};
AaNode<Tv>* root;
AaNode<Tv>* nil; // sentinel
inline AaNode<Tv>* make_node(Tv data, int level)
{
AaNode<Tv>* rn = new AaNode<Tv>();
rn->data = data;
rn->level = level;
rn->link[0] = rn->link[1] = nil;
}
inline AaNode<Tv>* skew(AaNode<Tv>* t)
{
if (t->link[0]->level == t->level && t->level != 0)
{
AaNode<Tv>* save = t->link[0];
t->link[0] = save->link[1];
save->link[1] = t;
t = save;
}
return t;
}
inline AaNode<Tv>* split(AaNode<Tv>* t)
{
if (t->link[1]->link[1]->level == t->level && t->level != 0)
{
AaNode<Tv>*save = t->link[1];
t->link[1] = save->link[0];
save->link[0] = t;
t = save;
++t->level;
}
return t;
}
AaNode<Tv>* _insert(AaNode<Tv>* root, Tv data)
{
if (root == nil)
root = make_node(data, 1);
else {
AaNode<Tv>* it = root;
AaNode<Tv>* path[64];
int top=0, dir=0;
for (;;)
{
path[top++] = it;
dir = it->data < data;
if (it->link[dir] == nil)
break;
it = it->link[dir];
}
it->link[dir] = make_node(data, 1);
while (--top >= 0)
{
if (top != 0)
dir = path[top - 1]->link[1] == path[top];
path[top] = skew(path[top]);
path[top] = split(path[top]);
if ( top != 0 )
path[top - 1]->link[dir] = path[top];
else
root = path[top];
}
}
return root;
}
void _print(AaNode<Tv>* root)
{
if (root != nil)
{
_print(root->link[0]);
printf("level(%d): %d\n", root->level, root->data);
_print(root->link[1]);
}
}
public:
AaTree()
: root(0L)
{
nil = new AaNode<Tv>();
root = nil;
}
~AaTree()
{}
void Insert(Tv data)
{
root = _insert(root, data);
}
void Delete(Tv data)
{
root = _remove(root, data);
}
void Print()
{
_print(root);
}
};
int main(int argc, char* argv[])
{
AaTree<int> tree;
for (int i = 0; i < 100; i++)
tree.Insert(i);
tree.Print();
return 0;
}
Your make_node function claims to return a value, but contains no return statement.
struct AaNode should not be a template in your case. Try to remove it and see what will happen.
struct AaNode
{
AaNode()
{
level = 0;
link[0] = 0L;
link[1] = 0L;
}
~AaNode()
{}
int level;
Tv data;
AaNode* link[2];
};
But in any case make_node() must return a value. I don't know how you even able to compile this.
Use a proper construction initializer list:
AaNode()
:
level(0),
data(),
link()
{
link[0] = 0L;
link[1] = 0L;
}
Remove the inline keywords from your functions. Inline should be reserved for very small functions (general guideline is one or two lines max), the functions you are attempting to inline are too large and will most likely be more inefficient than calling normally.
Your sentinal value nil should probably be const static. Also it wouldn't hurt to initialize it with some easily recognisable value which may aid in debugging.
In skew() and split() you are not doing any checking to make sure that t is valid or that t's links are valid before dereferencing the pointer.
As others have noted, your make_node does not return the node it creates.
In insert your for loop doesnt check to make sure its not accessing out of bounds memory (> 64th entry of path)