Pass by Reference

Pages: 12
Hi,

I am asked to pass by reference to this method, but seem to be meeting with some errors. If i remove "&" from int solve(P &p) it would work, but i need to use pass by reference with the test.cpp file below that cannot be edited for submission purposes.

Could someone please help me out with the code below and maybe point to me why it is not working? I know this is bad coding practice, with including a .cpp to another .cpp but have no choice as i am following my lab submission requirements so hope everyone can overlook that part as much as it looks bad (even i think so).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//abc.cpp
int solve(P &p) {
try{
countIndex++;
        
                
    }catch(L l){
            cout << "L() caught " << endl;

            }
    catch(H h){
            cout << "H() caught " << endl;
            
            }
return countIndex-1;
}


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
//test.cpp
#include<iostream>
using namespace std;
class L {};
class H {};
class P {
int val;
public:
P(int Val) {
val = Val;
}

void guess(int g){
if(g<val) throw L();
if(g>val) throw H();
return;
}
};

#include "abc.cpp"

int main()
{
    for(int i=0; i<=1280; i++)
    if(solve(P(0,1280,i)) != i) cout << "testing\n";
   
 system("pause");
  return 0;
} 

You cannot bind a temporary to a non-const reference.

In english,

On line 25 you are constructing a temporary P and passing that to solve.
But solve's parameter is a non-const reference.

This isn't allowed by the standard.

To fix, you need to create a named instance of P and pass it to solve.

ie,

P temp( 0, 1280, i );
solve( temp );

This was always a fuzzy area for me as well.

You say that a temp object as a non-const reference isn't allowed, but it is allowed for a const reference, right?
Yes.

It was decided that if the programmer made a formal parameter a non-const reference, they clearly intended it to modify the caller's actual parameter. But if the caller passed a temporary, the modification would obviously be thrown away immediately as the temporary would be destroyed.

It was rather arbitrarily decided that there is no reason why a programmer would want to do this, so they made the rule that temporaries cannot bind to non-const references so that it would generate a compile error. The workaround of course is to create a named object.
Yeah, i tried the method mentioned by jsmith and it works considering we didn't need to use "&". So other than modifying test.cpp, is there anything i can do to abc.cpp besides removing "&" from int solve(P &p)?
make the parameter a const reference.

int solve( const P& p )

also solves the problem.
Thanks i tried, but it doesn't seem to work in BloodShed Dev C++.

Can i ask some logic problem because currently i am trying to guess a value of a secret number, so if say my guess value is 10 and my secret number is 100.

So 10<100, hence a class will be thrown and will be caught by my solve method. So i have to keep guessing till i get my secret number by resetting boundaries of my min and max value for my random number generator. So will i be able to call a method in the catch block? Not sure if i make any sense, but basically i have to guess the secret number eventually and not sure if my code is doing it right.

This is my error messages:
guessVal 447
H() caught
new guessVal 446
Abort (core dumped)


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
30
31
32
33
34
35
36
37
//abc.cpp
int solve(P p) {
    srand((unsigned)time(0)); 
    
    int guessVal=0;
    int max=p.getMax();
    int min=p.getMin();
    int range=max-min;
   
try{
                  
                  
 guessVal = (double) rand() / (RAND_MAX + 1) * (max-min) + min; 

    cout << "guessVal " << guessVal << endl;
           p.guess(guessVal);  
          
    }catch(L l){
            cout << "L() caught " << endl;
            srand((unsigned)time(0)); 
            min=guessVal+1;
            guessVal = (double) rand() / (RAND_MAX + 1) * (max-min) + min; 
            cout << "new guessVal " << min <<endl;
            p.guess(guessVal);  
            }
    catch(H h){
            cout << "H() caught " << endl;
            srand((unsigned)time(0)); 
            max=guessVal-1;
            guessVal = (double) rand() / (RAND_MAX + 1) * (max-min) + min; 
            cout << "new guessVal " << max <<endl;
            p.guess(guessVal);  
            }catch (...) { cout << "default exception"; }

return guessVal;

}


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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
using namespace std;
class L {};
class H {};
class P {
int min, max, val, cnt, lgn; // min <= val <= max
public:
P(int Min, int Max, int Val) {
min = Min;
max = Max;
val = Val;
cnt = 0;
lgn = 0;
int i=max-min+1;
while(i/=2) lgn++;
}
int getMin(){ return min; }
int getMax(){ return max; }
int getLgn(){ return lgn; }
int getCnt(){ return cnt; }
void guess(int g){
if(++cnt > lgn) return;
if(g<val) throw L();
if(g>val) throw H();
return;
}
};

#include "abc.cpp"


int main()
{
    for(int i=0; i<=0; i++)
    if(solve(P(0,1280,i)) != i) {
                          
                          cout << "wrong answer\n";}else{
                               cout<< "correct answer\n";
                               }
   
 system("pause");
  return 0;
} 
Last edited on
Btw, int solve(P &p) works in SUN C++ environment for some reason.
Noncompliant compilers I guess. The const reference has to work, otherwise most of the STL won't compile.

You can do whatever you want inside a catch block, however, the catch block is not part of the try block, so if you do something inside the catch block that throws, the catch block will not catch it. eg,

1
2
3
4
5
try {
    throw 4;
} catch( int x ) {
    throw 5;
}


The catch block will catch the 4 but not the 5.

Your program is dying because p.guess() is throwing an H or an L and you have nothing to catch it. (An uncaught exception causes the program to abort, just as you are seeing).

(NB, if you have learned about const references, you should be catching by const reference, not by value. If you haven't learned about them, then ignore previous sentence).
Your program is dying because p.guess() is throwing an H or an L and you have nothing to catch it. (An uncaught exception causes the program to abort, just as you are seeing).


So how should i solve this because i think my program is throwing an L or H class causing it to fail as i can't guarantee that the next guess value would be equivalent to the secret value.

Should i not be calling the p.guess() in the catch blocks, if not how do i keep guessing?

(NB, if you have learned about const references, you should be catching by const reference, not by value. If you haven't learned about them, then ignore previous sentence).


Also, just curious as to how do i catch by reference?
Last edited on
1
2
3
4
5
6
7
8
9
10
11
// pseudo-code:
while( guess-is-not-correct ) {
    try {
         do-guess;  // this will throw H or L if guess is not right
         // if we get here, the guess must have been right
    } catch( const H& h ) {
        // modify max value;
    } catch( const L& l ) {
        // modify min value;
    }
}


Thanks it works, but it seems that i still do my secret answer wrong sometimes. Is there anyway, i can make sure that my guess values will never give me a wrong answer? Maybe my logic of generating a random number is not good enough? The range is too huge?

Is there any improvement i can make from my formula perhaps? Can i also ask what is the difference between const H& h and H h in the catch condition?

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
30
31
32
//abc.cpp
int solve(P p) {
    //srand((unsigned)time(0)); 
    
    int guessVal=0;
    int max=p.getMax();
    int min=p.getMin();
    int range=max-min;
    int j=0;
   while(true){
try{
                  
         srand((unsigned)time(0));          
         guessVal = (double) rand() / (RAND_MAX + 1) * (max-min) + min; 

           p.guess(guessVal);  
           break;
    }catch(L l){
            //cout << "L() caught " << endl;
            min=guessVal+1;
          
            }
    catch(H h){
            //cout << "H() caught " << endl;
            max=guessVal-1;

            }catch (...) { cout << "default exception"; }
j++;
}

return guessVal;
}
Last edited on
First of all, you should only do line 13 once in your program. Move it to main().

Line 8 is wrong, but you never actually use the range. The range of numbers between a and b (a<=b) is b - a + 1.

Line 14 is way more complicated than it needs to be. To generate a random number in the range [ a...b ] inclusive, do rand() % range + min. rand() % range generates a random number in the range 0 ... range - 1. Then + min translates the range to min ... min+range-1.
Since range = max-min+1, min+max-min+1-1 = max.
So if for example rand()%10 + 1 --> This means that the range will be from 1 to 10? Am i right?

I have made some changes and added srand((unsigned)time(0)) before the while loop is that okay? I also used the formula of rand()%range+min but it seems to generate more wrong guess values than my previous method.
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
30
31
32
int solve(P p) {
    int guessVal=0;
    int max=p.getMax();
    int min=p.getMin();
    int range=max-min+1;
    int j=0;
    srand((unsigned)time(0));  
   while(true){
try{
                  
                 
         guessVal = rand() % range + min;
         
         //(double) rand() / (RAND_MAX + 1) * (max-min) + min; 
         //cout << "guessVal " << guessVal << endl;
           p.guess(guessVal);  
           return guessVal;
           //break;
    }catch(L l){
            //cout << "L() caught " << endl;
            min=guessVal+1;
          
            }
    catch(H h){
            //cout << "H() caught " << endl;
            max=guessVal-1;

            }catch (...) { cout << "default exception"; }
}


}
So the remainder of dividing any number by 10 must be in the range 0 to 9 inclusive,
so rand() % 10 is [0...9]. Add 1, and it becomes [1...10].

srand() is fine where you have it.

You have to recompute the range every time you change min or max. (so on lines 22 and 27).
I totally forgot about changing the range at the catch block! Thanks! But still the accuracy of it varies a lot. Is it possible to guess it by 10 tries? Any smarter way to do this?

So i edited this two parts of the code to re-calculate the range:

1
2
3
4
5
6
7
8
catch(L l){
            min=guessVal+1;
            range=max-min+1;
            }
    catch(H h){
            max=guessVal-1;
            range=max-min+1;
            }

Last edited on
The optimal algorithm is a binary search algorithm.

Always guess exactly halfway between min and max.

If the range is R, then it takes log R guesses maximum.

The optimal algorithm is a binary search algorithm.


Do you have a sample algorithm?
I did this so far, and it seems to work sometimes and still provides quite a bit of wrong guess values for me. Am i doing something wrong?

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
30
31
32
33
34
35
36
37
38
int solve(P p) {

    int guessVal=0;
    int max=p.getMax();
    int min=p.getMin();
    int range=max-min+1;
    int j=0;
    srand((unsigned)time(0));  

   while(j>=0){
try{
                  
         range=max-min+1;        
         if(p.getCnt()>1){
               guessVal=(rand() % range + min);           
         }else{
                guessVal = range/2;
         }
        
        
           p.guess(guessVal);  
           return guessVal;

    }catch(L l){

            min=guessVal+1;

            }
    catch(H h){

            max=guessVal-1;

            }catch (...) { cout << "default exception"; }
}

j++;

}
Last edited on
Always guess exactly halfway between min and max.


Do you have a sample algorithm?


To guess half way between min and max? how about: (max-min)/2+min
or, more specifically range / 2 + min

I have a game I made, where the game selects a secret number between 1 and 1000, and I have to guess it. When I play I use the same idea of half of range. (or close to)

I start off with 500. Higher, I go 700, or lower i go 300. (close enough to half for a non-computer brain..) I then devide the range roughly in half again, and keep doing so untill i zone in on the answer.

Usually I get it inbetween 9 and 13 tries. And that's just with my brain power.
Last edited on
Pages: 12