What is the difference between int x_ and int x in C++ - c++

class Stack{
public:
char data_[100];
int top_;
};
class Stack{
public:
char data[100];
int top;
};
What is the difference between the above two classes ? When I am using the class where the variable names are like int top_ ,the stack operations are running fine but when I am using the class with variables int top, errors like this are popping up :
error: invalid use of member ( did you forget the '&' ?)
error: conflicts with previous declaration.
What is the role of the _(underscore) in this code ? Why is it making such a difference ?
#include<iostream>
#include<cstring>
using namespace std;
class Stack{
public:
char data[100];
int top;
bool empty()
{
return (top == -1);
}
char top()
{
return (data[top]);
}
void pop()
{
top--;
}
void push(char c)
{
data[++top] = c;
}
};
int main()
{
Stack s;
s.top = -1;
char str[10] = "ABCDEFGH";
for(int i=0;i<strlen(str);i++)
s.push(str[i]);
cout<<str<<endl;
cout<<"Reversed string is : ";
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
}

What is the role of the _(underscore) in this code ?
It makes top and top_ 2 different identifiers. The same way you can make it top1 or topFOOBAR.
Why is it making such a difference ?
When you use top for member here you have a conflict with method named top as well. Changing top to top_ or top1 would make that conflict to disappear - you cannot have 2 different things in your class with the same name.
Some people have a habit to give member variables special names, like m_member or member_ or even _member (last one is not safe but still used sometimes). This decoration allows reader to see that code is dealing with member var on one side and avoiding name collisions like one you had on another.

Related

Transfer values from one stack to another keeping the same order in C++

#include <iostream>
#include<stdlib.h>
#include <stack>
using namespace std;
const int MAX = 1000;
class Stack
{
int top=-1;
int arr[MAX];
public:
void push(int value)
{
if (top > MAX - 1)
cout << "Stack Overflow";
else
arr[top++] = value;
}
int pop()
{
if (top == -1)
cout << "Stack Underflow";
else
return arr[top--];
}
void StackTransfer(stack <int> &s1, stack <int> &s2)
{
int x;
if (s1.empty())
return;
x = s1.top();
s1.pop();
StackTransfer(s1, s2);
s2.push(x);
}
};
int main()
{
stack <int> st1, st2, st3;
st1.push(10);
st1.push(20);
st2.push(30);
st2.push(40);
cout<<st3.StackTransfer(&st1, &st2);
}
I want to transfer values, but when I call StackTransfer() function in main (), I am getting this error
Severity Code Description Project File Line Suppression State
Error (active) E0135 class "std::stack<int, std::deque<int, std::allocator>>" has no member "StackTransfer"
Is the logic of StackTransfer() correct for transferring values and preserving the order same?
You made several mistakes in your code.
The first one is mismatching the class names: you declare an ordinary class Stack and then you use a templated class stack<int>. Those are two unrelated classes and the compiler is absolutely right when it complains the stack<int> class does not have a StackTransfer method.
The second mistake is a way you try to call the method. Either the method acts on an object and then:
(a) there's only one explicit parameter to it (another one is this),
(b) its name should indicate a direction of the action: void StackTransferFrom(Stack &s) or void StackTransferTo(Stack &s),
(c) the parameter should be the same class (Stack, not stack<int>), and
(d) it will be called on some object of the declared class: Stack s1, s2; ....; s1.StackTransferFrom(s2);
or the method acts on two objects and then:
(a) it should be defined as static, and
(b) it will be called with two arguments: Stack::StackTransfer(s1, s2); without any third object, but
(c) with a class identifier.
Another one is using the ampersand operator & when calling the function. Your method has reference-type parameters, not pointers, so you should call it with references to variables: StackTransfer(s1, s2) not with pointers to them: StackTransfer(&s1, &s2). The latter would work with a static void StackTransferTo(Stack *s1, Stack *s2) method.
Your attempt to send the result to standard output is wrong, too – your function is declared void, which means it returns no value, hence you get nothing from it that could be output to cout.
Yet another mistake lurks in the push() method: you used a post-increment operator there, but the initial value of top is minus-one. As a result the first value push-ed to your stack will be written to arr[-1], before the array's beginning. This triggers Undefined Behavior of your program.
Improved version:
#include <iostream>
const int MAX = 1000;
class Stack
{
int top = -1;
int arr[MAX];
public:
void push(int value)
{
if (top >= MAX - 1)
std.cout << "Stack Overflow\n";
else
arr[++top] = value;
}
int pop()
{
if (top < 0)
std.cout << "Stack Underflow\n";
else
return arr[top--];
}
bool empty()
{
return top == -1;
}
int top()
{
if (empty())
{
std.cout << "Stack is empty\n";
return 0;
}
return arr[top];
}
void StackTransfer(Stack &source)
{
if (source.empty())
return;
int x = source.top();
source.pop();
StackTransfer(source);
push(x);
}
};
int main()
{
Stack st1, st2;
st1.push(10);
st1.push(20);
st2.push(30);
st2.push(40);
st2.StackTransfer(st1);
}

C++ argument of type is incompatible with parameter of type

I am trying to get stockname to my derived class using a return function, but it shows a error 'argument of type is incompatible with parameter of type'.
strcpy(name,s.name()); //Problem
I tried to make it a constant char but that made a couple of errors.
I am making a project on stock market, text me your ideas.
#include<iostream>
#include<conio.h>
#include<fstream>
#include<string.h>
using namespace std;
class stock
{
char stockname[20];
float istockprice;
float fstockprice;
int demand;
public:
void senter();
void sdisplay();
int demands()
{
return demand;
}
char name()
{
return s.stockname[20];
}
};
class market : public stock
{
char stocksell[20];
char stockbuy[20];
float sellprice;
float rate;
public:
void marketdata();
void rate();
void search();
};
class transaction
{
public:
void credit();
void debit();
void transfer();
};
market m;
transaction t;
stock s;
void market::rate()
{
m.rate = demands();
m.rate += 1;
}
void market::search()
{
char name[30];
strcpy(name,s.name()); //Problem
ifstream search("Marketdata.txt");
if (!search)
{
cout << "Marketdata.txt file error";
return;
}
//while (search.read((char*)& m, sizeof(m)))
//{
// if (strcmp(m.stocksell,name)==0)
//{
//}
// }
}
You're confused about C style strings (and arrays). In C++ you should really use C++ style strings, but you've started this code with C strings so we'll carry on with that for now.
In C a string is an array of characters, to manipulate the string you need a pointer to the first element of the array. So this code is wrong
char name()
{
return s.stockname[20];
}
Firstly there's a total spurious s in there, I don't know what you think that does (and I'm surprised it compiles). But the main point is that because this is a C style string, the function should return a pointer.
char* name() // returns a pointer
{
return stockname;
}
So stockname is an array containing a C style string, and name is a method which returns a pointer to the first element of the array.
Weird as it is, that how you do strings in C. C++ strings are so much easier, in many different ways. If you really want to learn C++, you should leave all the legacy C stuff behind.

Why am I getting memory errors with valgrind? (C++, abstract syntax tree evaluation)

I am currently doing an assignment for a course I'm doing. I have what seems to be a fully working program (I get the right output for all my test data), however when I run with valgrind it says that I have memory errors. Here is the minimal code to reproduce the error (which is still quite a bit sorry):
note: this assignment is about evaluating abstract syntax trees (not parsing, just evaluating)
header file: (provided by my tutor - I can't change this)
struct env {
//will be used to store the values of variables in a stack. This is one 'node' of the stack
string var;
int value;
env *next;
};
class Exp {
//general expression - eval will be overridden.
public:
virtual int eval(env*) = 0;
};
class Constant : public Exp {
int n;
public:
Constant(int n) {this->n = n; }
int eval(env*);
};
class Var : public Exp {
string name;
public:
Var(string s) { this->name = s; }
int eval(env*);
};
class Let : public Exp {
//let binding. (let bvar = bexp in body)
//used to assign a value to variables
string bvar;
Exp *bexp;
Exp *body;
public:
Let(string v, Exp *e, Exp *b)
{
bvar = v; bexp = e; body = b;
}
int eval(env*);
};
This is the code that I have written to evaluate this subset of the syntax:
#include <string>
using namespace std;
#include "evalobj2.h"
int Constant::eval(env *env) {
return this->n;
}
int Var::eval(env *env) {
while(env) {
if ((env->var).compare(this->name) == 0) return env->value;
env = env->next;
}
//give up - variable not found in env
throw 1;
}
int Let::eval(env *env) {
//make a new struct env to be pushed to the environment stack
struct env* newEnv = (struct env*)malloc(sizeof(struct env));
//copy data into new env struct
newEnv->var = this->bvar;
newEnv->value = this->bexp->eval(env);
//make it the head of the "environment" so that it is seen first when looking up a value
newEnv->next = env;
//evaluate
int valToReturn = this->body->eval(newEnv);
free(newEnv);
return valToReturn;
}
When I run the following from a main method I get "6 errors from 6 contexts" from valgrind:
Exp *e = new Let("x",new Constant(1),new Var("x"));
cout << e2->eval(nullptr) << endl;
Even though I get the right result. I have tested on bigger data structures with the rest of the syntax that I have to evaluate, all of which give correct results.
I don't understand what Valgrind is complaining about! It says "Conditional jump or move depends on uninitialised values" at "operator delete(void*)" .... by some other stuff that isn't mine... by Let::eval(env*) ... which is mine.
I will get 0 marks for a program with memory errors.
struct env {
//will be used to store the values of variables in a stack. This is one 'node' of the stack
string var;
int value;
env *next;
};
// ...
struct env* newEnv = (struct env*)malloc(sizeof(struct env));
You are allocating env, a structure with C++ classes, namely a std::string, using the C library's malloc(), which knows absolutely nothing about C++ classes.
This is undefined behavior. C++ classes must be allocated and destroyed with new and delete. It's surprising that your code survives long enough to produce any results, instead of crashing and burning, right from the get-go.
you should use C++ memory allocation: for instance
int Let::eval(env *env) {
//make a new struct env to be pushed to the environment stack
env* newEnv = new env();
//copy data into new env struct
newEnv->var = this->bvar;
...
int valToReturn = this->body->eval(newEnv);
delete newEnv;
return valToReturn;
}
Also, it's good practice to initialize data in constructors. At least:
struct env {
env() : next(0) {}
//will be used to store the values of variables in a stack. This is one 'node' of the stack
string var;
int value;
env *next;
};

Error for getters and setters

I have a vector of vertices and I wish to set vertice.setVisit as false or 0 initially. I defined some getters and setters for this, but getting some type error. Code is as per below:
//Vector:
std::vector<project3::Vertex<VertexType, EdgeType>*> Vertice1;
//Class containing methods:
template <class VertexType, class EdgeType> class Vertex{
protected:
//std::vector<std::pair<int, EdgeType>> VertexList;
VertexType vertice;
EdgeType edge;
int num;
int mark;
//int status=0;
public:
void setNum(int){ this.num = num; }
int getNum() { return num; }
int getMark(){ return mark; }
void setVisit(int) { this.mark = mark; }
};
In some function I am assigning the values to it as :
for(int i=0; i<g1.Vertice1.size(); i++)
{
g1.Vertice1.at(i)->setNum(0);
g1.Vertice1.at(i)->setVisit(0);
}
Below is the error I am getting while compilation of the code for "this.mark=mark" and for "this.num=num" in the function definition in class.
Error: left of '.mark' must have class/struct/union
Error: left of '.num' must have class/struct/union
Isn't this the correct way to assign the values through getter and setters?
In C++, this is a pointer-type. Try this->mark or (*this).mark
EDIT: As Richard pointed out below, also be sure to name your parameters which you are trying to assign. In context, this->mark = mark is the same thing as this->mark = this->mark. Unless mark is a parameter, this is really unnecessary in this case. So realistically, you can get rid of this all together in your example by doing something like this:
void setVisit(int newMark) { mark = newMark; }
Regards,
Dennis M.
Change setNum and setVisit to the following
void setNum(int num) {this->num = num; }
void setVisit(int mark) {this->mark = mark; }
this is a pointer, so you have to use this->num.

How do I declare a struct within a class?

I want to declare a struct within a class which is private and I want to give a character value to a variable in the same struct, but I can't initialize it or cin it:
class puple
{
private:
struct p
{
char name[25];
int grade;
};
public:
puple(){};
void setme()
{
this->p::grade=99;
this->p::name[25]='g'; //here is the problem
}
void printme()
{
cout<<"Name: "<<this->p::name<<endl;
cout<<"Grade: "<<this->p::grade<<endl;
}
};
void main()
{
puple pu1;
pu1.setme();
pu1.printme();
}
You've describe a type called "p" which is a struct. There is yet no thing of type p around. Therefore your
p->...
calls make no sense.
Try declaring
p pInstance;
in your class and using it, ie:
void setme()
{
this->pInstance.grade=99;
this->pInstance.name[25]='g'; //here is the problem
}
Note even with this your assignment to name[25] will fail as the allowed indices for that array are 0 up to 24 (totalling 25 elements).
You have two serious problems here
struct p
{
char name[25];
int grade;
};
This defines a struct type, named p. I think what you wanted to do was
struct
{
char name[25];
int grade;
} p;
This will declare a struct, named p, with the name and grade member variables.
Your second serious problem is that you assign:
this->p::name[25]='g'; //here is the problem
This assigns 'g' to the 26th element of the array name. (arrays are 0-indexed)
isn't it
struct { ... } p; // variable of struct-type definition.
not
struct p { ... }; // type 'struct p' definition.
?
Place the struct definition outside of the class using a typedef. By having the struct defined in your .cpp file it will not be visible outside of your class.
#include <iostream>
typedef struct _foo
{
int a;
} foo;
class bar
{
public:
void setA(int newa);
int getA();
private:
foo myfoo;
};
void bar::setA(int newa)
{
myfoo.a = newa;
}
int bar::getA()
{
return myfoo.a;
}
using namespace std;
int main()
{
bar mybar;
mybar.setA(17);
cout << mybar.getA() << endl;
return 0;
}