lock&_lock Ответов: 2

Как правильно назвать структуру, возвращают в качестве входных данных для другой функции, структура ?


Привет, я хочу передать возвращаемое значение функции A в функцию B и передать возвращаемое значение функции B в функцию C. Я использую struct. Я могу перейти от структуры к функции, а затем к main, но, оказывается, я все еще путаю, как передать struct return функции, которая также возвращает другую структуру.


Когда я поставил первую функцию в качестве входных данных второй функции, она ожидала ввода (действительно, первая функция нуждается во вводе), но я хотел вызвать возвращаемое значение, а не функцию. Я в замешательстве. Что посоветуете ? Спасибо

Что я уже пробовал:

Вот как я определяю свою структуру
struct Credit {
    float A;
    float B;
    float C;
};

struct Intermediate {
   float math;
   float bio;
};


Затем у меня есть моя первая функция, с ручным вводом значения от пользователя. И из этой функции я возвращаю значение A, B и C
struct Credit course (float x1, float y1, float x2, float y2)
{ 
   // simple arithmetic calculation...
 
    struct Credit result;
    result.A = A;
    result.B = B;
    result.C = C; 
    return result;
}

В моей второй функции мне нужно получить входные данные от A,B,C из предыдущей функции. А затем верните значение math, bio в качестве входных данных из следующей функции.
struct Intermediate grade (struct Credit point)
{
   // simple calculation involving return result of previous function (A, B, C)
   // I call the value using point.A , point.B and point.C
    
    struct Intermediate result;
    result.math = math;
    result.bio = bio;
    return result;
    //result from this function will be used for the next function
}

Вот моя главная :
course(12,10,10,8);
grade(course());
//next function using input from function grade.

2 Ответов

Рейтинг:
8

Stefan_Lang

Хотя решение 1 по существу правильно, это то, что я бы изменил, чтобы ваш код не только работал, но и работал хорошо:

struct Credit course(...) // leave this function as is
...
struct Intermediate grade(struct Credit& credit) { //pass by reference!
 ... // leave the function code as is
}
int main () {
   Intermediate my_grade = grade(course(12, 10, 10, 8));
   ...
}

Объяснение:
- вызов, конечно, создает структура, тип кредита и возвращает ее
- компилятор следит за тем, чтобы структура, созданная локально, использовалась повторно, а не копировалась; нет никакого снижения производительности для создания копии!
- ссылка на эту кредитную структуру непосредственно передается в стек вызовов для вызова функции grade(); опять же, копия не требуется - передается только ссылка
- как и course(), grade() возвращает внутренне построенную промежуточную структуру и возвращает ее без копии

Другое преимущество: нет необходимости объявлять переменную типа Credit в main - если вы когда-нибудь решите изменить тип возврата, вам не нужно будет менять свою основную функцию!


lock&_lock

Привет, спасибо ! Первое решение предоставило мне указатель, я еще не совсем понимаю указатель, хотя это более выгодно, поэтому я придерживаюсь struct.
Я знаю, что проблема заключается в том, как я называю их в своем основном. Я с "структура среднего класса (структуры кредитной балл)" (без упоминания вскользь) и называют его "структуры средний I = класс(курс(12,10,10,8));". Теперь это работает. Кроме того, конечно, я попробовал ваше решение с передачей ссылки, к сожалению, я столкнулся со многими ошибками. Поскольку есть много преимуществ при передаче ссылки, я постараюсь устранить ошибки в ней и посмотреть, работает ли она. Спасибо снова.

Stefan_Lang

Я думаю, что многие детали, объясненные в обоих решениях, выходят за рамки вашего нынешнего уровня программирования.

На данный момент все, что вам нужно знать, это то, что когда функция возвращает значение, вы должны позаботиться о том, чтобы действительно использовать это значение при вызове функции. Либо назначьте его локальной переменной (в вашем примере переменной i, которой присваивается возвращаемое значение из вызова функции grade()), либо используйте ее в том месте, где ожидаемое значение ожидается в выражении, либо в качестве аргумента функции (в вашем примере функция grade() ожидает аргумент типа Credit, который вызов функции course() удобно предоставляет в качестве возвращаемого значения).

Stefan_Lang

Что касается использования указателей и ссылок, то это очень важные понятия в C и C++. Если вы планируете улучшить свои навыки программирования, посмотрите учебные пособия и статьи по этим темам.

Короче говоря, оба они не содержат полного объекта (struct или как-то иначе), а только указывают на то, где объект может быть найден в памяти. Поэтому передача указателя или ссылки на функцию (или обратно в виде возвращаемого значения) может быть более эффективной, чем передача структуры, если структура очень велика.

Однако указатели также являются одним из самых больших источников ошибок программирования в C/C++. Поэтому вам действительно стоит потратить некоторое время, чтобы научиться правильно их использовать.

Рейтинг:
13

k5054

Упуская из виду тот факт, что предоставленный вами код вообще не будет компилироваться ...

Ваша функция course() возвращает структуру, но она не назначается в небольшом фрагменте main() вы все предусмотрели. Возвращаясь к основам - предположим, что у нас есть функция f, которая принимает int в качестве аргумента и возвращает значение int:

int f(int x); /* declares a function taking an int which returns an int */

f(2);  /* calls f with value 2 as the parameter - return value is thrown away */
f();   /* ERROR: no parameter given to f() */

int i;
i = f(2);                    /* OK: assigns return value from f() to i */
printf("i = %d\n", i);       /* we can then use the i later */
printf("f(3) = %d\n", f(3)); /* OK : return value of f() is passed to printf() */ 

В вашем случае вы хотите сделать одно из следующих действий:
struct Credit MyCredit;
struct Intermediate MyIntermediate;
MyCredit = course(12, 10, 10, 8);
MyIntermediate = grade(MyCredit);
или
struct  Intermediate MyIntermediate = grade(credit(12, 10, 10, 8));

Вы бы использовали второй пример, если бы вам не нужно было снова использовать возвращаемое значение of course() позже.

Обычно, однако, мы не передаем и не возвращаем структуры в функции или из них. Это происходит потому, что C использует pass-by-value, что означает, что при передаче или возврате структуры компилятор копирует ее в/из стека по мере необходимости. Для небольшой структуры это, как правило, не проблема. Но если у вас есть большая структура, которая занимает несколько килобайт (или даже мегабайт!), вы копируете эти данные для каждого вызова функции или возврата. Альтернативный подход вероятно быть:
void course(struct Credit *credit, float x1, float x2, float y1, float y2)
{
   credit->A = x1+x2;
   /* and so on for other members of credit */
}

int main()
{
   struct Credit MyCredit;
   course(&MyCredit, 12, 10, 10, 8); /* passes address of MyCredit to course() */
   /* more code here ... */
   return 0;
}

В этом случае мы никогда не добавляем в стек больше размера указателя (обычно 4 байта для 32-битной системы, 8 байт для 64-битной системы).


CPallini

5.

Stefan_Lang

Я не согласен с последней частью. Проверьте GotW 90: фабрики ( https://herbsutter.com/2013/05/30/gotw-90-solution-factories/ ) который я случайно прочитал вчера. Функция course() явно является фабричной функцией, и рекомендуемый способ возврата построенного на заводе объекта-это именно то, что сделал ОП: вернуть объект по значению. Нет никакого хита производительности!

Несмотря на то, что в статье используется терминология C++ и упоминается механика C++, то же самое верно и для кода C в отношении производительности: в конце концов, нет никаких причин, по которым компилятор C не может быть таким же производительным, как компилятор C++.

Ваше решение вводит дополнительную проблему, которой нет в коде OP: передача нулевого указателя на фабрику. Легко поймать, но вы *должны* поймать его. А ты-нет.