Как я могу вернуть структуру, если условие истинно, и int, если условие ложно - PullRequest
1 голос
/ 27 мая 2019

Первый простой пример:

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
}

Вопрос: возможно ли вернуть int или структуру? Если нет, то как я могу сделать escamotage, чтобы избежать проблемы?

Я думал, что мог бы использовать указатели и вернуть указатель, НО указатель должен иметь тип.

Ответы [ 6 ]

2 голосов
/ 27 мая 2019

Вы можете разбить его на две части

  1. Пусть функция возвращает значение int, где (обычно) возвращаемое значение 0 указывает на успех, а другие отрицательныезначения указывают на различные типы ошибок.

  2. Взять указатель на структурную переменную в качестве одного из аргументов.В случае успешного выполнения заполните структуру, а в вызывающей стороне, основываясь на возвращаемом значении вызова функции, можно получить доступ к структуре, чтобы извлечь значение, сохраненное в ее членах.

1 голос
/ 27 мая 2019

У вас не может быть функции с типом возвращаемой переменной.

Обычные способы справиться с ситуацией:

1) использовать числовое возвращаемое значение для сигнализации об ошибках и возвращать полезную нагрузку через переданный указатель

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

2) или вернуть тегованную структуру (по моему опыту, менее распространенную, но она может генерировать немного более оптимальный код, если полезная нагрузка мала); если он помечен как успешный, остальная часть структуры пригодна для использования, иначе это не

 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
  }
0 голосов
/ 27 мая 2019

Нет способа получить тип возвращаемой переменной из функции в C.

Один из вариантов - изменить struct, включив в него int, который указывает, является ли struct действительным или нет.

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;
}

Для этого необходимо, чтобы вызывающий проверил, например;

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

Другой способ - добавить третий (указатель) аргумент в функцию

 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
      }
  }
0 голосов
/ 27 мая 2019

Вопрос: возможно ли вернуть int или структуру?

номер

Однако, есть обходной путь. Создайте объединение, которое может содержать вашу структуру или int. Затем вы создаете структуру-оболочку, содержащую одно такое объединение и одну переменную, которые вы используете для определения возвращаемого типа. Вы можете сделать так:

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;
}

А потом используйте что-то вроде этого:

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 */ }

Вы можете использовать структуру вместо объединения. Единственным недостатком является то, что он будет использовать немного больше памяти.

Это общее решение, которое вы можете использовать. Если вы думаете, что это загромождает код, вы можете вместо этого добавить два поля в существующую структуру:

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;
0 голосов
/ 27 мая 2019

Типы возвращаемых переменных не существуют в C.

Вы можете сделать это:

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

или проще:

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

и вызвать его так:

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

или вы можете вернуть указатель на ордер, если он в порядке, и вернуть NULL, если он не в порядке:

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

и вызвать его так:

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

Есть много возможностей для достижения этой цели.Смотрите также другие ответы.

0 голосов
/ 27 мая 2019

, если функция имеет тип Order, она не может вернуть int, но вы можете сделать это:

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;
}

и позже, вы можете проверить, равно ли возвращаемое значение ("",-1,"")

...