Exiting a loop early

Hi,

I'm trying to print out the first number in a loop that doesn't exist inside an array of numbers. I'm using a double nested for loop. The methods I've tried are these....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  for (int i = 1; i < max; i++){
        
        for (int j = 0; j < booked; j++){
        
      
            if (i != arr[j]){
            
            cout << i;
            break;
           
            }
        
            
        }
    
        
  }


and the other attempt only changed break to a return 0.

The goal is to have it say, okay. What's i? i is 1. Does 1 exist at arr[j] anywhere within its scope? Yes, it does. I will move on and check i at 2. 2 does not exist anywhere in the scope of arr[j] so I will print out 2 and stop there without checking i anymore.
Last edited on
"Does 1 exist at arr[j] for all valid j"

That's not a !=, that's an "=="

Your code will break for any arr[j] that is not "i".

Now, of course, you have to figure out that little puzzle. If the test is reversed to "==", how to you "remember" that all of j went by without finding an i.

Rather than just feed you that answer, see if you can turn that English into logic.

Note: Hint: "remember" implies some variable, possibly one you haven't yet created.
As you've figured out, break can only be used to break out of one level of loops.. What I would rather do is factor out the inner loop into a function.

The goal is to have it say, okay. What's i? i is 1. Does 1 exist at arr[j] anywhere within its scope? Yes, it does. I will move on and check i at 2. 2 does not exist anywhere in the scope of arr[j] so I will print out 2 and stop there without checking i anymore.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Example program
#include <iostream>
#include <string>

bool in_array(int value, int arr[], int size)
{
    for (int i = 0; i < size; i++)
    {
        if (arr[i] == value)
            return true;
    }
    return false;
}

int main()
{
    using std::cout;
    
    int arr[] = { 1, 9, 3, 4, -1, 7, 11, };
    
    for (int i = 1; i < 10; i++)
    {
        if (!in_array(i, arr, 7))
        {
            cout << i << " is NOT in array\n";
            break;
        }
    }
}


2 is NOT in array
 


Of course, the algorithmic complexity of this can be reduced by sorting first.

<Note: I have edited my post. My previous response slightly misread your question.>
Last edited on
I'm not entirely sure what you're after. Maybe something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

const int MaxSize = 20;

int find_lowest_missing_value(int arr[], int booked) {
    for (int n = 1; n <= MaxSize; ++n) {   // I'm assuming <= is correct here
        int i = 0;
        for ( ; i < booked; ++i)
            if (n == arr[i])
                break;
        if (i == booked) // didn't hit the break so n is not in arr[]
            return n;
    }
    return -1;
}

int main() {
    int arr[MaxSize] {4, 2, 3, 6, 1, 5, 8, 10, 9}; // 7 is missing
    int booked = 9;
    std::cout << find_lowest_missing_value(arr, booked) << '\n';
}

Your names are a little odd. "booked" seems specific to your application, but "arr" is next to meaningless!

If you tell us what you are trying to do instead of how you are trying to do it, there may be a better way, such as an array of MaxSize bools that are initially false but set to true when the number is in use.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 for (int i = 1; i < max; i++)
{        
        for (int j = 0; j < booked; j++)
          {       
            if (i != arr[j])
               {            
                  cout << i;
                  goto done;        //everyone hates goto.  But it works for this problem cleanly    
//my rule on goto: never go backwards, only forwards.  Backwards causes the bulk of the issues people hate. 
            }                   
        }           
  }
done:

Putting the code in a function to use a return is 
*exactly the same thing* (both jump out when found) and looks better, so unless that is not 
an option, its the better way to code it. 
Last edited on
>>If you tell us what you are trying to do instead of how you are trying to do it...

Fair enough.

It's a challenge. For personal growth. No sort of grade or competition.

The challenge is this.

Input: two integers X and Y. X is the total number of rooms in a hotel. Y is the number of rooms booked.
next line of input the assigned room numbers of the Y amount of booked rooms.

Output: Any available room number.

Sample test:

Input
100 5
23
1
5
31
3

Output
15


I am 80% confident I could do this with the random include, but I always try to learn how to do stuff with as few libraries as possible because when fall semester starts, that's what my teachers will require of me.
Last edited on
goto done:

That's slick.
That's slick.

It's a basic idiom, but totally inappropriate in this case.
It was slicker'n a frog's stomach.
If'n you insist. :-)

I am 80% confident I could do this with the random include

What would you use that for?

And what are the constraints of the problem? I.e. how big can X get?
Last edited on
Ha.

Appreciate all the help. I passed all the challenge's test, so this thread is complete.
I always try to learn how to do stuff with as few libraries as possible because when fall semester starts, that's what my teachers will require of me.

Understandable. However, you should learn to see the difference between what and how. Writing code yourself and using library are both "how". It is likely that the code in the library is more efficient than the code that you write. It is important to learn what is in the (Standard) library and how to use it.

That gets back to the "what". You had decided that you need nested loops. Then you had an issue with the "how".

Ganado's suggestion (and its library-based version below) emphasizes that the "what" is not two loops, but:
FOR each room in hotel
  IF the room is free
  THEN show room and break
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <algorithm>

int main()
{
    size_t Rooms {100};
    size_t booked[] { 23, 1, 5, 31, 3 };
    
    // Do we have a free room?
    for ( size_t room = 1; room <= Rooms; ++room )
    {
        if ( std::end(booked) == std::find( std::begin(booked), std::end(booked), room ) )
        {
            std::cout << "Room " << room << " is free\n";
            break;
        }
    }
}

The Is room free? is likely to be implemented with a loop, which makes you have that "nested loop", but the important thing is to see and remember what each loop is doing.


However, there is no need to have nested loops. As part of the "what" you have to decide how you store your data. That does affects how you have to operate on that data. Below each room is listed in "rooms" as being either booked (true) or free (false).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<bool> rooms( 100, false ); // empty hotel

    size_t booked[] { 23, 1, 5, 31, 3 };
    for ( auto room : booked ) rooms.at( room-1 ) = true; // mark booked rooms

    // Do we have a free room?
    auto it = std::find( rooms.begin(), rooms.end(), false ); // one loop
    if ( rooms.end() == it ) {
        std::cout << "We are full.\n";
    }
    else {
        std::cout << "Room " << 1 + ( it - rooms.begin() ) << " is free.\n";
    }
}
I would have to use a c++ 11 compiler for that right?

I read about the find, end and begin method while I was one step away from punching stuff that didn't need to be punch, and it didn't work on my compiler.

*edit* I have since installed a c++ 11 compatible compiler**

How do you have user input for a size_t vector?
Last edited on
? Not sure what you are asking, is it a vector<size_t> ? That is just an integer type..

for(... )
{
cin>> data;
vec.push_back(data);
}

or if you knew how many you had, more efficiently:
vec[index] = data; //but you had to have preallocated all the locations so index would work.
Input is tedious:
1
2
3
4
5
6
7
8
9
10
11
    size_t N {};
    if ( !(file >> N) ) return 1; // read number of rooms
    std::vector<bool> rooms( N, false ); // create empty hotel

    if ( !(file >> N) ) return 2; // read number of booked rooms
    size_t room {};
    while ( 0 < N && file >> room ) // read bookings
    {
        rooms.at( room-1 ) = true;
        --N;
    }

The file must be an istream object.
Topic archived. No new replies allowed.