Iteration variable goes out of range in for-loop - c++

I have a for-loop in my function:
for (int i = vector1.size() - 1, j = vector2.size() - 1;i >= vector1.size() - Get_polynomial_power(vector1) - 1;--i, --j) {
// some code
something = vector1.at(i); // <- here i goes out of range
}
The problem is that iteration variable i goes out of range.
Condition for exiting from loop is set with i >= vector1.size() - Get_polynomial_power(vector1) - 1; which equals to i >= 0 in my specific case (Get_polynomial_power is user defined function that returns some int value).
And the last value of i is -1. So the program terminates with thrown exception "out of range".
But if I set condition for exiting the loop directly with 0, so it looks like:
for (int i = vector1.size() - 1, j = vector2.size() - 1;i >= 0;--i, --j) {
// some code
something = vector1.at(i); // <- here i doesn't go out of range
}
then there is no error and the last value of i is 0 so it doesn't go out of range.
So the question is: why doesn't iteration variable goes out of range if condition for exit from loop is set directly via 0, but if it is set with a statement that is equals to 0 then the error appears?
I tried a solution with loop-local value as was told in other similar questions, like:
for (int i = vector1.size() - 1, j = vector2.size() - 1;i >= vector1.size() - Get_polynomial_power(vector1) - 1;--i, --j) {
// some code
int index = i;
something = vector1.at(index);
}
but it didn't change the thing.
Just in case, here is full code of my function:
vector<int> Polynomial_addition_substraction(vector<int> polynomial1, vector<int> polynomial2) {
vector<int> addition_substraction_result;
vector<int> vector1;
vector<int> vector2;
if (Get_polynomial_power(polynomial1) >= Get_polynomial_power(polynomial2)) {
vector1 = polynomial1;
vector2 = polynomial2;
}
else {
vector1 = polynomial2;
vector2 = polynomial1;
}
for (int i = vector1.size() - 1, j = vector2.size() - 1;i>=vector1.size()-Get_polynomial_power(vector1)-1;--i,--j) {
if (j < 0) {
addition_substraction_result.insert(addition_substraction_result.begin(), vector1.at(i));
}
else {
addition_substraction_result.insert(addition_substraction_result.begin(), vector1.at(i) ^ vector2.at(j));
}
}
return addition_substraction_result;
}

The issue is due to .size() evaluating to an unsigned type and the subsequent subtraction happening therefore in unsigned arithmetic. (The int in an expression containing an unsigned and and int is converted to an unsigned.) This effect is particularly noticeable if the vector is empty.
So wraparound effects take the expression value to a large unsigned number, and that yields a subscripting error.
The solution is to write an expression of the form
i > size() - a
as
i + a > size()

Related

Heap-buffer overflow when implementing two-pointer approch

I'm solving this brain teaser
Given a 1-indexed array of integers numbers that is already sorted in
non-decreasing order, find two numbers such that they add up to a
specific target number. Let these two numbers be numbers[index1] and
numbers[index2] where 1 <= index1 < index2 <= numbers.length.
Return the indices of the two numbers, index1 and index2, added by one
as an integer array [index1, index2] of length 2.
The tests are generated such that there is exactly one solution. You
may not use the same element twice.
Your solution must use only constant extra space.
Example 1:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9.
Therefore, index1 = 1, index2 = 2.
We return [1, 2].
and my solution is giving this error:
=================================================================
==31==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000620 at pc 0x000000345e97 bp 0x7ffcd6847990 sp 0x7ffcd6847988
READ of size 4 at 0x602000000620 thread T0
#2 0x7f2c3b9790b2 (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x602000000620 is located 0 bytes to the right of 16-byte region [0x602000000610,0x602000000620)
I did some research and saw that this is usually caused by calling an index that's too far (i.e. outside the range of the data structure you're using) but since I'm using vectors I don't get why I have this error. It happened on the following test case: [5,25,75]
100.
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
// can have an i that points forward and a j that loops through everything until sum
// is greater
// checking recursively
// if sum greater stop checking (as list is increasing)
// can reset i each time??
// add 1 at the end
vector<int> indices;
int i = 0;
int j = 0;
// for loop on top?
for (int i; i < numbers.size(); i++)
int j = 0;
while (numbers[i] + numbers[j] <= target) {
if (numbers[i] + numbers[j] == target && i != j) {
// some if determining if i or j is greater
// to determine the order in which to push back
indices.push_back(i+1);
indices.push_back(j+1);
return indices;
} else {
j++;
}
}
return indices;
}
};
The other tests are passing but this one is failing. I am trying to use a two-pointer approach here.
There are several issues with this code, some simple syntactic mistakes, some algorithmic problems.
First, as others have mentioned, i is uninitialized in your outer for loop. Luckily, that never comes into play because you have no braces around the loop body. Your code is equivilent to
for (int i; i < numbers.size(); i++) {
int j = 0;
}
while (numbers[i] + numbers[j] <= target) {
// ...
}
This is presumably not what you intended, so you need to both initialize i and add {} around the loop body:
for (int i = 0; i < numbers.size(); i++) {
int j = 0;
while (numbers[i] + numbers[j] <= target) {
// ...
}
}
Of course, you also don't need the redundant definitions of i and j outside the loops. Those variables get hidden by the ones defined within the loops, and are never used.
Of course, this still doesn't address your out-of-range error. For that, you need to re-think your algorithm. Lets walk through it to find the issue. I'll just focus on the inner while loop.
Assuming, from your test case that numbers = {5, 25, 75} and target = 100.
First iteration:
i = 0 and j = 0
numbers[i] + numbers[j] -> numbers[0] + numbers[0] -> -> 5 + 5 -> 10. That's less than 100, so the loop is entered
if (10 == 100) is false, so the else branch is selected
j++, so now i = 0 and j = 1
Second iteration:
numbers[i] + numbers[j] -> numbers[0] + numbers[1] -> 5 + 25 -> 30. That's less than 100, so the loop continues
if (30 == 100) is false, so the else branch is selected
j++, so now i = 0 and j = 2
Third iteration:
numbers[i] + numbers[j] -> numbers[0] + numbers[2] -> 5 + 75 -> 80. That's less than 100, so the loop continues
if (80 == 100) is false, so the else branch is selected
j++, so now i = 0 and j = 3
Third iteration:
numbers[i] + numbers[j] -> numbers[0] + numbers[3] -> boom
j is now out of range of the valid indices of numbers, so when you attempt to access numbers[j] the behavior of your program becomes undefined. In this case, it crashed; the best possible outcome.
as the above comments pointed it out,
for (int i; i < numbers.size(); i++)
here 'int i' hides the previous local declaration of 'int i = 0;' (C4456), which is not desirable.
and the problem is that although i is bound to the range [0, n-1], j is not, which can cause access violation when j exceeds the range.
You can use below code which will pass your all test cases.
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//first we will declare an additional vector which will return desired solution
vector<int> mult;
//by using two pointer approach
for(int i = 0; i<=nums.size(); i++){
for(int j = i+1; j<nums.size();j++){
//checking for condition
if(nums[i]+nums[j]==target){
mult.push_back(i);
mult.push_back(j);
j++;
return mult;
}
}
}
return mult;
}
};

strange error in main and incorrect reading of a vector [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 months ago.
Improve this question
hi I was writing a code where near the vectors it returns true if they are placed in ascending order otherwise false, when I try to start the code it gives me this error that I cannot understand
main.cpp:9:5: error: conflicting types for 'main'
int main(int, const char *[]) {
^
./solution.cpp:30:5: note: previous definition is here
int main()
^
1 error generated.
the other error happens in the vector inAscOrder_3 in which it should return false but I don't understand why it doesn't return it.
the code.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool isAscOrder(vector<int> arr)
{
int size_array = arr.size()-1;
int min = 0;
int max = 0;
for (int j = 0; j < size_array; j++)
{
if (min == 0)
{
min = arr[j];
max = arr[j];
}
if (arr[j] > min)
{
return true;
}
if(arr[j]<min)
{
return false;
}
}
return false;
}
int main()
{
vector<int> inAscOrder_1 = {1, 2, 4, 7, 19}; // returns true
vector<int> inAscOrder_2 = { 1, 2, 3, 4, 5 }; // returns true
vector<int> inAscOrder_3 = { 1, 6, 10, 18, 2, 4, 20 }; // returns false
vector<int> inAscOrder_4 = { 9, 8, 7, 6, 5, 4, 3, 2, 1 }; // returns false because the numbers are in DESCENDING order
//test 1
if (isAscOrder(inAscOrder_1) == true)
{
cout << "test #1 passed! " << endl;;
}
if (isAscOrder(inAscOrder_2) == true)
{
cout << "test #2 passed! "<<endl;
}
if (isAscOrder(inAscOrder_3) == false)
{
cout << "test #3 passed! "<<endl;
}
if (isAscOrder(inAscOrder_4) == false)
{
cout << "test #4 passed! ";
}
return 0;
}
In your average C++ program, the main function is the singular entry and exit point for the program. When your executable is called, the program starts at main, and once main returns, the program releases all of its allocated resources and is terminated.
Your first issue arises because you have multiple declarations of the main function; the first is located at main.cpp:9:5, and the second is located at solution.cpp:30:5
As for your second issue, your function does not do what you think it does; any correlation between your expected outputs and the real outputs are pure coincidence.
bool isAscOrder(vector<int> arr)
{
// This gets the size of your vector, then subtracts 1.
// size_array is now the index of the last element in the vector,
// and can be accessed with arr[size_array] without throwing an exception.
int size_array = arr.size()-1;
int min = 0;
int max = 0; //< you never actually read the value from this
// This condition is true until (j == size_array), and once it is the for loop breaks the loop.
// Keep in mind, size_array is currently set to the index of the last ELEMENT in your vector;
// That means you're always skipping the last element in the vector.
// You can avoid this by checking either ( j < arr.size() ) or ( j <= size_array )
// ▼
for (int j = 0; j < size_array; j++)
{
// This is always triggered on the first loop because min is always set to 0 the first time.
// if every number in the vector is 0 (except for the last one),
// then this will trigger every single time.
// ▼▼▼▼▼▼▼▼
if (min == 0)
{
// ▼ Sets min to the value at arr[j]
min = arr[j];
max = arr[j];
// ▲ Sets max to the value at arr[j],
// so max is now equal to min.
// For tests 1-3, that value is `1`;
// for test 4, that value is `9`
// Here we check if the value at arr[j] is greater than min, and if it is-
// -we immediately break from the for loop and return true.
if (arr[j] > min)
{
return true;
}
// Here we check if the value at arr[j] is less than min, and if it is-
// -we immediately break from the for loop and return false.
if(arr[j]<min)
{
return false;
}
//< we never reach this point a second time unless ( arr[0] == arr[1] )
}
//< This is only ever reached if every element of arr except for
// the last one is set to the same number.
return false;
}
As an example of what this function is doing, I debugged it for you:
As you can see, the function returned true on the second loop; this is because arr[1](2) is greater than min(1).
inAscOrder_1
Returns true when j == 1, because inAscOrder_1[1] == 2, and 2 > 1
inAscOrder_2
Returns true when j == 1, because inAscOrder_2[1] == 2, and 2 > 1
inAscOrder_3
Returns true when j == 1, because inAscOrder_3[1] == 6, and 6 > 1
inAscOrder_4
Returns false when j == 1, because inAscOrder_4[1] == 8, and 8 < 9
This is a working example of what your function should be doing:
bool isAscOrder(vector<int> arr)
{
if (arr.size() < 2) //< make sure arr[1] exists
return false;
// Start at 1 Don't skip the last element
// ▼ ▼▼▼▼▼▼▼▼▼▼▼▼▼
for (int i{ 1 }; i < arr.size(); ++i) {
// Check if arr[i] is less than or equal to arr[i - 1], this is
// why we started at 1 instead of 0; to prevent accessing arr[-1]
// ▼ ▼▼▼▼▼
if (arr[i] <= arr[i - 1])
return false;
// This approach works because if the sequence is in ascending order,
// each number in arr is never less than the previous one. (except for arr[0], which doesn't have a previous number)
}
return true;
}
You can allow a vector with repeated numbers to return true with this variant:
bool isAscOrder(vector<int> arr, bool allowRepeats = false)
{
if (arr.size() < 2) //< make sure arr[1] exists
return false;
for (int i{ 1 }; i < arr.size(); ++i) {
if (allowRepeats
? ( arr[i] < arr[i - 1] ) //< when allowing repeats, return false if the current element is less than the previous one.
: ( arr[i] <= arr[i - 1] ) //< when disallowing repeats, return false if the current element is less than or equal to the previous one.
)
{
return false;
}
}
return true;
}
When you're writing C++ code, having access to a debugger is incredibly important; if you're on Windows you can download and use Visual Studio Community for free.

The knapsack problem, visual studio issues

I implemented a dynamic programming solution to the famous knapsack problem. Now the funny part of this is that visual studio will not allow my code to compile yet when I copy and paste my code in cpp.sh it runs fine with no errors.
At the moment this is what I am getting in visuial studio for errors:
Unhandled exception at 0x0FADED76 (ucrtbased.dll) in Practice.exe: An invalid
parameter was passed to a function that considers invalid parameters fatal.
This occurs at line 10, i.e. dp[i][j] = 0. I am not sure how to fix this issue, and in general I have noticed that visual studio can be particularly whiny.
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
int maxKnapSack(std::vector<int>& v, std::vector<int>& w, int capacity) {
std::vector<std::vector<int>> dp(capacity + 1, std::vector<int>(v.size() + 1));
for (int i = 0; i <= v.size(); i++) {
for (int j = 0; j <= capacity; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
}
else if (j - w[i - 1] >= 0) {
dp[i][j] = std::max(v[i-1] + dp[i - 1][j - w[i-1]], dp[i - 1][j]);
}
else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[v.size()][capacity];
}
int main() {
std::vector<int> v = { 10, 4, 7 };
std::vector<int> w = { 4, 2, 3 };
int capacity = 5;
std::cout << "The maximum I can get is " << maxKnapSack(v, w, capacity) << "\n";
std::cin.get();
}
Your vector dp contains 6 elements, each element being a vector of 4 elements. It's equivalent to the array definition int dp[6][4].
Your outer loop loop from 0 to 4 (inclusive) and the inner loop loops from 0 to 6 (inclusive). That means you will use index out of bounds in the nested (inner) vector.
Your loops should be the other way around with their limits. Or your vector dp should be defined with the sizes switched.
Your conditions inside the inner loop are also wrong. The condition i == 0 || j == 0 will be false if e.g. i == 0 and j != 0. That will then lead to you using negative indexes because of i - 1. That is also out of bounds and again lead to undefined behavior.
You need to make sure that the else if only happens when i > 0 and j - w[i-1] > 0 as well. And the else only when i > 0.

c++ for loop post-increment pre-increment difference

i've been searching for an answer, but i get more and more confused.
i have these 2 for loops
for (int i = 1; (i < 5) && move.from[i - 1]; i++) {
int const departurePoint = move.from[i - 1];
int arrivalPoint = move.to[i - 1];
if (arrivalPoint < 0) { // A blot was hit
arrivalPoint = -arrivalPoint;
board[1 - turn][BAR - arrivalPoint]--; // Remove the blot
board[1 - turn][BAR]++; // and place it on the bar */
}
board[turn][departurePoint]--; // Move our own checker
board[turn][arrivalPoint]++; // to it's landing spot.
}
and
for (int i = 1; (i < 5) && move.from[i - 1]; ++i) {
int const departurePoint = move.from[i - 1];
int arrivalPoint = move.to[i - 1];
if (arrivalPoint < 0) { // We hit a blot
arrivalPoint = -arrivalPoint;
board[1 - turn][BAR - arrivalPoint]++; // Replace the blot
board[1 - turn][BAR]--; // remove it from the bar
}
board[turn][departurePoint]++; // Replace our own checker
board[turn][arrivalPoint]--; // to it's original spot.
}
my questions are:
In the for loop statement with pre-increment, has i been incremented when the "move.from[i - 1] is evaluated?
Has i been incremented in the body of the statement?
for (int i = 1; (i < 5) && move.from[i - 1]; i++ /*i increments here and nowhere else*/)
and
for (int i = 1; (i < 5) && move.from[i - 1]; ++i /*i increments here and nowhere else*/)
Both codes are equivalent. The difference is very slight and it does not apply to this example.
when i==3,
++i means:
4=i+1=(++i) then i=4.
i++ means:
3= i =(i++) then i=4.
it does not make a difference until you assign it to another variable:
for(...; ...; k=i++)
or
for(...; ...; k=++i)
i+1 means:
store i to a temporary variable. Increase the temporary variable by one. It reads i but does not write to i. i will change only on ++, -- or i= and a few other cases.
Your short question is What is the difference between i++ and ++i is the value of the expression?
The value i++ is the value of i before the increment. The value of ++i is the value of i after the increment.
Example:
int i = 2;
std::cout << i++ << std::cout; // shows 2
std::cout << i << std::cout; // shows 3
i = 2;
std::cout << ++i << std::cout; // shows 3
std::cout << i << std::cout; // shows 3
The i-- and --i operators works the same way.
The for loop takes two statements and an expresion like this:
for(init_statement;condition_expresion;progress_statement){
//...body...
}
The semantic of this instruction is basically the same as writing:
init_statement;
while(condition_expresion){
//...body...
progress_statement;
}
Notice the side effect of both i++ and ++i is the same, the variable i is incremented by one. Those two instructions are different when they are used as expresions, i++ evaluates to the value of i before the increment, and ++i evaluates to the value after the increment. This is all irrelevant for the for loop, as the value of the progression statement is discarded.

What does it mean for an array to have incremented element in square brackets?

In the following algorithm for merge-sort, within the 3rd definition, first while loop there is:
a[k++] = (a[j] < b[i]) ? a[j++] : b[i++].
I understand that the RHS is a conditional statement stating that if the first operand is satisfied, then we should perform the second operand, and if it is not satisfied, we should perform the third operand.
What element does a[k++], a[j++] and b[i++] correspond to?
From my understanding, it should mean in each successive while loop, the element is incremented.
ie. beginning with the initialised values (i=1, j=m+1, k=1) for the first while loop, the next while loop will consist of (i=2, j=m+2, k=2), and so on.
Here is the entire algorithm:
# split in half
m = n / 2
# recursive sorts
sort a[1..m]
sort a[m+1..n]
# merge sorted sub-arrays using temp array
b = copy of a[1..m]
i = 1, j = m+1, k = 1
while i <= m and j <= n,
a[k++] = (a[j] < b[i]) ? a[j++] : b[i++]
→ invariant: a[1..k] in final position
while i <= m,
a[k++] = b[i++]
→ invariant: a[1..k] in final position
a[k] takes the kth element of the array a.
k++ increases the value of k, but returns the previous value.
Thus, a[k++] returns a[k] with the side-effect of increasing k after returning the value of a[k]. a[k++] = 4 is equivalent to:
a[k] = 4
k = k + 1
On the other hand, ++k would increase k before returning it, so a[++k] = 4 would be
k = k + 1
a[k] = 4
The increment and decrement operators work the same in array subscripts as they do in other locations. The postfix version increments the variable and returns its original value, and the prefix version increments the variable and returns its new value.
int i = 0;
do {
if (i++) { std::cout << "i > 0" << std::endl; }
} while (i < 10);
// Checks "i"'s original value.
// First check fails, because i was 0 before incrementing.
// Outputs line 9 times.
// -----
int i = 0;
do {
if (++i) { std::cout << "i > 0" << std::endl; }
} while (i < 10);
// Checks "i"'s incremented value.
// First check succeeds, because i is incremented before being read.
// Outputs line 10 times.
Similarly, if we have this:
int arr[5] = { 1, 2, 3, 4, 5 };
int i = 0;
do {
std::cout << arr[i++] << std::endl;
} while (i < 5);
The variable's original value will be used as the index, and the output will be:
1
2
3
4
5
However, if we have this:
int arr[5] = { 1, 2, 3, 4, 5 };
int i = 0;
do {
std::cout << arr[++i] << std::endl;
} while (i < 5);
The variable's incremented value is used as the index, and the output will be:
2
3
4
5
Considering this, we can take your example line, a[k++] = (a[j] < b[i]) ? a[j++] : b[i++], and read it as meaning this:
Assign value to a[k], then increment k.
Value is conditionally determined based on:
(a[j] < b[i])
If true, value is:
Read a[j], then increment j.
If false, value is:
Read b[i], then increment i.
It can be a useful time-saver if you know how to use it properly, but it can also make things harder to parse if used improperly.