How to check if bool method returns value in an if statement C++ - c++

I'm having a go at creating classes and have created this method inside
Input.cpp:
bool Input::CheckKeyPress(char key)
{
SDL_Event ev;
while (SDL_PollEvent(&ev))
{
keyState = SDL_GetKeyboardState(NULL);
if (ev.type == SDL_KEYDOWN)
{
switch (key)
{
case 'w' :
if (keyState[SDL_SCANCODE_W])
{
return 1;
}
else
{
return 0;
}
case 'a' :
if (keyState[SDL_SCANCODE_A])
{
return 1;
}
else
{
return 0;
}
case 's' :
if (keyState[SDL_SCANCODE_S])
{
return 1;
}
else
{
return 0;
}
case 'd' :
if (keyState[SDL_SCANCODE_D])
{
return 1;
}
else
{
return 0;
}
}
}
}
}
I try to use it in an if-statement in my main class like so:
if (bool Input::CheckKeyPress(w))
{
//do stuff
}
However as expected I get an error saying: "A function type is not allowed here" So what do I do?

Just write:
if (CheckKeyPress(w))
{
//do stuff
}
You have already told the compiler that the CheckKeyPress() method returns a bool. Here, you are just calling the function, so you don't need to mention the return type again. When the control will call the function CheckKeyPress(), it will return a bool value that would be checked for its truth within the if statement.
Note: There are two possibilities:
Instance is a different class:
If Instance is altogether a different class and CheckKeyPress() is
one of the methods that it contains, then you first need to create an object of the Instance class like below:
Instance it = new Instance(); //or just Instance it;
and then access the function via:
it.CheckKeyPress();
If the method is static:
In this case you need to call the method as:
Input::CheckKeyPress(w)
without just the return type (bool).
Hope this is helpful. Thank you for your inputs, #user4581301.

Related

Function checking values of type chars

I am new to programming and have an exercise in which I create a function to check whether an array of type char hold particular values.
Here is my function:
bool arrCheck(char n[],char pos1,char pos2,char pos3,int size)
{
int n1,n2,n3;
for (int i=0;i<size;i++)
{
if (n[i]==pos1)
{
n1=1;
}
if (n[i]==pos2)
{
n2=1;
}
if (n[i]==pos3)
{
n3=1;
}
}
if ((n1==1)&&(n2==1)&&(n3==1))
{
return true;
}
}
here is my test program:
int main()
{
char a[5]={'6','1','a','a','a'};
if (arrCheck(a,'1','6','9',5))
{
cout<<"true\n";
}
}
I thought the result is supposed to be false but all I got is true. What did I do wrong?
n1, n2 and n3 are default-initialized and they have indeterminate values at first. Initialize them before checking their values. Also do not forget to return something even when the condition is false.
Try this:
bool arrCheck(char n[],char pos1,char pos2,char pos3,int size)
{
int n1=0,n2=0,n3=0;
for (int i=0;i<size;i++)
{
if (n[i]==pos1)
{
n1=1;
}
if (n[i]==pos2)
{
n2=1;
}
if (n[i]==pos3)
{
n3=1;
}
}
return (n1==1)&&(n2==1)&&(n3==1);
}
Using boolto store boolean values and using const to mark that the contents of array won't be changed may be better .
bool arrCheck(const char n[],char pos1,char pos2,char pos3,int size)
{
bool n1=false,n2=false,n3=false;
for (int i=0;i<size;i++)
{
n1=n1||(n[i]==pos1);
n2=n2||(n[i]==pos2);
n3=n3||(n[i]==pos3);
}
return n1&&n2&&n3;
}
1) Use a bool variable instead of three int variable
2) Initialize it (You have not initialized the int variable and they have random garbage value)
3) Also add else condition to return false value (Your code is not returning false).
4)Also print false in main function using else condition.
Hope this helps you..!
THE CODE IS ALRIGHT. You just forgot to add some statements and this is causing the error (it might or might not have been silly on your part).
Your definition of the function arrCheck() is incomplete. It returns true if a certain condition is fulfilled but what if it isn't? In that case, you must return false. But in your code, false is never returned. So firstly, you've gotta add an else statement after the last if statement in the arrCheck() method to this:
if((n1==1)&&(n2==1)&&(n3==1)){
return true;
}
else{
return false; //this has to be added
}
It can now return false if such a case is encountered.
Also, you must display "false" in the main method if arrCheck() returns false. You are recommended to add an else statement after the if statement in the main() method. See the modification below:
if (arrCheck(a,'1','6','9',5))
{
cout<<"true\n";
}
else{
cout<<"false\n"; //it must show false;
}
Once you correct these, your code will produce the correct output.
P.S. This answer serves as an elaboration of the answer earlier submitted by #KUSHAGRA GUPTA.
int n1,n2,n3;
This line leads to undefined behaviour because you do not initialise the variables yet attempt to read from them later on even if not all of them have been assigned a value:
if ((n1==1)&&(n2==1)&&(n3==1))
Fix the undefined behaviour by initialising the variables to 0:
int n1 = 0;
int n2 = 0;
int n3 = 0;
There is another case of undefined behaviour when your function does not state what to return if the condition is not true. Fix this, too:
if ((n1==1)&&(n2==1)&&(n3==1))
{
return true;
}
else
{
return false;
}
Or simply:
return (n1==1)&&(n2==1)&&(n3==1);
change that line to like this.int n1= 0,n2= 0,n3 = 0;
because when uninitialized these variable have garbage values.
bool arrCheck(char n[],char pos1,char pos2,char pos3,int size)
{
int first = 0,second = 0, third = 0;
for (int i=0;i<size;i++) {
if (n[i]==pos1) {
first = 1;
} else if (n[i]==pos2) {
second = 1;
} else if (n[i]==pos3) {
third = 1;
}
}
if( first+ second + third == 3)
return true;
else
return false;
}

How to make variables within a function accessible to the main function?

I have some simple code below that I am having trouble getting to run correctly. Essentially, I have a custom function Create() that creates a variant (either Point, Line, Circle) depending on the users input. Then I call this function in the main function, and attempt to call on the variant that I created in Create(). This obviously doesnt work. How can this be fixed?
using boost::variant; //Using declaration for readability purposes
typedef variant<Point, Line, Circle> ShapeType; //typedef for ShapeType
ShapeType Create()
{
int shapenumber;
cout<<"Variant Shape Creator - enter '1' for Point, '2' for Line, or '3' for Circle: ";
cin>>shapenumber;
if (shapenumber == 1)
{
ShapeType mytype = Point();
return mytype;
}
else if (shapenumber == 2)
{
ShapeType mytype = Line();
return mytype;
}
else if (shapenumber == 3)
{
ShapeType mytype = Circle();
return mytype;
}
else
{
throw -1;
}
}
int main()
{
try
{
cout<<Create()<<endl;
Line lnA;
lnA = boost::get<Line>(mytype); //Error: identified 'mytype' is undefined
}
catch (int)
{
cout<<"Error! Does Not Compute!!!"<<endl;
}
catch (boost::bad_get& err)
{
cout<<"Error: "<<err.what()<<endl;
}
}
You need to store the return value:
ShapeType retShapeType = Create() ;
std::cout<<retShapeType<<std::endl;
....
lnA = boost::get<Line>( retShapeType );
You can not access values that are local to a scope(in this case if/else statements) outside of that scope. You can return values from functions which you are doing you just need to store that value to use it.

Should I use returning functions when the return value isn't needed?

I have a function that looks like this:
int Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return 0;
}
else {
// do other stuff
}
}
}
I'm wondering if it is common or proper to have a returning function, rather than a void function, for the sole purpose of leaving the function (the value being returned wouldn't do anything in the program except for ending the function). Is this good practice, or is there a better way to end a function?
There is no problem with void functions. If it does not return anything useful, it should be void.
Just make your function void, and simply return?
// vv void return type
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return; // <<<< No return value
}
else {
// do other stuff
}
}
}
You can easily just use return; with no parameter to exit a void function. Your above code would become:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
else {
// do other stuff
}
}
}
If there is no useful value for the function to return, it is better not to return a value - because the calling code should check the returned value.
Your code can be doubly simplified:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
// do other stuff
}
}
The else is unnecessary; the only way to execute the 'do other stuff' is if something is false.

C++ vector problem

I'm getting some weird behavior with a vector in C++ I was hoping someone could help me out. I have a vector like so:
vector<Instruction*> allInstrs;
the struct for Instruction is as follows:
struct Instruction : simple_instr
{
InstrType type;
Instruction(const simple_instr& simple) : simple_instr(simple)
{
type = Simple;
loopHeader = false;
loopTail = false;
}
int Id;
bool loopHeader;
bool loopTail;
};
the problem I'm having is this:
I need to iterate through each instruction and pull out specific fields and use those to do some analysis on the instructions in the vector. To do that, I was basically doing
VariableList Variables;
void GenerateVariableList()
{
for (int i = 0; i < allInstrs.size(); i++)
{
Variables.Add(allInstrs[i]);
}
Variables.RemoveDuplicates();
}
Variable List is defined as
struct VariableList
{
void Add(simple_instr* instr)
{
PrintOpcode(instr);
switch(instr->opcode)
{
case STR_OP:
case MCPY_OP:
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
case LDC_OP:
Add(instr->u.ldc.dst);
break;
case BTRUE_OP:
case BFALSE_OP:
Add(instr->u.bj.src);
break;
case CALL_OP:
cout << "CALL OP" <<endl;
break;
case MBR_OP:
Add(instr->u.mbr.src);
break;
case RET_OP:
if (instr->u.base.src1 != NO_REGISTER)
Add(instr->u.base.src1);
break;
case CVT_OP:
case CPY_OP:
case NEG_OP:
case NOT_OP:
case LOAD_OP:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
break;
case LABEL_OP:
case JMP_OP:
break;
default:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
}
}
void Add(Variable var)
{
variableList.push_back(var);
}
void RemoveDuplicates()
{
if (variableList.size() > 0)
{
variableList.erase(unique(variableList.begin(), variableList.end()), variableList.end());
currentID = variableList.size();
}
}
VariableList()
{
currentID = 0;
}
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable var(varList[i]);
if (setLiveness)
{
var.isLive = LiveVal;
}
variableList.push_back(var);
}
}
Variable& operator[] (int i)
{
return variableList[i];
}
int size()
{
return variableList.size();
}
vector<Variable>::iterator begin()
{
return variableList.begin();
}
vector<Variable>::iterator end()
{
return variableList.end();
}
protected:
int currentID;
vector<Variable> variableList;
void Add(simple_reg* reg, bool checkForDuplicates = false)
{ cout << "Register Check" <<endl;
if (reg == null)
{
cout << "null detected" << endl;
return;
}
if (reg->kind == PSEUDO_REG)
{
if (!checkForDuplicates || (checkForDuplicates && find(variableList.begin(), variableList.end(), reg->num) != variableList.end()))
{
cout << "Adding... Reg " << reg->num << endl;
Variable var(reg->num, currentID);
variableList.push_back(var);
currentID++;
}
}
}
};
When I do this though, every instruction goes to the default case statement, even though I knwo for a fact some instructions shouldn't. If I change GenerateVariableList to
void GenerateVariableList()
{
for (int i = 0; i < allInstrs.size(); i++)
{
PrintOpcode(allInstrs[i]);
Variables.Add(allInstrs[i]);
}
Variables.RemoveDuplicates();
}
so that there is now a second PrintOpCode in addition to the one in Variables.Add, the program behaves correctly. I can't understand why adding a second PrintOpcode makes it work correctly. All print Opcode is is a function with a switch statement that just prints out a specific string depending on what the value of one of simple_instr's fields is.
VariableList Variables is contained inside of a separate struct called CFG
If you need more information/code i can provide it. If the answer is obvious I apologize, I don't program in C++ very often
EDIT:
One of the answers left, deleted now though, got me the fix.
Previously I was doing
static vector<Instruction*> ConvertLinkedListToVector(simple_instr* instructionList)
{
vector<Instruction*> convertedInstructions;
int count = 0;
for (simple_instr* current = instructionList; current; count++, current = current->next)
{
//Instruction* inst = new Instruction(*current);
Instruction inst = Instruction(*current);
inst.Id = count;
convertedInstructions.push_back(&inst);
}
return convertedInstructions;
}
to make the vector, but after reading that answer I changed it back to using "new" and it works correctly now. Thanks for the help, sorry for the dumb question heh
Most likely the const simple_instr& simple passed to your constructor goes out of scope, and you keep an invalid reference/pointer to a simple_instr.
Possibly not related your problem, but certainly a potential source of strange behaviour: Your Instruction(const simple_instr& simple) constructor may be getting called when you don't intend it. Mark it explicit...
explicit Instruction(const simple_instr& simple) ...
If that causes compiler errors, then that's progress :-) You might need to write a copy constructor to make them go away, and explicitly call the old constructor where you need to.
So, there are several suspicious observations:
In your definition of VariableList you use a type called Variable - how is that type defined?
Iterating over a container should be done using an iterator:
for (vector<Intruction *>::iterator it = allInstrs.begin();
it != allInstrs.end();
++it) {
Variables.Add(*it);
}
You should consider using a vector of boost::shared_ptr, or a boost::ptr_vector instead of a vector of pointers.
I can give you a huge general overview of "don'ts" relating to your code.
You are right in this case to use classes "deriving" from simple_instr but you are doing it wrong, given that later on you do a switch statement based on type. A switch-statement based on type (rather than state) is an anti-pattern. You should be calling some virtual method of your base class.
You almost certainly do not want your derived class to copy from the base class. You want to construct it with the parameters to construct its base-class.
You want a vector of the base class pointers? And to manage lifetime probably shared_ptr
const-correctness. Some of your methods like size() should certainly be const. For others you might want two overloads.

Return from a C++0x lambda caller directly

I've just rewritten the following C89 code, that returns from the current function:
// make sure the inode isn't open
{
size_t i;
for (i = 0; i < ARRAY_LEN(g_cpfs->htab); ++i)
{
struct Handle const *const handle = &g_cpfs->htab[i];
if (handle_valid(handle))
{
if (handle->ino == (*inode)->ino)
{
log_info("Inode "INO_FMT" is still open, delaying removal.",
(*inode)->ino);
return true;
}
}
}
}
With this C++0x STL/lambda hybrid:
std::for_each(g_cpfs->htab.begin(), g_cpfs->htab.end(), [inode](Handle const &handle) {
if (handle.valid()) {
if (handle.ino == inode->ino) {
log_info("Inode "INO_FMT" is still open, delaying removal.", inode->ino);
return true;
}
}});
Which generates:
1>e:\src\cpfs4\libcpfs\inode.cc(128): error C3499: a lambda that has been specified to have a void return type cannot return a value
I hadn't considered that the return in the lambda, doesn't actually return from the caller (having never seen a scoped function in C/C++ before now). How do I return true from the caller where the original function would have done so?
You don't; std::for_each isn't structured to handle an early return. You could throw an exception...
Or don't use a lambda:
for (auto const &handle : g_cpfs->htab) {
// code that was in lambda body
}
Use std::find_if() instead of std::for_each():
if (std::find_if(g_cpfs->htab.begin(), g_cpfs->htab.end(),
[inode](Handle const &handle) {
if (handle.valid() && handle.ino == inode->ino) {
log_info("Inode "INO_FMT" is still open, delaying removal.",
inode->ino);
return true;
}
return false;
}) != g_cpfs->htab.end()) {
return true;
}