user3460758
user3460758

Reputation: 987

Outputting returning a struct from a function

so I'm trying to output a struct from a function in C. The code so far is:

//Step 1: Create a volume function that outputs a volume structure
//Step 2: Input boat dimensions from main
//Step 3: Use outputted volume values to calculate centre of gravity/buoyancy
//Step 4: Use values 

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//Struct to fill with the values calculated in the submerged_volume function
struct vol {
    double V, Uc, Vc;
    };

struct vol submerged_volume(double L1, double L2, double Lavg, double H) {

    double C, delta, a, b, d;
    double theta, theta_rad, theta_min, theta_lim, theta_lim2, theta_lim_deg;
    double Ug1, Ug2, Vg1, Vg2, V1, V2;
    double pi; 

    pi = 4*atan(1);
    C = sqrt(L1*L1 + L2*L2);
    delta = acos(L1/C);

    theta_lim = asin(H/L1);
    theta_lim_deg = (theta_lim/pi) * 180.0;
    theta_min = asin(H/C) - delta; 
    theta_lim2 = 0;

    //Calling the structure to fill with values
    struct vol volume;


    double V_sub, Uc_sub, Vc_sub;
    V_sub = 0;

    //Volume calculations

    for (theta == 0; theta <= 10; theta = theta + 0.5) {
        theta_rad = (theta * pi)/180.0;
        //if (H > L2) { 
        printf(" H > L2\n");                          //Case where H > L2
            if (theta_rad > theta_lim) {
                V_sub = Lavg * L2 * (L2/(2.0 * tan(theta_rad)) + L1 - H/sin(theta_rad));
                //Case of triangle plus rectangle
                V1 = Lavg * L2 * L2/(2.0 * tan(theta_rad));     
                V2 = Lavg * L2 * (L1 - H/sin(theta_rad));
                Ug1 = -(H/sin(theta_rad) - L2/tan(theta_rad) + L2 * (cos(theta_rad)/(3.0*sin(theta_rad/2.0))));
                Vg1 = -(L2 - sin(theta_rad/2.0) * (L2/(3.0 * sin(theta_rad/2.0))));
                Ug2 = -(L1 + H/sin(theta_rad))/2.0;
                Vg2 = -L2/2.0;           //b 
                }
            else if (theta_rad > theta_min) {
                V_sub = Lavg * tan(theta_rad)/2.0 * pow((L1 - L2 * tan(theta_rad) - ((H - L2/cos(theta_rad))/sin(theta_rad))), 2);
                //Case of a triangle only 
                V1 = V_sub;
                V2 = 0; 
                Ug1 = -1.0/3.0 * (2.0 * L1 + L2 * tan(theta_rad) + (H - L2/cos(theta_rad))/sin(theta_rad));
                Vg1 = -(L2 - tan(theta_rad)/3.0 * (L1 - (H - L2/cos(theta_rad))/sin(theta_rad) - L2 * tan(theta_rad)));
                }
            else {
                V_sub = 0; 
                }
            //}

            if (V_sub != 0) {
            Uc_sub = Ug2 - V1/(V1 + V2) * (Ug2 - Ug1);
            Vc_sub = Vg2 - V1/(V1 + V2) * (Vg2 - Vg1);
            //moment = m * g * (b*sin(theta_rad) - a*cos(theta_rad)) + (Uc * cos(theta_rad) - Vc * sin(theta_rad)) * Fa - d * Fm;
            //fN = -(f * Fm * cos(theta_rad));
            //friction = m * g - Fa - Fm * sin(theta_rad);
            }
        }
    volume.V = V_sub;
    volume.Uc = Uc_sub;
    volume.Vc = Vc_sub;



    /*
    volume.V = 110;
    volume.Uc = 10;
    volume.Vc = 10;
    */

    return volume;
    }

int main() {

    double L1, L2, Lavg, H;
    struct vol volume; 

    printf("Enter L1: \n");
    scanf("%lf", &L1);
    printf("Enter L2: \n");
    scanf("%lf", &L2);
    printf("Enter Lavg: \n");
    scanf("%lf", &Lavg);
    printf("Enter H: \n");
    scanf("%lf", &H); 

    volume = submerged_volume(L1, L2, Lavg, H);

    printf("V = %lf\nUc = %lf\nVc = %lf\n", volume.V, volume.Uc, volume.Vc);

    return 0;
    }

I first tried it using just one set value for theta (theta == 5), which worked perfectly. I don't know if I can do this but I basically want to put a value for V, Uc, and Vc for each value of theta as it goes through the for loop. Is this possible? I hope this is explained ok, let me know if more details are needed. Thanks in advance!

Upvotes: 0

Views: 96

Answers (2)

Joseph Quinsey
Joseph Quinsey

Reputation: 9962

Point #1: Your code has at least one bug, which may be the cause of your problem. A quick compilation gave me the following warnings:

 In function 'submerged_volume':
40: warning: statement with no effect
40: warning: 'theta' is used uninitialized in this function
35: warning: 'Vc_sub' may be used uninitialized in this function
35: warning: 'Uc_sub' may be used uninitialized in this function
19: warning: 'Vg2' may be used uninitialized in this function
19: warning: 'Ug2' may be used uninitialized in this function

In particular, on line 40:

for (theta == 0; theta <= 10; theta = theta + 0.5) {
           ^^
           want "=" here

Point #2: By the way, you should ignore the suggestions about submerged_volume using pointers rather than returning a struct, for two reasons.

  • The structure here is so small that it makes no difference.
  • The compiler will likely eliminate unnecessary copying anyway (e.g. by implicitly using a pointer).

Point #3: The OP clarified that he/she wished to return an array of structures. In this case we do need to add pointers, since arrays are not 'first class objects" in C. Something like:

In main():

 struct vol volume[21];
 // ...
 submerged_volume(L1, L2, Lavg, H, volume);
 // ...

In submerged_volume():

 void submerged_volume(double L1, double L2, double Lavg, double H, struct vol out[])
 // ...
 int i = theta * 2;
 // ...
 out[i].V  = V_sub;  // at bottom of loop
 out[i].Uc = Uc_sub;
 out[i].Vc = Vc_sub;

Or use the perhaps more common idiom:

 void submerged_volume(double L1, double L2, double Lavg, double H, struct vol *out)
 // ...
 out->V  = V_sub;  // at bottom of loop
 out->Uc = Uc_sub;
 out->Vc = Vc_sub;
 out++;

(Note my use here of the hard-coded 21 is a bad idea.)

Upvotes: 0

Andrey
Andrey

Reputation: 1561

I believe the proper way to achieve this is by passing output struct to the function either by reference or via a pointer:

// Declare
void submerged_volume(double L1, double L2, double Lavg, double H, struct vol& out);

// Use
struct vol volume;
submerged_volume(L1, L2, Lavg, H, volume);

Or via a pointer:

// Declare
void submerged_volume(double L1, double L2, double Lavg, double H, struct vol *out);

// Use
struct vol volume;
submerged_volume(L1, L2, Lavg, H, &volume);

Upvotes: 1

Related Questions