Related
I'm a complete newbie at C++. I want to create my own predicate. But the part with bool operator seems to be wrong (at least in my humble opinion). Could someone give me a hint? I don't want to change the overall structure of this idea, I'm just sure I don't understand some details about operator () implementation or something related to classes in c++.
#include <iostream>
#include <vector>
class Predicate
{
private:
int number = 0;
public:
Predicate() = default;
Predicate(const int number)
{
this->number = number;
}
bool operator()(int value) const
{
Predicate *pred = new Predicate();
bool result = pred->operator()(value);
return result;
}
};
class Even : public Predicate
{
bool operator()(int value) const
{
return value % 2 == 0;
}
};
class Negative : public Predicate
{
bool operator()(int value) const
{
return value < 0;
}
};
int count(const std::vector<int> &elements, const Predicate &predicate)
{
int count = 0;
for (int index = 0; index < elements.size(); ++index)
{
if (predicate(elements[index]))
{
++count;
}
}
return count;
}
int main()
{
const std::vector<int> elements{-7, 12, -11, 2, 9, -4, -6, 5, 23, -1};
std::cout << count(elements, Even()) << " " << count(elements, Negative()) << std::endl;
}
What you need is:
define Predicate as an abstract type,
implements different versions of it.
Predicate as an abstract type:
class Predicate {
public:
virtual bool operator(int v) const = 0;
};
Implementing (realising) a given Predicate:
class IsNegative : public Predicate { // means IsNegatives are Predicates
public:
virtual bool operator(int v) const { return v<0; } // realisation of the operator
};
I have a class that contains a tree structure implemented by a vector< vector< Node > > where Node contains a bunch of attributes exposed via getters/setters.
class Tree
{
vector< vector< Node > > mGrid;
printTree(std::ostream& output = std::cout);
};
class Node
{
double property1 { return mProp1; }
double property2 { return mProp2; }
};
printTree() is currently hardwired to use property tstep:
void Tree::printTree( ostream& output )
{
...
for (unsigned t = 0; t < mGrid.size(); ++t)
{
toPrint = "";
for (unsigned state = 0; state < mGrid[t].size(); ++state)
{
toPrint += to_string_with_precision( mGrid[t][state].tstep(), 1 );
...
Is there some slick / convenient / object-oriented way of generalizing this function so that it can print out any of Node's properties (rather than only spitting out the hardwired tstep() property or essentially doing the same thing via if/then statements).
I've done things like this in C using function pointers, but this is C++ and the C++ FAQ says not to mess with pointers to member functions.
You might want template function:
class Tree
{
vector< vector< Node > > mGrid;
public:
template <typename F>
void ForEachNode(F&& f) {
int i = 0;
for (auto& v : mGrid) {
int j = 0;
for (auto& node : v) {
f(node, i, j);
++j;
}
++i;
}
}
};
Then you may do
void printTreeProp1(Tree& tree) {
tree.ForEachNode([](const Node& node, int i, int j) {
if (i != 0 && j == 0) {
std::cout << std::endl;
}
std::cout << node.property1() << " ";
});
}
1st op all you loops are ignoring the first element. vector is zero based and you are using ++t and ++state which increases the values on top of the loop. That means you are never accessing the 0th element (mGrid[0] and mGrid[t][0]).2nd, you did noy include the definition of tstep(), so we don't know what you are getting back. Assuming you want to print each dimension of your 2 dimension array, I think you have to break it to peaces. Something like this:
class Node
{
protected:
double mProp1;
double mProp2;
public:
double GetProp1(void) {return mProp1;}
double GetProp2(void) {return mProp2;}
String tStep(void) {return L"";} // add your code here
};
class NodeRow : public std::vector<Node>
{
public:
void Print(std::ostream& output)
{
iterator i;
String tStr;
for(i = begin(); i != end(); i++)
tStr += /*to_string_with_precision(*/i->tStep()/*, 1)*/;
output << tStr.c_str() << L"\r\n";
}
};
class Node2D : public std::vector<NodeRow>
{
public:
void Print(std::ostream& output = std::cout)
{
iterator i;
for(i = begin(); i != end(); i++)
i->Print(output);
}
};
I need help with a problem pertaining to classes. I know how to solve it but I am wondering if there is a better solution than my current idea.
Each Class Tile Object and Class Player Object has an x and y position. I would like to know if there is a way to expedite things. My current idea is if-else statements like this:
if(x==1) {
if(y==1) {
return tileone1;
} else if(y==2) {
return tileone2;
} else if(y==3) {
return tileone3;
} else if(y==4) {
return tileone4;
} else if(y==5) {
return tileone5;
} //......
} else if(x==2) {
if(y==1) {
return tiletwo1;
} else if(y==2) {
return tiletwo2;
} else if(y==3) {
return tiletwo3;
} else if(y==4) {
return tiletwo4;
} else if(y==5) {
return tiletwo5;
} //......
} //......
The problem is it would take way too long to write this for every tile.
I need a function that will return a Tile object based on the x and y input of the Object Player. Any other solution would be great as well.
Tile getTileBasedOnCoords(int x, int y){
}
There are multiple ways to achieve this. The easiest seems to be (given the question) is by putting all Tile objects into the array, and returning the one with corresponding index.
Use a map with custom keys providing x and y values. This way you have direct access to the tile without the need to compare each tile with the player position (see getSectorByCoordinate() in the following code taken from a project of mine).
struct CSectorCoordinate
{
private:
int mX;
int mY;
public:
CSectorCoordinate();
CSectorCoordinate(int aX, int aY);
bool operator() (const CSectorCoordinate & a, const CSectorCoordinate & b) const;
int getX();
int getY();
};
...
bool CSectorCoordinate::operator() (const CSectorCoordinate & a, const CSectorCoordinate & b) const
{
// note: the following conditions ensure a strict weak ordering (see documentation of std::map)
if (a.mX < b.mX)
return true;
if (b.mX < a.mX)
return false;
return a.mY < b.mY;
}
...
typedef std::map<CSectorCoordinate, Configuration::CSectorEntity *, CSectorCoordinate> CSectorCoordinateMap;
CSectorCoordinateMap mSectorCoordinateMap;
...
bool CSectorEntityConfigurationBunch::getSectorByCoordinate(int aX, int aY, Configuration::CSectorEntity * & prSector)
{
CSectorCoordinateMap::const_iterator i(mSectorCoordinateMap.find(CSectorCoordinate(aX, aY)));
if (i != mSectorCoordinateMap.end())
prSector = i->second;
else
prSector = 0;
return prSector;
}
My question is to find the string in 2d array and if it match display binary no.
Pience of my cide
string inst[37][3]={{"ld","00001","C2"},{"st","00011","C2"},{"la","00101","C2"},{"ldr","00010","C1"},
{"lar","00110","C1"},{"str","00100","C1"},{"add","01100"," "},{"addi","01101","C2"},
{"sub","01110"," "},{"neg","01111"," "},{"or","10110"," "},{"ori","10111","C2"},
{"and","10100"," "},{"andi","10101","C2"},{"not","11000"," "},{"shr","11010","C3"},
{"shra","11011","C3"},{"shl","11100","C3"},{"shc","11101","C3"},{"br","01000","C3"},
{"brl","01001","C3"},{"brlnv","01001"," "},{"brzr","01000"," "},{"brlzr","01001"," "},
{"not","11000"," "},{"brnz","01000"," "},{"brlnz","01001"," "},{"brpl","01000"," "},
{"brmi","01000"," "},{"brlmi","01001"," "},{"nop","00000"," "},{"stop","11111"," "},
{"een","01010"," "},{"edi","01011"," "},{"rfi","11110"," "},{"svi","10000"," "},
{"ri","10001"," "}};
int last=36, initial=0 , mid, index;
for(int i = 0; i < icount-1; i++)
{
//display arrays
for(int j = 0; j < 4;j++)
{
cout << input[i][j] << " ";
// this is for check first column that consist inst and then convert to binary code
if(j==0)
{
while(last>=initial)
{
mid=(last+initial)/2;
if(input[i][0]==inst[mid][0])
{ index=mid;
}
else if(input[i][0]>inst[mid][0])
{ initial=mid+1;
}
else
last=mid-1;
}
cout<<" "<<inst[index][1]<<" ";
}
}
it's like output not display the correct binary code. Any kind of help I'm really appreciated.
Thanks you.
* I don't want to use return mid and create another function
Your search would be soooo much simpler if you reorganized your data:
struct Data_Record
{
string command;
string value;
string other;
// Here's what makes the search work better:
bool operator==(const Data_Record& dr)
{
bool is_equal = false;
if (command == dr.command)
{
if (value == dr.value)
{
if (other == dr.other)
{
is_equal = true;
}
}
}
}
bool operator<(const Data_Record& dr)
{
return command < dr.command;
}
};
const Data_Record inst[37] = { /* ... */};
Data_Record const * p_item_found = NULL;
Data_Record key = {"and", "", ""};
p_item_found = std::binary_search(&inst[0], &inst[38], key);
if (p_item != &instr[38])
{
cout << "Found it\n";
}
else
{
cout << "Item not found.\n";
}
You can do other cool stuff like overloading operator<< and operator>> for custom output and input.
Edit 1: OOP hierarchy
Many instruction sets have groups that share commonality. For example, jump or branch instructions all have a destination address. Math instructions may have the same operands.
I recommend having a hierarchy of classes (or structures). Research "C++ Factory Design Pattern".
class Instruction
{
public:
virtual void Print_Annotated(std::ostream& output) = 0;
virtual void Instruction_Counter Execute(void) = 0;
protected:
std::string opcode;
std::string instruction_value;
};
class Jump_Instr_Category : public Instruction
{
protected:
unsigned int destination_address;
};
class Math_Instr_Category : public Instruction
{
protected:
std::string parameter1;
std::string parameter2;
};
You use the Factory Pattern to return a pointer to the Instruction base class.
The User's program would be a simple as:
std::vector<Instruction *> program;
I've been looking around and haven't come up with any tangible solutions. It sounds like it is looking for a default constructor instead of the one in place but I have one below. Moving it up as the first listed constructor didn't change the error messages so I'm wrong about that. Here's the full error message (using jGRASP):
In file included from intset.h:47:0,
from IntSet.cpp:1:
IntSet.cpp:12:11: error: expected unqualified-id before 'int'
IntSet(int a, int b, int c, int d, int e) {
^
IntSet.cpp:12:11: error: expected ')' before 'int'
Here's the IntSet.cpp code:
#include "intset.h"
//#include <algorithm>
//#include <iostream>
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
//Constructors
IntSet(int a, int b, int c, int d, int e) {
size = a;
if(b > size) {
size = b;
}
if(c > size) {
size = c;
}
if(d > size) {
size = d;
}
if(e > size) {
size = e;
}
set = new bool[size];
for(int i = 0; i <= size; i++) {
if(i == a || i == b || i == c || i == d || i == e) {
insert(i);
} else {
remove(i);
}
}
}
IntSet(int a, int b, int c, int d) {
IntSet(a, b, c, d, -1);
}
IntSet(int a, int b, int c) {
IntSet(a, b, c, -1, -1);
}
IntSet(int a, int b) {
IntSet(a, b, -1, -1, -1);
}
IntSet(int a) {
IntSet(a, -1, -1, -1, -1);
}
//Copy constructor
IntSet(const IntSet& x) {
size = x.size;
for (int i = 0; i <= x.size; i++ ) {
set[i] = x.set[i];
}
}
//Destructor
~IntSet()
{
//for(int i = this.length(); i >= 0; i--) {
// this[i]
//}
}
////////////////////////
bool insert(int a) {
if(a <= size && a >= 0) {
set[a] = true;
return true;
}
else if(a >= 0) {
//removed "new" from line below
IntSet temp = IntSet(a);
&this += temp;
set[a] = true;
return true;
}
return false;
}
bool remove (int a) {
if (isInSet(a)) {
set[a] = false;
return true;
}
return false;
}
bool isEmpty() {
bool retVal = true;
for (int i = 0; i <= size; i++) {
if (set[i] == true) {
retVal = false;
}
}
return retVal;
}
bool isInSet (int a) {
if (set[a]){
return true;
}
return false;
}
/////////////////////////////////////////////
IntSet operator + (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] || a.set[i]){
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator * (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] && a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator - (IntSet a) {
IntSet c = IntSet();
c.size = 0;
for (int i = 0; i <= size; i++) {
if (set[i] && !a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
c.size++;
}
return c;
}
IntSet operator = (const IntSet a) {
return IntSet(a);
}
IntSet operator += (IntSet a) {
return IntSet(operator+(a));
}
IntSet operator *= (IntSet a) {
return IntSet(operator * (a));
}
IntSet operator -= (IntSet a) {
return IntSet(operator - (a));
}
IntSet operator == (const IntSet a) const{
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return false;
}
}
return true;
}
IntSet operator != (IntSet a) {
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return true;
}
}
return false;
}
IntSet operator << (IntSet a) {
cout << "{";
for(int i = 0; i < size; i++) {
if(set[i]) {
cout << " " << i;
}
}
cout << "}";
}
IntSet operator >> (IntSet a) {
int index;
while(cin >> index && index != SENTINEL) {
insert(index);
}
}
Here is the attached intset.h code:
#ifndef INTSET_H
#define INTSET_H
#include <iostream>
#include <algorithm>
using namespace std;
class IntSet {
public:
//Constructors
IntSet();
IntSet(int);
IntSet(int, int);
IntSet(int, int, int);
IntSet(int, int, int, int);
IntSet(int, int, int, int, int);
IntSet(const IntSet&); // M: Added the &; must be a pointer or reference
~IntSet();
//Overloaded Operators M: Added 'IntSet' in front of the word 'operator.'
// It was required syntax.
IntSet operator+(IntSet);
IntSet operator*(IntSet);
IntSet operator-(IntSet);
IntSet operator=(IntSet);
IntSet operator+=(IntSet);
IntSet operator*=(IntSet);
IntSet operator-=(IntSet);
IntSet operator==(IntSet);
IntSet operator!=(IntSet);
IntSet operator<<(IntSet);
IntSet operator>>(IntSet);
//Functions
bool insert(int);
bool remove(int);
bool isEmpty();
bool isInSet(int);
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
#include "IntSet.cpp"
#endif
I haven't had much experience with header files so it wouldn't surprise me if I formatted something incorrectly but I'm looking at plenty of other samples provided by the professor and there isn't anything unusual about mine. I thought maybe it had something to do with the order listed in the .h file and that I wasn't following the same exact order in the .cpp but nothing changed when I had everything listed in the same order.
There is a lot that is wrong with your code. We are going to have to jump around a bit between the header and the implementation. Ready?
In your header you do this:
class IntSet {
/* stuff */
private:
bool set[];
};
First of all, the name set is a bad choice: it is the name of a class in namespace stdw which you are importing by having using namespace std in your header file. This can be confusing at best.
More importantly, the syntax bool set[] isn't correct in this context. Even if your compiler allows it, it's an extension. Who knows what it does and how it will behave on other compilers? Avoid it.
If you want to declare an array, declare an array. If you want to declare a pointer, declare a pointer. Just remember: an array isn't a pointer.
Unfortunately you don't, becase later on in your code you do this:
set = new bool[size];
What is this supposed to do? set isn't a pointer, it's some kind of array, and you cannot assign a pointer to an array.
Now, we get to the second problem: you declare some member variables for your class, in your header file:
class IntSet {
/* some stuff here */
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
Then in your implementation you have the following code floating up at the top:
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
I don't think that this does what you think it does. It seems that your intention is to initialize those variables, but that's not what happens. Remember, those variables only exist as members variables that belong to a particular instance of a class, and they are not "free-standing". So what's happening here?
Well, this declares all these variables again, so you have variables called MAXSIZE, size, set and SENTINEL that are valid anywhere in that translation unit (i.e. the .cpp file), independent of the member variables in the class.
This, of course, means that the member variables with those names aren't initialized (well, except set which you assign a pointer to, which we already know is wrong). This will cause your code to exhibit undefined behavior. After all, the value of an uninitialized variable can be anything at all.
If your intention had been to initialize the class members, then you should remove that code and initialize those variables in your constructor(s):
IntSet::IntSet(int a, int b, int c, int d, int e)
: size(a), MAXSIZE(25000), SENTINEL(-1)
{
/* whatever*/
}
Notice, by the way, how I used IntSet:: in front of the constructor name? This is called the scope resolution operator. Remember, there is no constructor called IntSet. The constructor belongs to a class, which is called IntSet, and outside of that class, it's proper name is IntSet::IntSet. A small example may help:
class Test
{
int Length;
public:
/* notice how inside the class, you only need Test
* when providing a body for the constructor. This
* makes sense. You know which class you inside of.
*/
Test()
: Length(0)
{
}
Test(int len);
};
/* Now we are outside the class. We need to help
* the compiler out and tell it what class the
* function belongs to.
*/
Test::Test(int len)
: Length(len)
{
}
A tangential point as to do with the names that you are using. What's a? Why do you use a to initialize something called size? You should choose meaningful variables names that help document the code so that when you have to read it back your head doesn't explode.
Another tangential point is that if variables like MAXSIZE and SENTINEL are going to be shared between all instances of the class, then, for future reference, you should probably consider making them static class members.
Lastly, you have this bit of code in your header file
#include "IntSet.cpp"
This is, almost certainly, not correct. You should never do this (there may be some who think that there are exceptions, but don't learn bad habits at this point. When you know enough to stumble on this legitimately, then you will know enough to determine whether it's the right thing to do or not).
What makes it worse is that your implementation file contains:
#include "IntSet.h"
Think about what you are doing here: when the compiler is processing the file IntSet.h you are telling to also process the file IntSet.cpp. The file IntSet.cpp tells the compiler to process the file IntSet.h. Which tells the compiler to process the file IntSet.cpp. And so on and so forth.
Generally speaking, implementation files (.cpp) will include header files. Header files will only include other header files.
There are a few other issues, but you should probably fix all these things, and then, if you are still having issues, post a new question and we can go from there.
Good luck!
You need to put the name of the class and :: before defining a member function.
IntSet::IntSet(int a, int b, int c, int d, int e) {
//^^^^^^^^
//here
Do the same with the other constructors, the operators and methods.