Triangle Challenge Solution and Question


#1

So, I seem to have been able to get the program to run without error and display the required text. My creation is here:

[code]#include <stdio.h>

float remainingAngle(float angleA, float angleB)
{
float angleAB = 180 - angleA - angleB;
return angleAB;
}

int main(int argc, const char * argv[])
{
float angleA = 30.0;
float angleB = 60.0;
float angleC = remainingAngle(angleA, angleB);
printf(“The third angle is %.2f\n”, angleC);

return 0;

}[/code]

My question is about the “return” in the function that I wrote. I used the Degrees program asa guide, and I don’t understand why it ends in “return fahr”. I ended mine in “return AngleAB”, which seems to work, but I don’t really understand what that is meaning or its purpose. Could someone enlighten me?


#2

Your creation is perfect.

A function can communicate the result of its computation to its caller in three distinct ways:

  1. Through a global variable - the function stores the result of its computation in the variable;
  2. Through an argument (of pointer type) passed to it - the function stores the result of its computation in the variable whose address is contained in the passed argument; and
  3. Through the return statement (as you have done.)

(There are other ways but they are beyond the scope of this discussion.)

Your function float remainingAngle (float angleA, float angleB) is using the return statement to pass the result of its computation back to the caller, which is the most preferable way (most of the time.)

Example:

// main.m
#include <stdio.h>

// Global variable
float _thirdAngle;

// Return result through a global variable
void remainingAngle (float angleA, float angleB)
{
    float angleAB = 180 - angleA - angleB;
    _thirdAngle = angleAB;
}

// Return result through an argument
void thirdAngle (float *result, float angleA, float angleB)
{
    float angleAB = 180 - angleA - angleB;
    *result = angleAB;
}

int main (int argc, const char * argv[])
{        
    float angleA = 30.0;
    float angleB = 60.0;
    remainingAngle (angleA, angleB);
    printf ("The third angle is %.2f\n", _thirdAngle);
    
    float result;
    thirdAngle (&result, angleA, angleB);
    printf ("Now the third angle is %.2f\n", result);
    
    assert (result == _thirdAngle);

    return 0;
}

#3

[quote=“ibex10”]Your creation is perfect.

A function can communicate the result of its computation to its caller in three distinct ways:

  1. Through a global variable - the function stores the result of its computation in the variable;
  2. Through an argument (of pointer type) passed to it - the function stores the result of its computation in the variable whose address is contained in the passed argument; and
  3. Through the return statement (as you have done.)

(There are other ways but they are beyond the scope of this discussion.)

Your function float remainingAngle (float angleA, float angleB) is using the return statement to pass the result of its computation back to the caller, which is the most preferable way (most of the time.)

Example:

[code]
// main.m
#include <stdio.h>

// Global variable
float _thirdAngle;

// Return result through a global variable
void remainingAngle (float angleA, float angleB)
{
float angleAB = 180 - angleA - angleB;
_thirdAngle = angleAB;
}

// Return result through an argument
void thirdAngle (float *result, float angleA, float angleB)
{
float angleAB = 180 - angleA - angleB;
*result = angleAB;
}

int main (int argc, const char * argv[])
{
float angleA = 30.0;
float angleB = 60.0;
remainingAngle (angleA, angleB);
printf (“The third angle is %.2f\n”, _thirdAngle);

float result;
thirdAngle (&result, angleA, angleB);
printf ("Now the third angle is %.2f\n", result);

assert (result == _thirdAngle);

return 0;

}
[/code][/quote]

Ah, that makes sense. Thank you.

I’m curious though, why is the using the return statement typically the preferred way?


#4

a couple of questions…

why do you use angleAB, wouldn’t it be more direct to use angleC?

also, why do we need to put as arguments of the function (float angleA, float angleB)? i thought these variables were already declared in the “main”? so we would only need to list them in the function, like (angleA, angleB)… ?


#5

[quote]why do you use angleAB, wouldn’t it be more direct to use angleC?
[/quote]Yes.

[quote]also, why do we need to put as arguments of the function (float angleA, float angleB)? i thought these variables were already declared in the “main”? so we would only need to list them in the function, like (angleA, angleB)… ?[/quote]You must follow the syntax of the language: If a function takes parameters, they must be declared in the parameter list.


#6

#include <stdio.h>

float remainingAngle(float measure1, float measure2)

{
float measure3 = 180 - (measure1 + measure2);
return measure3;

}

int main(int argc, const char * argv[])

{

float angleA = 30.0;
float angleB = 60.0;
float angleC = remainingAngle(angleA, angleB);
printf("The third angle is %.2f\n", angleC);

return 0;

}

Okay, here is my solution and my question. I originally tried to include angleA and angleB in my function but I had issues. So i just use measure1 and measure2 which worked fine. I assumed that angleA and angleB in main were just being used as variables to fulfill those arguments in the function. Is this wrong. I followed the degree program and it seemed that the names in the function were not necessarily the same as the variables used later. What would be the correct way to handle this? Did I complete it wrong?


#7

#include <stdio.h>

float remainingAngle(float angleA, float angleB)

{
float angleC = 180 - (angleA + angleB);
return angleC;

}

int main(int argc, const char * argv[])

{

float angleA = 30.0;
float angleB = 60.0;
float angleC = remainingAngle(angleA, angleB);
printf("The third angle is %.2f\n", angleC);

return 0;

}

I rewrote it using the names of the variables, both give me the correct answer. I would assume that this answer would be better. So then my question would be why did we change the name of things in the Degrees program?


#8

I don’t think you realize what is happening here. The variables in the function are different instances of the variables in main(). Just because the names are the same doesn’t mean they are the same. To see this more clearly, change the names of the parameters in the function to angle1 and angle2 and change the code to calculate and return angle3 instead of angleC. Then set a breakpoint on the return statement in the function.

When you run your program and hit the breakpoint, you will see two frames in the stack – remainingAngle() on top of main(). Click on each of the frames and you’ll see the variables in scope of that frame.

When remainingAngle is called, the parameters passed to the function are local variables initialized with the values passed through the parameters. The code inside the function does not access the variables in main(). It can’t see them.

I hope that makes sense.


#9

Mbspears is saying that every function has its own name scope.

Variables created in a given name scope are independent of the variables created in other name scopes.

Functions create name scopes, as do the braces {…}:

void FooBar (T1 bar1, T2 bar2) 
{
     if (...) {
         ...
     }
     else {
         ...
     }
}

void FooBar /* [start of new name scope] */ (T1 bar1, T2 bar2) 
{
     if (...) { // [start of new name scope]
         ...
     } // [end of name scope]
     else { // [start of new name scope
         ...
     } // [end of name scope]

} /* [end of name scope] */

Thus this is legitimate but confusing code:

void Foo (int v1, double v2)
{
   {
      char v1;
      void *v2;
   }

   if (1) {
        char v1 [3];
        void* v2 [5];
   }
   else {
        int v1 [3];
        double v2 [5];
   }
}

#10

I have a question regarding coding style. Instead of doing the function in two steps i just made it a one-liner:

float remainingAngle(float angleA, float angleB)
{
    return (180-(angleA+angleB));
}

Is that considered “dirty” coding because i see everybody else did it in two steps?
Is it more efficient in other ways than just saving typing some characters?
Or doesn’t it matter at all and is just a matter of taste?


#11

[quote]float remainingAngle(float angleA, float angleB) { return (180-(angleA+angleB)); }[/quote]
That is nearly perfect. Outer parentheses are redundant though.

float remainingAngle (float angleA, float angleB) { return 180 - (angleA + angleB); }
Even better:

float remainingAngle (const float angleA, const float angleB) { return 180 - (angleA + angleB); }const specifier ensures that you can’t accidentally change the values of the parameters.

For example:

if (angleA = 0) // Oops! should be angleA == 0
{
   ...
}

#12

Thank you ibex10, those were two valuable hints, i really appreciate that and this combo of book and community is excitingly great fun and a very effective way to learn!