C++ Statement can be simplified - c++

Apologies for the lame question. I am using Intellij Clion Student licensed version for my C++ curriculum. As a part of implementing an UnsortedList class, we had to write a method isInTheList to see if an element is present in the array. The class implementation goes as
bool UnsortedList::isInTheList(float item) {
for (int i = 0; i < length; i++) {
if (data[i] == item) {
return true;
}
return false;
}
}
However, the ide shows a coloured mark at data[i] == item with a popup saying
Statement can be simplified less... (Ctrl+F1)
This inspection finds the part of the code that can be simplified, e.g. constant conditions, identical if branches, pointless boolean expressions, etc.
For a previous method to check if the list if empty, I used the following simplified form instead of if-else statement.
bool UnsortedList::isEmpty() {
return (length == 0);
}
However, with iteration involved now, I cannot come up with a simplified statement in the former. Any help is much appreciated. Thank you.

Fix
Your return false should be moved outside off the for loop.
Because you accidentally put it inside the for loop, this iteration never execute for the second time.
So your IDE thinks the for loop is pointless, and suggests you to simplify it to:
return data[0] == item;
This obviously isn't what you want. So really this is just a one-line shift to make it right.

Why not use STL?
inline bool UnsortedList::isInTheList(float item) {
return std::find(data, data+length, item) != data+length;
}
std::find returns an iterator pointing to the element if it's found, or an iterator equal to one-past-last item (i.e. exactly the second argument passed) if nothing is found. You can use a simple equality check to decide if one is found.

You are actually returning after one iteration in your loop. That's the remark of your compiler.
Your code could be simplified by easy write this:
bool UnsortedList::isInTheList(float item) {
if (length != 0) {
return data[0] == item;
}
}
Note, that this is still undefined behavior (UB). You do not have a return in all of your execution paths.
If your list is empty, you never enter the loop, which results in an UB, because there is no return statement, but the function has to return a bool.
I think, your intention was, to write something like this.
bool UnsortedList::isInTheList(float item) {
for (int i = 0; i < length; i++) {
if (data[i] == item) {
return true;
}
}
return false;
}
Move the return false; out of your for loop and you will be fine (still there are better ways to implement this, but that's another topic).

Related

searching for a key in a bst

the compiler is telling me that the assertion failed even though I have atleast 2 items in the array of linked nodes. How do I fix this bool contains function? And yes, I have tried multiple ways but I still get the same error.
Keep in mind that there are 2 items in different indexes of the array. But its not shown below.
This is the contain function:
bool Map::contains(string key){
bool idk = false;
if(elementsStoredCount != 0){
int idk = hashFunc(key); //the hashFunc computes using modulo
if(array[found] != nullptr){
idk = false;
}
else{
found = true;
}
}
return found;
}
when I test in my main.cpp, the second line fails for some reason.
assert(as.contains("1")==true);
Based on some of the other comments and reading the code, i would think that your problem is that your int hashFunc(string key) function is returning an incorrect index outside of the range of array[].
Have you debugged/tested taht the hashFunc() function to ensure the correct data? If correctly implemented and still you are facing a bug, then i'd next look at your table data/insertion functions.

C++ understanding issue- linked lists and stack

I have to make a code, that checks if parentheses are balanced using stack and linked list.
Here is my code, that i made using many tutorials and power point presentations from my class, and also with little bit of help from my friend.
but, can anyone explain what is happening under 'int pop' and 'check' parts, line by line(il put as comment parts i do not understand)? I have problems with understanding this part of c++ (stacks and l.lists that are implemented), and i don't have anyone who can explain it and who have time. I've tried many things, but i really don't understand it.
P.S. code works as it should
Thank you guys!
#include<iostream>
#include <string>
using namespace std;
struct node
{
char data;
node *link;
};
int pop(node *&stack) //node that points to address of a stack?
{
char result;
node *top=new node; //how can i explain this?
top=stack; //why are we equalizing top with stack?
result=top->data;//i dont understand
stack=top->link;//dont understand
delete top;
return result;
}
bool Pairs(char openP,char closedP)
{
if(openP == '(' && closedP == ')') return true;
else if(openP == '{' && closedP == '}') return true;
else if(openP == '[' && closedP == ']') return true;
else return false;
}
bool Check(string exp)
{
int i=0;
node *stack=NULL;
while(exp[i])
{
if(exp[i]=='(' || exp[i]=='[')
{
node *neww=new stack;//dont understand
neww->data=exp[i];//dont understand
neww->link=stack; //-II-
stack=neww; //-II-
}
if(exp[i]==')' || exp[i]==']')
{
if(stack==NULL)
return 0;
else if (Pairs(pop(stack), exp[i])==0) //what does mean this part in parentheses?
return 0;
}
i++;
}
if(stack==NULL)
return 1;
else
return 0;
}
int main()
{
string exp;
cout<<"Enter parentheses:\n";
cin>>exp;
if(Check(exp)!=0)
cout<<"P. are balanced";
else
cout<<"P. are not balanced";
return 0;
}
I would recommend the following approach:
Think about your algorithm ignoring language details. A stack is the right way to go but you don't need to consider how you will implement your stack until you've thought out the algorithm.
Having decided that you need a given data structure ask yourself whether it already exists in C++ (std::stack) before inventing your own.
Use C++ idioms not C idioms (i.e. use iterators begin() and end() not indexing) Apart from anything else this will prevent your exp[i] bug.
Don't have one class doing more than one thing. If you need a stack then create a stack class rather than have your parsing class involved with stack implementations. Firstly it makes it easier to think about the checking algorithm and secondly the stack class can be reused elsewhere.
In outline your solution will use iterators to examine the characters of the string and push and pop opening brackets using a
std::stack<char>. There is no need for new or pointers anywhere.

How to find an element in a binary search tree?

I've been trying to build a 2-3 node. The adding function is working properly and has been confirmed by me so far. The only problem is the find function, which is called to find an element inside the 2-3 node. It does not seem to be working at all. The match pointer inside the it does not take the returned valued from the find_rec method at all, even though I already assigned it. It's just getting a new given address whenever the function is called and I have no idea why it does that. Can anyone help me out ? and tell me what I did wrong ? Thank you
**LValue and RValue**
E LValue() {return _first._value;}
E RValue() {return _second._value;}
**find function**
// Assuming this set contains an element y such that (x == y),
// return a reference to y. Such a y must exist; if it does not an
// assertion will fail.
E& find(E& x)
{
// the match pointer is supposed to take
// returned pointer from the find_rec function
// Yet, it is not doing that at all.
E* match = find_rec(x, _root);
assert(match != nullptr);
return *match;
}
**find_rec function**
// Helper function: find recursion
// function returns a pointer
E* find_rec(E& x, BNode<E>* root)
{
if(root == nullptr)
return nullptr;
else
{
// 2-node
if(!root->IsThree())
{
if(x == root->LValue())
return &root->LValue();
else if (x < root->LValue())
return find_rec(x, root->GetLeft());
else
return find_rec(x, root->GetRight());
}
// 3-node
else
{
if(x == root->LValue())
return &root->LValue();
else if(x == root->RValue())
return &root->RValue();
else if(x < root->LValue())
return find_rec(x, root->GetLeft());
else if(x < root->RValue())
return find_rec(x, root->GetMiddle());
else
return find_rec(x, root->GetRight());
}
}
}
The code is clearly able to return a nullptr when the desired value is not present in the tree.
The moment it gets into that situation, the assert will trigger and the *match return would fail. I expect you need to change the function signature to provide a return type that allows for this case.
From the code seems you're returning the address of a local temporary.
I cannot be sure because the LValue() method declaration is not visible, but if it's returning the node content by value and not by reference then the find_rec function will just return garbage (the address of a temporary allocated on the stack).
A decent compiler should issue a warning for this, by the way.

What can I use as a NULL struct?

I'd like to code a loop going through several instances of the same struct (named edg in my case) iterated by a certain function going from neighbor to neighbor until it returns an element that says STOP. I tried coding it using a NULL return but it doesn't work. What could I use?
Here is some code explaining it probably more accurately than my previous words:
My structure:
struct edg{
int i,j,k;
edg(int a, int b, int c){
i = a; j = b; k = c; //I'm adding a constructor to it
}
}
My iterating function:
edg neighbour(edg temp){
if(temp satisfies certain criterias){ return edg(new coordinates);}
else{ return NULL;}
}
My loop:
while(my_edg!=NULL){
my_edg = neighbour(my_edg);
}
I guess I could just pick a certain value of an edg define it as a rejection, and replace in my loop by:
while(my_edg!=edg_marked_as_rejection)
But is there another way to do so?
Note that your function:
edg neighbour(edg temp){
if(temp satisfies certain criterias){ return edg(new coordinates); }
else{ return NULL; }
}
returns an instance of edg by value thus trying to return NULL; is invalid (unless you've defined some custom conversion). NULL is a possible value when passing / returning by pointer, which in this case could mean changing the prototype of this function to:
edg* neighbour(edg temp) { ... }
however based on the semantics it would be more reasonable to either pass by reference and return a flag indicating success:
bool neighbour(const edg& temp, edg& result) {
if (...) {
result = ...;
return true;
}
return false;
}
or in case your condition "if(temp satisfies certain criterias)" should be met in most of cases and these criteria not being met is rather an exceptional state, you might also consider throwing an exception (instead of returning NULL).
A third option might be implementing a NULL object design pattern, meaning that instance of edg marked as "invalid" would be constructed and returned and caller would do something like:
edg n = neighbour(tmp);
if (!n.isValid()) {
...
}

Trouble erasing items through list while iterating

Okay, I have a STL list of references I am iterating through. This function has three equivalent parts. The function takes a wstring as a parameter, and runs the appropriate if statement. I have reduced the code to one if statement to try and get it working.
So, I check to see what has been passed in as an argument. I then check to see if the ClassItem is a certain type of animal. If it is, I check if it is hungry, and erase it from the list. I am just trying to avoid seg faults right now, and cannot seem to do it.
list<ClassItem *>::iterator i = Items.begin();
while(i != Items.end())
{
if(!AnimalType.compare(L"tiger"))
{
if((*i)->IsAnimalType(L"tiger"))
{
if((*i)->IsHungry())
{
i = Items.erase(i);
}
}
else
{
++i;
}
}
// I have tried removing this
else
{
i++;
}
}
I was under the impression that the current iterator is invalidated when I call erase. So, if I erase an element, I return the next valid iterator. Where am I going wrong?
EDIT: Thank you for all the quick help. The problem has been fixed. I have made use phresnel's solution and it worked wonderfully.
You are better off by using std::list::remove_if with a suitable predicate. This avoids the manual loop entirely, reducing scope for errors, and helping to either remove or at least you localise the source of the problem, since you can rely on this idiom being correct as long as your predicate is.
bool badAnimal(ClassItem * item)
{
// return true if animal is to be removed
}
Items.remove_if(badAnimal);
I see no potential for a segfault here. Anyways:
There are (IMHO) two possible problems:
if(!AnimalType.compare(L"tiger"))
This looks fishy. What is AnimalType? Do you really expect the value of if(!AnimalType.compare(L"tiger")) to change during iteration, if AnimalType itself does not?
In any case, it looks like a read, therefore shouldn't write. It looks constant, therefore shouldn't change.
Then:
if((*i)->IsAnimalType(L"tiger"))
{
if((*i)->IsHungry())
{
i = Items.erase(i);
}
// NO ITERATION IN CASE OF NOT HUNGRY.
// ONCE TRAPPED HERE, YOU HAVE AN INFINITE LOOP,
// EXCEPT AnimalType.compare(L"tiger") DOES SOMETHING
// NON-SANE.
}
else
{
++i;
}
this should better be:
if((*i)->IsAnimalType(L"tiger") && (*i)->IsHungry())
{
i = Items.erase(i);
}
else
{
++i;
}
However, even better would be to use the standard algorithms for element removal.
you may want to add
continue;
after your erasion.