Issues of getting stuck into infinite loop while iterating through vectors - c++

I want to search through a vector of pairs and in order to do so..i am doing the following:
vector<pair<double ,double> > vec_pairs;
for(vector<unsigned int>::size_type j = 0; j != vec_pairs.size(); j++ )
{
if(vec_pairs[j].first==12.6)
{
int z=7;
continue;
}
}
However my problem is...upon doing this...i am getting stuck in an infinite loop...
Can anyone help me in resolving the problem

First of all, the code that you posted works well 'as it is'.
The only reason for such type of a code to go into infinite loop is to modify j inside the loop.
If you increase j inside the loop, you will probably not get stuck because you will go out of bonds and might have your code crash.
for(vector<unsigned int>::size_type j = 0; j != vec_pairs.size(); j++ )
{
if(vec_pairs[j].first==12.6)
{
j++;//You will go out of vector bonds and might get an error here.
continue;
}
}
However, if you do something like this:
for(vector<unsigned int>::size_type j = 0; j != vec_pairs.size(); j++ )
{
if(vec_pairs[j].first==12.6)
{
j--;//j is decreased each time you get in here, so you will be stuck on one element,
continue;
}
}
Then you will get stuck inside, because when you go into the if statement (say, on element 7), j will decrease to 6, then you will continue the loop, j will increase back to 7, you will go inside the if again, and so on.

I have tested your code in codepad. Check it here! And it is working fine. Check the value of the variable j while debugging. As SingerOftheFall said, It might be getting decremented or reset somewhere. It can also go on an infinite loop if you are adding elements inside the loop which increase the value of vec_pairs.size() and the condition j != vec_pairs.size() will never be true in that case. Can't find anything wrong in the code you given.

Related

Comparing indexes in arrays/vectors

I just completed a project through Codecademy, and I couldn't for the life of me figure it out. I went and looked at the example solution and it contained code that I didn't even know you could do and I cannot figure out how it works.
There is a nested for loop, and the user takes advantage of adding the indexes together?? Or is comparing them?? I've just never seen it done, to be quite honest and I have looked for an explanation of what exactly is happening and I can't find one.
`
for (int i = 0; i < text.size(); ++i) {
int match = 0;
for (int j = 0; j < word.size(); ++j) {
if (text[i+j] == word[j]) {
++match;
}
}
`
The project was a C++ program where you had to bleep a word out of any phrase that was input into the program. I just don't understand what "text[i+j]" accomplishes? How do you add two indexes together in a for loop?? Does it add?? Does it compare?? But comparison doesn't make much sense to me either??
Here is a link to the github repository as well, so you can see the entire program: https://github.com/Codecademy/learn-cpp/tree/master/8-references-and-pointers/bleep
Since you're learning, the easiest way to figure this out is to write out exactly what is happening. Take text=="Hello, World and word=="World", and work out on paper how this code runs. For what values of i and j will match be incremented?

Why does the line "subsets.push_back(n);" give me an error in the following code?

I want to find the power set of a set of numbers and there is some issue I can't figure out with the code. What changes should I make??
vector<vector <int>> subsets={{}};
for(int i=0; i<a.size();i++){
int elem = a[i];
for(int j=0;j<subsets.size();j++){
vector<int> prev = subsets[j];
vector<int> n = prev;
n.push_back(elem);
subsets.push_back(n);
}
}
I am getting the following error :
""terminate called after throwing an instance of 'std::bad_alloc'""
As mentioned in comment:
[You code contains an] infinite loop. You are calling
subsets.push_back inside loop, so subsets.size is increased at
every iteration of loop and it cannot be stopped, until exception is
called due to lack of memory.
Exception std::bad_alloc is thrown because the process is trying to allocate a too large memory block (as deemed by the OS) - there are ways around this but this is not the issue here, the issue is the infinite loop as already pointed out.
To avoid that particular issue you could use a range-based for loop instead (and avoid the push_back within the loop), such as:
for(vector<int> prev : subsets){
//do stuff...
}
Remember that the loop condition is evaluated in its entirety on each iteration.
You're expanding subsets inside the loop, so j will always be less than subsets.size().
This means that the loop will never terminate - at least not until you run out of memory or encounter some other "external" problem.
Save the limit before the loop instead:
const int limit = subsets.size();
for(int j = 0; j < limit; j++){
//...

C++ Assignment don't work

Sorry for this very simple looking problem, but I have no idea what causes it:
In a C++ project I have a loop in a loop in a loop and have to leave the inner two so I have a variable for a query. In the first iteration it works fine, but in the second the assign from dtime to abbruch does not work. In the Debugger dtime has correctly the value "1" and abbruch "0" but this stays after the assignment. Both are of type long.
for (sect = 0; sect <= sections; sect++)
{
abbruch = 0;
for(line = 0; line < maxlines ; line ++)
{
abbruch = dtime[sect][0];
if(abbruch != 0)
{
break;
}
for (index = 0; index < 30; index ++)
{
if (complicated query)
{
dtime[sect][0] = DiffTime[maxlines * sect + line];
break;
}
}
}
}
I use VS2012 Ultimate.
Has anyone an idear how this can happen ot how to solve it?
Did you maybe mean to put this?
abbruch = dtime[sect][line];
(line instead of 0)
But also what Bathseba said is true. A break will only break one for-loop.
break will only take you out of the current for loop. In your case, the loop over index will not be called following a break when abbruch != 0 as that break will take you out of the loop over line. The other break statement will take you out of the loop over index.
That's the rationale, but, by far the best thing to do is to step through with a debugger. I wouldn't use break statements in this way as it's too confusing. Consider breaking the triple loop structure into function calls using return statements in place of breaks.
Also, it's a good idea to localise the interating variables in the for loops, e.g.
for (int sect = 0; sect <= sections; sect++)

Invalidating loop bounds

I've recently inherited a project primarily done in C++, so this is my first real exposure to it. I'm wondering if I may have a problem erasing a vector's elements from within a loop bounded by the vector's begin() and end().
Here's (essentially) what I've been trying to do:
for (vector<double>::iterator i = distance.begin(); i < distance.end(); i++) {
for (vector<double>::iterator j = i + 1; j < distance.end(); j++) {
/* code to assemble *i, *j, and some other values, say *x & *y
(also iterators) assumed to be in the distance vector */
vector< vector<double >::iterator remove;
remove.push_back(i); remove.push_back(j);
remove.push_back(x); remove.push_back(y);
sort(remove.begin(), remove.end());
for (int r = remove.size() - 1; r >= 0; r--) {
distance.erase(remove.at(r));
}
}
}
For what I'm testing it on, this appears to work. However, I'm concerned that's just because of a fluke and this solution shouldn't be used. Does distance.end() get reset at the beginning of each loop, or does C++ just check with the initial value?
for-loop will evaluate i < distance.end() on each loop. The problem is in distance.erase, it will invalidate i, so the result of i++ is undefined.
distance.end() is always accurate to the current state of the vector.
for() loops always re-evaluate the condition on every loop.

Beginner for loop problem

[EDIT]Whoops there was a mistake in the code, and now all the responses to the question seem bizzare, but basically the for loop used to be, for(i=0; i<15; i++). I also edited to make the question more clear.[/EDIT]
I am trying to make a for loop, that checks a 16 element array, so it loops from 0 to 15. I then use the i variable later, however sometimes i == 16, which causes problems by being out of bounds.
I have a solution but it doesnt seem elegant, which makes me think I am missing something. I've tried while loops, but I can never get any loop to go from 0 to 15, and never end at a value greater than 15.
Is there any way to make a loop go and check all 16 elements of the array, while never being greater than 15 at the end of the loop?
int i;
for(i=0; i<16; i++)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
if (i == 16)
{
i = 15;
}
I suggest using some other variable other than i after your loop is finished. The criteria of using a for loop instead of a while loop is that you know beforehand exactly how many times a for loop will execute. If you already know this, just set some other variable to the ending value of your loop and use it instead of giving i a dual purpose.
int j = 15;
for(int i=0; i <= j; i++)
{
someClass.array[i];
}
// continue on using j, which value hasn't changed
Well for starters, your sample code loops from 0 to 14. But if you loop from 0 to 15, naturally i has to be 16 before the loop can end. What happens is it becomes 16, THEN your loop notices it's out of bounds and breaks out. If you want it to end at 15, honestly the easiest thing to do is just decrement just after the loop end.
i is incremented on last check to be 16, which is not less than 15, so loop exits with i being 16.
Maybe it's useful to know that:
for (before; check; after) { body }
it's the same as:
before
while(check) {
body
after
}
If you think at your for loop in that term, maybe you'll find out easily why i, at the exit, is 16.
There seems to be some fundamental flaws in your approach.
You shouldn't really use an index variable outside the scope of the loop.
You should use a variable or function to determine the limit of the loop.
It would be better to use iterators instead of numeric indexes.
Generic algorithms can remove the need for loops.
Just my $0.02.
So - if you're checking a 16 element array, normally you'd do this:
for(i=0; i<16; i++)
How for works, is it starts with the first statement of three:
i=0
Then it does your check, in the second statement:
i < 16 // True here, since 0 < 16
That happens before your loop. Then it runs the block of your loop with that set:
someClass.array[i]; //0
Finally, it does the final statement:
i++
Then it repeats the second and third statements, in a sequence.
Before the last run, i == 14, then it does i++, setting i to 15, and executes the block. Finally, it does i++, setting:
i==16
At this point, the condition is no longer true:
i < 16 // False, since i==16
At this point, your block does not execute, but i is still set to 16.
You must have missed something.
In this loop it wouldn't even hit 15, you'd need to say i <= 15, as soon as i = 14 it'd run once and bail.
The for loop is equivalent to the following while loop:
i = 0;
while(i < 16) {
someClass.array[i];
i++;
} // while
i needs to reach 16 to get out of the loop correctly.
Technically there are ways of writing the loop such that i is 15 on exiting the loop, but you shouldn't do them:
int i = 0;
while (1) {
someclass.someMethod(i);
if (i < 15) {
i++;
} else {
break;
}
}
Yes, it does what you ask. But the flow is horrible.
You cannot accomplish this with the built-in loop structures, and as Bill The Lizard said, you probably don't really want to reuse the for-loop variable.
But, if you really want to, here's a way to do it. The trick is to put the loop condition in the middle of the loop:
int i = 0;
while (true)
{
someclass.array[i];
if (i == 15)
break;
++i;
}
The key issue to understand here is that there are 17 different answers to the question "What value of i causes the test to succeed?". Either i can be in {0, 1, ..., 15}, or no value of i causes the test to succeed, which is denoted by i == 16 in this case. So if i is restricted to only 16 values, the question cannot be answered.
There are legitimate cases where you do not want to go past the last valid value. For instance, if you had 256 values and for some reason you only have one byte to count with. Or, as happened to me recently, you want to examine only every ith element of an array, and the last addition to your iterator takes you far beyond the end of the array. In these cases loop unrolling is necessary.
However, for this problem it would be cleaner to use a flag:
bool flag = false;
for (int i = 0; i < 15; ++i)
{
someClass.someMethod(i);
if (someClass.Test())
{
flag = true;
break;
}
}
Then it's clear whether or not the test ever succeeded.
If your loop terminates natuarally, rather than with a break, i will be 16. There's no way to avoid this. Your code is perfectly acceptable if what you want is for i to end up as 15 or less:
int i;
for (i=0; i<16; i++) {
someClass.someMethod(i);
if (someClass.Test())
break;
}
if (i == 16)
i = 15;
Anything that changes i from 16 to 15 after the loop body will do:
if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */
and so on.
However that assumes that i is going to be used for something meaningful as a post-condition with respect to that loop. I find that's rarely the case, people tend to re-initialize it before re-use (such as another for loop).
In addition, what you are doing makes it very difficult (impossible, even) to figure out as a post-condition, wheteher your loop terminated normally or whether it terminated prematurely because someClass.Test() returned true for i == 15. This means using i to make further decision is fraught with danger.
My question would be: Why do you think you need to leave i as 15 or less?
I am trying to make a for loop, that
checks a 16 element array, so it loops
from 0 to 15. I then use the i
variable later, however sometimes i ==
16, which causes problems by being out
of bounds.
You need to check for the case where your for loop didn't break, because this information determines whether or not whatever you wanted to do with i is valid.
There are a couple of ways to do this. One is to keep track of it in a bool, such as "foundClass" or "testSucceeded". Default it to false, then set it to true on your break. Enclose any uses of i later in the function in "if (foundClass) { }" blocks.
Another is to just do what you've done. Although your fallback doesn't look right at all. If you're setting i to 15, you're lying to your code and telling it that someClass.Test() succeeded for i == 15, which isn't true. Avoid setting the value to something that's wrong just so your code doesn't error later on. It's much better to put bounds checks around the actual usage of i later in the code.
for(int i=0; i<17; i++)
{
if(i<16)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
else if(i==16)
{
i=15;
}
}
if you say you have an array with 16 elements, you don't have to define that, use the array to get that info (DO NOT DUPLICATE INFORMATION)
afterwards if you want to get the last index again use the array to get that info.
for(int i = 0; i < myArray.length; ++i){
myArray[i].somemethod();
}
// lastindex = myArray.length-1;