Break statement not exiting for loop - c++

I'm trying to make a for loop so that when there is an item for sale and an item wanted with a lower price, it removes the two listings and exits the for loop using 'j'. For some reason though, the value of askingPrice is staying the same, and removing all items with a lower price, instead of just removing the first one it encounters, and breaking the loop. Is there a different way I should be exiting the loop, or do I just have a logic error somewhere?
for(int i = 0; i < elements; i++){
if(itemArray[i].status == "for sale"){
int askingPrice = itemArray[i].price;
string ITEM = itemArray[i].type;
for(int j = 0; j < elements; j++){
SOLD = 0;
position = 0;
if(itemArray[j].status == "wanted" && itemArray[j].type == ITEM && itemArray[j].price >= askingPrice){
soldArray[soldPosition].type = itemArray[j].type;
soldArray[soldPosition].price = askingPrice;
soldPosition += 1;
//cout << soldPosition << endl;
if(i > j){
for(int k = i; k < elements; k++){
itemArray[k].price = itemArray[k+1].price;
itemArray[k].type = itemArray[k+1].type;
itemArray[k].status = itemArray[k+1].status;
if(k == elements - 2){
elements = elements - 1;
}
}
position = 1;
}
for(int k = j; k < elements; k++){
if(k == elements - 1){
elements = elements - 1;
break;
}
itemArray[k].price = itemArray[k+1].price;
itemArray[k].type = itemArray[k+1].type;
itemArray[k].status = itemArray[k+1].status;
}
if(position = 0){
for(int k = i; k < elements; k++){
if(k == elements - 1){
elements = elements - 1;
break;
}
itemArray[k].price = itemArray[k+1].price;
itemArray[k].type = itemArray[k+1].type;
itemArray[k].status = itemArray[k+1].status;
}
}
SOLD = 1;
}
if(SOLD == 1){
i = i-2;
break;
}
}
}
}

break only breaks out of the innermost loop. There are 2 ways you can conquer this problem:
Set a flag and break out of each subsequent loop if it is triggered.
Extract functions from your program and distinguish single loop breaks from total loop breaks using return to break form multiple associated loops vs break for a single loop. For larger problems always use this method, it will make your code easier to read, well structured and more maintainable.

Either use a sentinel value and sequentially break out of each loop. (The modern way of doing things) OR Cause a massive wave of "You're doing it wrong!" screaming and just use a goto statement. I advocate goto only if you are nesting for loops on 4th or 5th order or higher. If that's the case: "YOU'RE DOING IT WRONG!"

For some reason though, the value of askingPrice is staying the same
You are not changing askingPrice anywhere in your code.
when there is an item for sale and an item wanted
An itemArray object cannot have both status "for sale" and "wanted" at the same time.
So lets say if(itemArray[i].status == "for sale") is true in i loop. The control goes into the if statement and initializes askingPrice and ITEM with ith item's price and type.
From there, j loop is started from 0th element in itemArray. Your j loop has no regard for status = "for sale", this loop only knows the price and type. At this point SOLD = 0;
Now control checks this
if(itemArray[j].status == "wanted" && itemArray[j].type == ITEM && itemArray[j].price >= askingPrice)
Please Note that above if can either be true or false. But in any case it is not considering
status = "for sale"; Therefore, when the above if condition is true, it runs the code within and deletes low priced item according to the condition and when it is false, the code never reaches SOLD = 1; which does not allow j loop to break as if(SOLD == 1) break;
So there you have it and yes you are right, it is indeed a logical error.

Related

What is wrong with this loop-based function that returns the position of an element?

This function looks for an integer 'key' in a given vector from a position 'start'. It returns the position of key if it finds it. But if it does not find key, it should return -1.
However, it is only returning -1 as the output. The function works fine if the else statement is removed, but obviously I need it.
So what is wrong in this function? Please explain in simple terms, I am new to C++. Thank you for all your help.
int Sequential_Search(const vector<int>&v, int key, int start){
int result = 0;
int i;
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
return result;
}
This is pretty easy to understand:
for(i = start; i < v.size(); i++){
if(v[i] == key){
result = i;
}
else{
result = -1;
}
}
Let's say your vector contains [1, 2, 3, 4] and you search 2 starting at index 0: here is what your code is doing:
i = 0: (v[i] : 1) == 2 -> false: result = -1
i = 1: (v[i] : 2) == 2 -> true: result = 1
i = 2: (v[i] : 3) == 2 -> false: result = -1
i = 3: (v[i] : 4) == 2 -> false: result = -1
When you've found your value, you still continue to read other value whereas you should stop.
Either using break or directly returning (return i) in the v[i] == key condition;
Either by checking result in the for condition (result == -1 && i < v.size())
Per comment remark: the case with break and return (the last one is not so hard):
int Sequential_Search(const vector<int>&v, int key, int start){
int result = -1; // important for 'break'
for(int i = start; i < v.size(); i++){
if(v[i] == key){
result = i; break;
}
}
return result;
}
int Sequential_Search(const vector<int>&v, int key, int start){
for(int i = start; i < v.size(); i++){
if(v[i] == key){
return i;
}
}
return -1;
}
When the loop finds the key, it sets result = i - but it doesn't stop looping. On the next iteration, v[i] is likely not equal to key, and the loop resets result to -1. The function returns -1 unless key just happens to match the last element.
The reason this is failing with the else statement is because there are many scenarios that the key would not be the last item in the vector.
If the key is 3 and the vector of ints if <1,3,4>, the for loop will loop through 3 times total. On the first iteration, it will go into the else statement since we did not find the key at the 0th index. Result is -1. On the second iteration, we found the key! Set result to i = 1. The third iteration will go into the else statement again, and set the result back to -1.
To fix this, you can use 'break' to leave the for loop as soon as you find result. Set result to I and then follow that with break; This will ensure that if the result is found, you will not go into the else statement again and reset it to -1.

how to cout the longest permanent sequence (increasing or decreasing) in c++?

I have to make a program in C++ what can manage a sequence optionally with from 2 to 1000 element. At the end the program has to cout the longest increasing or decreasing sequence's numbers of element.
Examples:
6;1;2;3;2;4;1; output: 3; (because: 1;2;3 is the longest with 3 elements)
6;4;3;1;5;2;1; output: 4; (because: 6;4;3;1 is the longest with 4 elements)
I tired the following code and kind of working. The problem is that it cant give the longest one it gives the number of last sequence every time.
Unfortunately i cant find the bug or problem. Could anyone help please?
int counting = 1;
int counting_max = 0, counting_min = 0;
for (int i = 1; i < n; ++i) {
if(block[i] < block[i+1]) {
if(block[i]-block[i-1]>0) {
counting++;
if(counting>counting_max) {
counting_max = counting;
}}
else {
counting = 1;
}
}
if(block[i] > block[i+1]) {
if(block[i]-block[i-1]<0) {
counting++;
if(counting>counting_min) {
counting_min = counting;
}}
else {
counting = 1;
}
}
}
if(counting_max >= counting_min) {
cout<< counting_max;
}
else {
cout<< counting_min;
}
return 0;}
In my code I didn't share the first part because i guess it works properly.
The first is just a while and for function to call for the elements number and after the exact numbers in a block.
So in my code the block contains the numbers.
In the code you have posted your outer loop creates an out-of-bounds access of the block array, since you're accessing block[i+1] in the loop. That's likely the reason that your code is producing correct answers in one direction and not in the other.
Beyond that there are some other problems you might come across with this approach:
You probably don't need to keep track of two separate counters if in the end you take the largest. You could just keep track of the largest sequence regardless of if it increases or decreases.
Since you test the relationships between three elements in the array to see if the sequence is increasing/decreasing, you will have to add extra logic to handle when the list has fewer than three elements.
You need to be careful of when the same number repeats, as this probably does not count as increasing or decreasing.
Here's a revised version that covers these points:
int counting = std::min(n, 1);
int counting_max = counting;
for (int i = 0; i < n - 1; ++i) {
if (
block[i] < block[i + 1] &&
(counting < 2 || block[i] > block[i - 1])
) {
counting++;
} else if (
block[i] > block[i + 1] &&
(counting < 2 || block[i] < block[i - 1])
) {
counting++;
} else if (block[i] == block[i + 1]) {
counting = 1;
} else {
counting = 2;
}
if (counting > counting_max) {
counting_max = counting;
}
}
cout << counting_max << "\n";
Try this alternate code: counting_max is finding longest ascending sequence and counting_min is finding longest descending sequence(by decrementing its loop counter) and at the end, we compare them to find the ultimate longest(supposing we have n-1 elements, if not change it accordingly)
for (int i=1,j=n-2; i<n && j>=0; ++i,--j) {
if (block[i] - block[i - 1]>0) {
counting++;
if (counting>counting_max)
counting_max = counting;
}
else
counting = 1;
if (block[j] - block[j + 1]>0) {
counting_back++;
if (counting_back>counting_min)
counting_min = counting_back;
}
else
counting_back = 1;
}
if (counting_max >= counting_min)
cout << counting_max;
else
cout << counting_min;

C++ for loop continue to loop even though it shouldn't

int inc = swap ? 1 : -1;
for(int j=j1; j!=j2; j+=inc){
if(j < 0)
j = curve2->controlPoints()->size()-1;
if(j >= curve2->controlPoints()->size())
j = 0;
curve->addControlPoint(curve2->controlPoint(j)->pos(), curve2->controlPoint(j)->triangle());
}
I found out that in some case, this for loop infinitely. When looking with a debugger, j does reach j2 but for some reason continue to loop.
I then tried to add a break if j == j2 inside the loop (technically j-inc since j is incremented as it enter into the loop again)
for(int j=j1; j!=j2; j+=inc){
if (j - inc == j2)
{
qDebug() << "break =================================";
break;
}
if(j < 0)
j = curve2->controlPoints()->size()-1;
if(j >= curve2->controlPoints()->size())
j = 0;
curve->addControlPoint(curve2->controlPoint(j)->pos(), curve2->controlPoint(j)->triangle());
}
And doing that indeed solved the problem (and the "break" is indeed printed), but it doesn't really make any sense ?
Why does the first for loop act this way ?
Edit :
I'm iterating over a part of a list (between values j1 and 2). The iteration can go both side depending of the swap parameter (boolean). If j reach one of the end of the list, it continue on the other side (for example if j1=5, j2=1 and the list size is 7, j will take the following values : 5 6 0 1)
It should be noted that I'm only guessing about what happens here...
My guess is that j becomes equal to j2 inside the loop, by one of the assignments. But then the increase j += inc happens and j is no longer equal to j2 when the loop condition is checked.
Generally speaking, a for loop is equivalent to a while loop:
for (a; b; c)
d
is equivalent to
{
a;
while (b)
{
d;
c;
}
}
That means your first loop is equal to (with extra comments added)
{
int j = j1;
while (j != j2)
{
if(j < 0)
j = curve2->controlPoints()->size()-1;
if(j >= curve2->controlPoints()->size())
j = 0;
curve->addControlPoint(curve2->controlPoint(j)->pos(), curve2->controlPoint(j)->triangle());
// At this point `j == j2`, so the loop condition is false
// BUT then you do
j += inc;
// Here `j != j2` again, and the loop condition is true and will continue
}
}
Perhaps your loop condition should be j - inc == j2 instead?

Return Statement positioning

I am writing some function which basically takes in input a range and a 1D vector. It looks at each number in the range of values given of the vector such that:
1) If the number to the left of it is 0 they swap positions.
2) If the number to the left of it is equal to it they add.
Now up till now this was good. The issue arises when I am trying to add return statements:
1) It should return True after all iterations are complete and at least one of the if conditions is entered in each iteration.
2) It should return false after all iterations are complete and none of the conditions are entered.
Now if I put these return statements in the loops they would terminate this function here but this is not desirable since it needs to go through all the iterations first. Is the current code comparable with this or do I need to redo it in a different manner ( if not where could the return statements go?)
bool proc_num(std::vector<int>&v, int LB, int UB) {
bool check = false;
for( int i=LB+2 ; i<UB; i++) {
for(int j = i-1; j>LB; j--) {
if(v[j] == 0){
v[j] = v[i];
check = true;
} else if(v[j] == v[i]) {
v[j]= v[j]+v[i];
v[i] = 0;
check = true;
}
}
}
return check;
}
You can simply add a boolean to make sure that at least one of the if conditions are entered.

Trying to compare elements of string with loops and indices, but indices do not increment

I am trying to make a Su Doku solver for Euler Project. I am having trouble comparing string elements. My 2nd loop with index k occurs only once, rather than nine times. if I remove the code with my if statement, it loops through just fine. Anyone know why? Something about trying to access my strings makes it stop...
puzzle is a vector and reference_stringis a string ="123456789".
for (int i = 0; i != 9; i++){
cout << "loop 1" << endl;
for (int k = 0; k != 9; k++) {
if (reference_string[i] == puzzle[row_index][k] ||
reference_string[k] == puzzle[col_index][k] ||
reference_string[i] == puzzle[box_index][k] ){
possible_answers.push_back(0);
}
else if ( k = 8 ){
possible_answers.push_back(1);
}
}
}
You need to change k = 8 to k == 8, or safer 8 == k. You are not performing a comparison, you are performing an assignment that alters the loop counter so the loop condition is satisfied after just one iteration.