简体   繁体   中英

How can I return a struct if a condition is true and an int if the condition is false

First a simple example:

typedef struct
{
    char article[DIM_STRING];
    double price;
    char buyer[DIM_STRING];
}Order;

Order algorithm(int a, int b){
    if(a == b) return -1;   //Error
    else return ord;    //Returns the Order ord
}

The question is: is it possible to return an int OR a struct? If not how can I make an escamotage to avoid the problem?

I thought I could've use pointers and return a pointer BUT pointer must have a type.

You can break it down into two parts

  1. Let the function return an int value, where (usually), a return value of 0 indicates success and other negative values indicate different types of error.

  2. Take a pointer to the structure variable as one of the arguments. In case of success condition, fill the structure, and in the caller, based on the return value of the function call, the structure can be accessed to retrieve the value stored into it's members.

You can't have a function with a variable return type.

The common ways to handle the situation is to either:

1) use a numerical return value for error signalling and return the payload through a passed pointer

 int algorithm(Order *ret, int a, int b){
        if(a == b) return -1;   //Error
        else return *ret=ord, 0;    //Returns the Order ord
    }

2) or return a tagged struct (less common, in my experience, but it can generate slightly more optimal code if the payload is small); it it's tagged as successful, the rest of the struct is usable, otherwise it isn't

 struct taggedOrder { Order order; _Bool is_ok; };
 struct taggedOrder algorithm(int a, int b){
    struct taggedOrder r = { ord, 1 };
    if(a == b) return r.is_ok=0, r;   //Error
    else return r;    //Returns the Order ord
  }

if the function is of type Order it cannot return an int but you can do this:

Order error_value;
error_value.article=""; error_value.price=-1.0; error_value.buyer="";

Order algorithm(int a,int b) {
    if (a==b) return error_value;
    else return ord;
}

and later then you can check whether the return value is equal to ("",-1,"")

Variable return types do not exist in C.

You could do this:

Order algorithm(int a, int b, int *ok) {
  if(a == b)
     *ok = 0;
  else
     *ok = 1;
   return ord;    //Returns the Order ord
}

or simpler:

Order algorithm(int a, int b, int *ok) {
  *ok = (a != b)
  return ord;    //Returns the Order ord
}

and call it like this:

int ok;
someorder = algorithm(v1, v2, &ok);
if (ok)
  ... handle OK case
else
  ... handle not OK case 

or you could return a pointer to the order if it's OK and return NULL if it's not OK:

Order *algorithm(int a, int b) {
  if(a == b)
     return NULL;
  else
     return ⩝    //Returns the Order ord
}

and call it like this:

Order *someorder;
...
someorder = algorithm(v1, v2);
if (someorder != NULL)
  ... handle OK case
else
  ... handle not OK case 

There are many possibilities to achieve this. See also the other answers.

The question is: is it possible to return an int OR a struct?

No.

However, there is a workaround. Create a union that can contain your struct or an int. Then you create a wrapper struct containing one such union and one variable that you use to determine the return type. You can do like this:

struct myStruct {
   int a, b;
};

union myEnum {
    struct myStruct s;
    int i;
};

struct myContainer {
    union myEnum e;
    int retType;
};

struct myContainer myFunc() {
    struct myContainer ret;
    if(...) {
        ret.e.s.a = 42;
        ret.e.s.b = 99;
        ret.retType = 0;
    } else {
        ret.e.i = 55;
        ret.retType = 1;
    }
    return ret;
}

And then use it something like this:

struct myContainer x = myFunc();
if(x.retType == 0) {
     struct myStruct w = x.e.s;
     // Do whatever you want to do if a struct is returned
} else if(x.retType == 1) {
     int w = x.e.i;
     // Do whatever you want to do if an int is returned
} else { /* Error */ }

You can use a struct instead of a union. The only drawback is that it will use a little bit more memory.

This is a generic solution that you can use. If you think it clutters the code, you can instead add two fields to your existing struct:

typedef struct
{
    // Old fields
    char article[DIM_STRING];
    double price;
    char buyer[DIM_STRING];

    // The integer you want to return
    int integerValue;

    // Used to determine which fields to use
    int retType;
} Order;

There's no way to have a variable return type from a function in C.

One option is to modify the struct to include an int which indicates if the struct is valid or not.

typedef struct
{
    int valid;
    char article[DIM_STRING];
    double price;
    char buyer[DIM_STRING];
} Order;

Order algorithm(int a, int b)
{
    Order ord;
    ord.valid = -1;     //  assume an error has occurred
    if(a != b)
    {
        ord.valid = 0;
        // populate other members of ord
    }
    return ord;
}

This requires the caller to check, for example;

 Order result = algorithm(i, j);
 if (result.valid == 0)
 {
      // use members of result
 }
 else
    complain_bitterly();

Another is to add a third (pointer) argument to the function

 Order algorithm(int a, int b, int *valid)
 {
      Order ord;
      *valid = -1;
      if (a != b)
      {
          // populate members of ord
          *valid = 0;
      }
      return ord;
  }

  void caller()
  {
      int valid;
      Order result = algorithm(i,j, &valid);
      if (valid == 0)
      {
          // use members of result
      }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM