Using vector from other class as reverse iterator - c++

I'm on thin ice here, Sorry. I have not used reverse iterators before, and like you can see in my code is that I also want to use a vector from another class as THE iterator object:
double indicators::sRSItemp(input* Close1, int StartDay) {
int n = 14;
double rs;
double rsi;
double tmpavl;
double tmpavg;
if (!RSI.empty()) {
for ( vector<double>::reverse_iterator i = Close1->Close.rbegin(); i != Close1->Close.rend(); ++i ) {
if (Close1->Close[i] < Close1->Close[(i + 1)]){
tmpavl = ((AVL[0] * 13 ) + (Close1->Close[(i +1)] - Close1->Close[i] ) / n);
cout << "AVLtmp " << AVL[0] << endl;
cout << "tmpavl " << tmpavl << endl;
AVL.insert(AVL.begin(), tmpavl);
cout << "AVL is " << AVL[0] << endl;
tmpavg = ((AVG[0] * 13 ) / n );
AVG.insert(AVG.begin(), tmpavg);
// cout << "AVG is " << AVG[i] << endl;
}
else if (Close1->Close[i] > Close1->Close[(i + 1)]) {
tmpavg = ((AVG[0] * 13 ) + (Close1->Close[i] - Close1->Close[(i +1)]) / n );
AVG.insert(AVG.begin(), tmpavg);
// cout << "AVG is " << AVG[i] << endl;
tmpavl = ((AVL[0] * 13 ) / n );
AVL.insert(AVL.begin(), tmpavl);
// cout << "AVL is " << AVL[i] << endl;
}
rs = AVG[0] / AVL[0];
rsi = (100.0 - (100.0 / (1.0 + rs)));
RSI.insert(RSI.begin(), rsi);
}
}
return 0;
}
But when I compile this code I get several errors like this :
error: no match for ‘operator[]’ (operand types are ‘std::vector’ and ‘std::vector::reverse_iterator {aka std::reverse_iterator<__gnu_cxx::__normal_iterator > >}’),
pointing to my vector indexing ??
if (Close1->Close[i] < Close1->Close[(i + 1)]){
Like I said this is new territory for me, and the fault I guess lies with the declaration of the iterator ?
When I iterate through the same vector (front-to-back) in other code there are no problems.
Help much appreciated!

The square brackets operator of std::vector accepts indexes, not iterators.
Here you're trying to use iterators as indexes:
if (Close1->Close[i] < Close1->Close[(i + 1)]) {
Instead of passing iterators to operator [], you should just use asterisks to dereference them, in order to get to vector elements they are pointing to:
if (*i < *(i + 1)) {
Also, be careful with dereferencing i + 1: on the last iteration of your loop i + 1 will be equal to rend() (the reverse past-the-last element iterator). Attempting to access anything via such an iterator will result in undefined behavior.

To see what you're doing wrong, notice that these two are equivalent
int main(){
vector<int> myVec {{1,2,3,4}};
//read then print each value in vector
for(vector<int>::iterator i=myVec.begin();i!=myVec.end(); ++i){
//here i is an iterator not an index
int val = *i; //get value in current position within vector
cout<<val<<endl;
}
for(int i=0; i!=myVec.size(); ++i){
// here i is an index
int val = myVec[i];//get value in current position within vector
cout<<val<<endl;
}
}
in your case use "*i" instead of "Close1->Close[i]" to read the value

Related

Where is the origin of this munmap_chuck(): invalid pointer error in C++?

I try to implement Hierholzer's algorithm in C++. The underlying multigraph is represented using a two-dimensional map, which maps two vertices to the number of edges between them. My approach is to decrement this count of an edge every time it is traversed and completely removing it if the count is 0.
This is the function:
vector<int> euler_tour(map_2d edge_copies) {
map<int, int> available_nodes;
available_nodes.insert({ 0, 0 });
vector<int> tour = { 0 };
while (!edge_copies.empty()) {
int n0 = (available_nodes.begin())->first;
int n = n0;
vector<int> subtour = { n0 };
while (!edge_copies.at(n).empty()) {
int n_ = (edge_copies.at(n).begin())->first;
subtour.push_back(n_);
cout << n << " " << n_ << endl;
cout << "graph and soubtour: " << endl;
print_map_2d(edge_copies);
print_vector(subtour);
edge_copies.at(n).at(n_) -= 1;
edge_copies.at(n_).at(n) -= 1;
if (edge_copies.at(n).at(n_) == 0) {
edge_copies.at(n).erase(n_);
edge_copies.at(n_).erase(n);
}
if (edge_copies.at(n).empty()) {
edge_copies.erase(n);
available_nodes.erase(n);
} else {
available_nodes[n] = available_nodes.at(n0) + subtour.size() - 1;
}
if (edge_copies.at(n_).empty()) {
edge_copies.erase(n_);
available_nodes.erase(n_);
} else {
available_nodes[n_] = available_nodes.at(n0) + subtour.size();
}
n = n_;
}
tour.insert(tour.begin() + available_nodes[n0], subtour.begin(), subtour.end());
print_vector(tour);
}
}
When I execute it, i get munmap_chunk(): invalid pointer after the first iteration of the second while loop. I experimented a bit, and I think it breaks at the line subtour.push_back(n_);. But why? This is a standard operation. Or do you see any other problematic lines?
The functions print_map_2d and print_vector are implemented elsewhere, they are surely not the problem.

For-loop-condition (vector of ints). How to get the previous value?

I have vector of integers which is filled only by 1 or 0 values. What I am trying to make is that when the current value is 1 and previous/old is 0 or opposite if Current=0 and Previous=1, then to assign another variable(AvgCan) to 0.
I am trying to get from FOR condition previous value. However, if I try it the usual way I still get the same value all the time until the loop end. The issue is in the first if-statement.
int AvgCan = 0;
int OldAvgCan = 0;
int iteration = 0;
int iterationDecrease = 0;
for (int i = 0; i < resultINT.size(); i++)
{
//myFileO << to_string(resultINT.at(i)) + "\n";
cout << to_string((resultINT.at(i))) + " Current" + "\n";
cout << to_string((resultINT.at(i - iteration))) + " Old" + "\n" << endl;
cout << to_string(AvgCan) + "\n" << endl;
iteration = i;
iterationDecrease = i - 1;
if ((resultINT.at(i)) != (resultINT.at(iteration - iterationDecrease)))
{
AvgCan = 0;
}
if ((resultINT.at(i)) == 1)
{
/*if ((resultINT.at(i- iteration)) != 1)
{
AvgCan = 0;
}*/
AvgCan++;
}
if ((resultINT.at(i)) == 0)
{
/*if ((resultINT.at(i- iteration))!=0 )
{
AvgCan = 0;
}*/
AvgCan--;
}
myFileO << to_string(AvgCan) + "\n";
}
As you can see I assigned iterator i to iteration variable and i - 1 to iterationDecrease. (I also tried i-- and similar possible ways.)
I simulated the data so the results are 1,1,1,1,0,0,0,0. When it is changing from 1 to 0 and it gets to the if condition, but each next iteration it still returns 1 like old values, even when it's 0.
I am adding also screenshot for better understanding. On the right side is output in the console.
Here
iteration = i;
iterationDecrease = i - 1;
if ((resultINT.at(i)) != (resultINT.at(iteration - iterationDecrease)))
the iteration - iterationDecrease is equal to i - (i - 1) which is always 1. Meaning in effect that if the statement is equivalent to
if ((resultINT.at(i)) != (resultINT.at(1)))
You probably meant
if (resultINT.at(iteration) != resultINT.at(iterationDecrease))
which is still not correct, as when i==0, the iterationDecrease = -1 which will throw an exception, for the call .at(-1)
You need to start from i=1 in the loop therefore,
for (int i = 1; i < resultINT.size(); i++)
{
// ...code
if (resultINT[i] != resultINT[i-1])
{
// ...code
}
}
Think about the expression iteration - iterationDecrease. It has a constant value 1.
You wished probably resultINT.at(iterationDecrease), but it will cause an exception on the first iteration, since it will try to access -1 element.
Avoid indexing when it is possible. It is not final solution but it may show you right direction. Use adjacent_find to find pairs. I made this example for you here.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> vec{ 0,0,1,1,0,0,0,1,0,1,0,0,0,0,1,1 };
auto it = std::begin(vec);
while (1) {
it = std::adjacent_find(it, std::end(vec), [](int v1, int v2) {
return std::min(v1, v2) == 0 && std::max(v1, v2) == 1;
});
if (it != std::end(vec)) {
std::cout << "Pairs " << *it << " and " << *(it + 1) << " with indexes "
<< std::distance(std::begin(vec), it) << " and "
<< std::distance(std::begin(vec), it + 1) << std::endl;
++it;
}
else {
break;
}
}
return 0;
}
Output
Pairs 0 and 1 with indexes 1 and 2
Pairs 1 and 0 with indexes 3 and 4
Pairs 0 and 1 with indexes 6 and 7
Pairs 1 and 0 with indexes 7 and 8
Pairs 0 and 1 with indexes 8 and 9
Pairs 1 and 0 with indexes 9 and 10
Pairs 0 and 1 with indexes 13 and 14

Merging points closest to each other in an array of 3 elements each

I am implementing a simple greedy merging algorithm that merges the two points which are closest to each other and averages their position. After merging two points at indices i and j, I need to replace one of them, say i, by the mean of the two points. Then, copy the last point in the array over the other point, say j, after which I can reduce the array size by 1 with all remaining points being within the new reduced range.
I need to repeat the above step until there are only 3 representative points left, each of which represents a group of merged points. I have written the following code, but I guess it is not able to update the array (pts). I would appreciate if anyone could help me figure out the mistake. Thanks in advance. This is my code:-
void merge_point(Point pts[], int &size) {
double a;
int x, y;
Point d;
while(size != 3) {
double min = get_distance(pts[0],pts[1]);
for (int i = 0; i < size; i++) {
for (int j = i+1; j < size; j++) {
get_distance(pts[i], pts[j]);
if ((a = get_distance(pts[i],pts[j])) <= min) {
x = i;
y = j;
}
a = get_distance(pts[i],pts[j]);
}
}
d = mean_point(pts[x],pts[y]);
pts[x] = d;
pts[y] = pts[size-1];
size = size - 1;
}
}
When I am entering the input array as :-
3 8 2
5.7 7.2 2.2
10.83 6.48 2.42
20.577 5.832 2.662
39.0963 5.2488 2.9282
74.283 4.72392 3.22102
141.138 4.25153 3.54312
268.162 3.82638 3.89743
509.507 3.44374 4.28718
968.063 3.09936 4.7159
My expected output should be:-
181.974 4.29686 3.57395
968.063 3.09936 4.7159
509.507 3.44374 4.28718
But, I am getting an output of:-
4.35 7.6 2.1
968.063 3.09936 4.7159
36.6506 5.8958 2.68145
Think I find out the problem, you don't update the min distance as soon as you find a new one during the cicle, try this:
cout << "distance between p[" << i << "] and " << "p[" << j << "]" << "is " << get_distance(pts[i], pts[j]) << '\n';
if ((a = get_distance(pts[i], pts[j])) <= min)
{
cout << "current min distance is between point[" << i << "]" << " and point[" << j << "]" << '\n';
min = a;
x = i;
y = j;
}
you've got to add this instruction:
min = a;
in order to update the min.
Otherwise it will works only for some edge cases.

Overloading operator< to (0, 1) = (0, 1) and (0, 1) = (1, 0)

How can i change the operator< to make my logic work?
Im trying like this, but it is not working.
struct simpleLink {
int orig;
int dest;
bool operator<(const simpleLink& otherLink) const
{
if(orig == otherLink.orig)
return dest < otherLink.dest;
else if (orig == otherLink.dest)
return dest < otherLink.orig;
else
return orig < otherLink.orig;
}
}
From my point of view it should be working, but it isn't...
When i have a set of simpleLink and i insert (0, 1) and then i try to insert (1, 0) , it should not insert
Example:
int main() {
set<simpleLink> test;
simpleLink secureLink;
secureLink.orig = 0;
secureLink.dest = 1;
simpleLink secureLink2;
secureLink2.orig = 1;
secureLink2.dest = 0;
cout << secureLink.orig << " " << secureLink.dest << endl;
cout << secureLink2.orig << " " << secureLink2.dest << endl;
test.insert(secureLink);
test.insert(secureLink2);
cout << "Test Size:" << test.size() << endl;
return 0;
}
Output is:
0 1
1 0
Test Size: 2
The set's size should be 1.
If you wish for two items in a set to compare equivalent, the comparitor must produce equivalence for (a,b) or (b,a). Your function does not do that.
It would appear that you would like to ignore any two that compare equal and sort based upon the unequals?
For this you must choose how to order all orig and dest relative to each other!
The following works by sorting orig and dest for each link, and then comparing the smallest. Only if the smallest are equal do we compare the larger.
bool operator<(const simpleLink& that) const
{
auto this2 = std::minmax( orig, dest );
auto that2 = std::minmax( that.orig, that.dest );
return (this2.first != that2.first)
? (this2.first < that2.first)
: (this2.second < that2.second);
}
Examples:
(1 2) < (2 2)
(1 2) < (1 3)
Hope this helps.

Lint warning Suspicious Truncation in arithmetic expression combining with pointer

I have the following code:
int array[128][3] = { /*lots of emelents there*/}
int* listIt = &array[0][0];
for(unsigned int index = 0 ; index < 128; index++)
{
printf("%x", array[index*3 + 1]);
}
but I got lint warnings like:
Suspicious Truncation in arithmetic expression combining with pointer
Then I changed the code to
array[index*3 + 1u];
still get warnings, can someone help me on that?
Try the following:
1) change literal 3 to unsigned, as you did for 1;
2) use indexing in 2D-array style: array[row][col] instead of array[row*col+1].
Lint's warning is correct you are going to index out of bounds with this code.
The line: printf("%x", array[index*3 + 1]); Will look at array[index * 3 + 1]. When index is 44, index * 3 + 1 is 133. array only has 128 int[3] elements this is out of bounds.
It appears that you are trying to print the addresses of the start of each int[] in array. Try this instead:
for(auto it = begin(array); it < end(array); ++it){
cout << *it;
}
Not sure but you may be trying to print the contents rather than the address of each int[3] in array. If so you could accomplish that like this:
for(auto it = begin(array); it < end(array); ++it){
cout << (*it)[0] << ", " << (*it)[1] << ", " << (*it)[2] << endl;
}