Перейти к main () из пользовательской функции - PullRequest
1 голос
/ 15 июля 2011

У меня есть 3 функции: my_fun1(), my_fun2() и my_fun3().

main(), звонки my_fun1(), которые звонят my_fun2(), которые, в свою очередь, звонят my_fun3().

После некоторого предопределенного условия в my_fun3() я бы хотел, чтобы моя программа возвращалась непосредственно к функции main() в строке my_fun1().

Возможно ли перейтинепосредственно от my_fun3() до main(), или мне нужно добавить некоторые условия к my_fun2() и my_fun1() для достижения этого?

Ответы [ 7 ]

4 голосов
/ 15 июля 2011

Ну, есть способ перейти непосредственно к другой точке кода, используя longjmp / setjmp, но я не собираюсь рассказывать вам, как, потому что это ужасная идея.Примерно так же плохо, как и получается.Итак, давайте поговорим о хороших решениях: -).

Самый очевидный способ - использовать исключения .Например:

int my_fun3() {
    throw 1; // could be any type...
}
int my_fun2() {
    my_fun3();
}

int my_fun1() {
    my_fun2();
}

int main() {
    try {
        my_fun1();
    } catch(int n) { // catch the same type you threw...
    }
}

Если вы не хотите использовать исключения (возможно, некоторые утверждают, что это будет злоупотреблением исключениями, если причина длявозврат к основному не является «исключительным») следующим самым простым способом является получение my_fun1, my_fun2 и my_fun3 возвращаемых значений, означающих «выполнено», скажем, int, где значение меньше 0 означает «вернуться на главную».Структура вашего вызова будет выглядеть следующим образом:

int my_fun3() {
   // ...
   if(some_condition) {
       return -1;
    }

    return 0;
}

int my_fun2() {
    // ...
    int r = my_fun3();
    if(r < 0) {
        return r;
    }
    // ...
    return 0;
}

int my_fun1() {
    // ...
    int r = my_fun2();
    if(r < 0) {
        return r;
    }
    // ...
    return 0;
}

int main() {
    my_fun1();
}
3 голосов
/ 15 июля 2011

Либо вернитесь из всех функций, либо сгенерируйте и поймайте исключение (не рекомендуется, если причиной подъема в стек действительно является ошибка)

3 голосов
/ 15 июля 2011

Да, это возможно, выбрасывая исключение и перехватывая его в main.Но, пожалуйста, не используйте исключения в качестве общего механизма управления потоком, это не то, для чего они нужны.

Есть также setjmp / longjmp, но код, использующий их, очень сложен для понимания.

0 голосов
/ 15 июля 2011

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

main
    while running
        do stuff

Так что вы можете сделать

bool running = false;

int main(int argc, char **argv)
{
    while(running)
        function1();
}

void function3()
{
    ...
    if(whatever)
    {
        running = true;
        return;
    }
    ...
}

Если вам нужны функции function1 () и function2 (), чтобы прервать выполнение чего-либо на основеповедение, то ваша ситуация либо является ошибкой, либо в основном похожа на ошибку, поэтому выбрасывание исключения будет лучшим решением.Даже если это не ошибка, это в основном тот же тип логики управления.

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

0 голосов
/ 15 июля 2011

Это возможно, вызвав исключение, как сказал larsmans (хотя только в C ++).Это также возможно через setjmp () / longjmp (), который действует как своего рода перекрестный оператор goto.

Но если это действительно тот дизайн, который вы хотите / нуждаетесь, то, вероятно, что-то не так с вашим дизайном,Наличие условий в my_fun1 и my_fun2 может быть «правильным» ответом здесь, но это, конечно, зависит от того, что вы делаете.Если вы опубликуете немного больше информации о том, почему вы хотите / нуждаетесь в этом, мы сможем помочь вам лучше.

0 голосов
/ 15 июля 2011

Возможно, вы намекаете на goto, что плохо.

Не видя структуру вашей программы, вы можете рассмотреть возвращаемое логическое значение (например, флаг), которое проверяется при возвращениифункция # 3, которая проверяется в # 2, которая затем возвращается, проверяется в # 1, а затем возвращается к main().

0 голосов
/ 15 июля 2011

Чистый подход без злоупотребления исключениями будет

#define EXITCONDITION 42

void main ()
{
  ...
  myfunc1 ();
  ...
}

int myfunc1 ()
{
  ...
  if (myfunc2 () == EXITCONDITION) return EXITCONDITION;
  ...
}

int myfunc2 ()
{
  ...
  if (myfunc3 () == EXITCONDITION) return EXITCONDITION;
  ...
}

int myfunc3 ()
{
  ...
  if (somethingweirdhappens) retrun EXITCONDITION;
  ...
}
...