This question already has answers here:
How does C++ handle &&? (Short-circuit evaluation) [duplicate]
(7 answers)
Closed 7 years ago.
How does and operator evaluates its arguments. I have a code to check whether a graph is cyclic or not. In this code there is an and condition in an if statement. And I think, to the best of what I can make out is, that it terminates at the first encounter of a false expression without evaluating the second expression at all.
This is the code
bool Graph::isCyclicUtil(int v, bool *visited, bool *recStack){
if (visited[v] == false){
// Mark the current node as visited
visited[v] = true;
recStack[v] = true;
// Recur for all the vertices adjacent to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); i++){
-------->**This and cond**if (!visited[*i] && isCyclicUtil(*i, visited, recStack))
return true;
else if (recStack[*i])
return true;
}
}
recStack[v] = false; // remove the vertex from the recursion stack
return false;
}
void Graph::printRecStack(bool *recStack){
cout << "\n \n";
for (int i = 0; i < V; i++){
if (recStack[i])
cout <<i<< "\n";
}
return;
}
bool Graph::isCyclic(){
// Mark all the vertices as not visited and not part of recursion stack
bool *visited = new bool[V];
bool *recStack = new bool[V];
for (int i = 0; i<V; i++){
visited[i] = false;
recStack[i] = false;
}
// Call the recursive helper function to detect cycle in different
// DFS trees.
if (isCyclicUtil(0,visited, recStack)){
printRecStack(recStack);
return true;
}
/*for (int i = 0; i < V; i++){
if (isCyclicUtil(i, visited, recStack))
printRecStack(recStack);
return true;
}*/
return false;
}
Please observe the and condition inside the if statement in isCyclicUtil function.
If you take a simple graph as a test case like this one:
0->1
1->2
2->0
2->3
3->3
And call isCyclicUtil for 0, the first 3 values in recStack comes out to be true. Which should have not been the case if the second expression was also evaluated in the if statement. Because call to node 2 will reach for its child 0. But since the loop started from 0, 0 is already visited, so recStack[0] should be initialized to false. But this does not happens, and all of them come out to be true. As if the and condition terminated as soon as it encountered visited[0] to be true, without even calling isCyclicUtil(0,visited,recStack) again.
That's correct. This is called short-circuiting and is a feature of many programming languages.
Related
First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.
I'm trying to create a program for an assignment that will add and remove strings from a vector of strings, but first I need to create a function that will find whether or not the string already exists in the vector.
I've already tried to use a loop to search through the vector to find a specific desired string at each index. I tried adding a break; to exit if the string was found. I don't know if the function is supposed to be void or boolean.
bool FindString(int vctrSize, vector<string> restaurantVctr, string targetRestnt) {
int i;
for (i = 0; i < vctrSize; ++i) {
if (restaurantVctr.at(i) == targetRestnt) {
return true;
break;
}
else {
return false;
}
}
}
I expect the output to be true if the string was found, else it would obviously be false.
Edit: I forgot to mention that I also received the warning: "not all control paths return a value"
You should use std algorithms whenever possible:
auto result = std::find(restaurantVctr.begin(), restaurantVctr.end(), targetRestnt);
return result != restaurantVctr.end();
That is exactly what std::find is for.
While I recommend using std::find as others have recommended, if you're curious what is wrong with your code, the problem is your else:
for (i = 0; i < vctrSize; ++i) {
if (restaurantVctr.at(i) == targetRestnt) {
return true;
break;
}
else {
return false;
}
}
If the first item in your vector is not equal to targetRestnt, then your function returns--that is, it ends execution.
You only want to return false if it's not in the whole list--that is, you want the whole loop to execute:
for (i = 0; i < vctrSize; ++i) {
if (restaurantVctr.at(i) == targetRestnt) {
return true;
// Also, you don't need a break here: you can remove it completely
// For now, I just commented it out
// break;
}
}
// We didn't find it:
return false;
I'm trying to make function that has a loop that checks every member of an array made from boolean variables and exits when it finds the first "true" value.
That's what I have now:
bool solids[50];
int a,i;
//"equality" is a function that checks the equality between "a" and a defined value
solids[0] = equality(a,&value_1);
solids[1] = equality(a,&value_1);
solids[2] = equality(a,&value_1);
solids[3] = equality(a,&value_1);
for (i = 0; solids[i] != true; i++)
{
[...]
}
But I have no idea, what should I put into the loop?
My attempt was
for (i = 0; i <= 50; i++)
{
if (solids[i] == true)
{
return true;
break;
} else {
return false;
}
}
,that should return true after the first found true and return false if the array has no member with true value, but it doesn't seem to work in the code.
Is it wrong? If yes, what is the problem?
PS.: I may count the number of trues with a counter but that's not an optimal solve to the problem, since I just look for the FIRST true value and consequently, the program doesn't have to check all the 50 members. Needley to count, how many unnecesary steps should this solve would mean.
here's a short example usage of std::find() as advised by #chris:
bool find_element_in_array() {
bool solids[50];
int length;
/* ... do many operations, and keep length as the size of values inserted in solids */
bool* location = std::find(solids, length, true);
// if element is found return true
if (location != solids + length)
return true;
// else return false
return false;
}
Once you have solids correctly set (it looks like you're currently setting every value to the same thing), you can make a loop that exits on the first true like this:
for (i = 0; i < 50; i++)
{
if (solids[i] == true)
{
return true;
}
}
return false;
I'd also just move the declaration of i into the for loop body, since it's not used outside, but the above answers your question.
return immediately exits the function, so there is no need to break the loop after.
If it's sufficient to exit the function right after the search, you should write something like:
for (int i = 0; i < 50; i++) {
if (solids[i]) return true;
}
return false;
If you need to use the result of the search in the same function, use additional variable:
bool found = false;
for (int = 0; i < 50; i++) {
if (solids[i]) {
bool = true;
break;
}
}
if (found) { ...
This is one of the solution of getting true or false from given set and target value
bool subsetSumExists(Set<int> & set, int target) {
if (set.isEmpty()) {
return target == 0;
} else {
int element = set.first();
Set<int> rest = set - element;
return subsetSumExists(rest, target)
|| (subsetSumExists(rest, target- element));
}
}
However, this solution will return true or false value only. How is it possible to get the element that involve in the subset(set that add together will equal to target) as well?
Do I have to use dynamic programming? Coz as i know.. recursion is building up stack actually and after the function return the value, the value inside the frame will be discarded as well.
So, is it possible to get the elements that add up equal to the target value.
Is passing an object a solution of the problem?
Thank you
First of all you can optimize your program a little bit - check if target is 0 and if it is always return true. Now what you need is to have somewhere to store the elements that you have already used. I will show you a way to do that with a global "stack"(vector in fact so that you can iterate over it), because then the code will be easier to understand, but you can also pass it by reference to the function or avoid making it global in some other way.
By the way the stl container is called set not Set.
vector<int> used;
bool subsetSumExists(Set<int> & set, int target) {
if (target == 0) {
cout << "One possible sum is:\n";
for (int i = 0; i < used.size(); ++i) {
cout << used[i] << endl;
}
return true;
} else if(set.empty()) {
return false;
}else {
int element = set.first();
Set<int> rest = set - element;
used.push_back(element);
if (subsetSumExists(rest, target- element)) {
return true;
} else {
used.pop_back();
}
return subsetSumExists(rest, target);
}
}
Hope this helps.
I am working on a school project for graphs and here I am doing a depth first search down the tree.
void wdigraph::depth_first(int v) const {
static int firstv = -1;
static bool *visited = NULL;
if (firstv == -1) {
firstv = v;
vector<bool> visited(size);
for (int i = 0; i < size; i++) {
visited[i] = false;
cout << visited[i] << endl;
}
}
cout << label[v];
visited[v] = true;
// visited[0] = true;
The first input value to the function is 0 (v = 0) and it crashes with that. size = 5. As you can see at the end of the code, I have tried to set visited to true manually with the same seg fault. When I remove all attempts to change visited, the program runs how it should normally without a seg fault.
Any ideas why this can't be modified? Also, there is more code but I have decided not to provide it unless necessary.
There are two different variables named visited in your code. Inside the if condition, visited is a vector, but outside this block, on the last line:
visited[v] = true;
visited refers to the bool *visited = NULL defined at the beginning of your code. The segfault occurs because you're trying to dereference a null pointer.