Как можно добиться того, чтобы стек-кадр не разрушался после возвращения из функции? - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь сохранить элементы для ряда Фибоначчи в массиве, который находится внутри функции, и после возврата из функции с помощью «return arr» мой стековый фрейм разрушается, и я не могу получить значения в основной функции. Я хотел использовать только рекурсию и печать из основной функции - это мои условия.

#include <stdio.h>

int *fib(int *num, int *first, int *second, int i, int *arr);

int main()
{
  int num;
  printf("Enter any number : \n");
  scanf("%d", &num);
  int first = 0, second = 1, i = 0;
  int arr[num];
  int *result = fib(&num, &first, &second, i, arr);
  for (int i = 0; i < num; i++)
    printf("%d ", result[i]);
}

int *fib(int *num, int *first, int *second, int i, int *arr)
{
  int temp;
  if (*first == 0)
    printf("%d ", *first);
  if (*num < 0)
  {
    if (*second == 1)
      printf("%d ", *second);
    temp = *first - *second;
    *first = *second;
    *second = temp;
    if (*second > *num && *second < -*num)
    {
      *(arr + i) = *second;
      return fib(num, first, second, i++, arr);
    }
    else
      return arr;
  }
  else
  {
    temp = *first + *second;
    *first = *second;
    *second = temp;

    if (*second >= *num + 3)
      return arr;
    else
    {
      *(arr + i) = *second;
      return fib(num, first, second, i++, arr);
    }
  }

  printf("\n");
}

Ответы [ 4 ]

4 голосов
/ 27 марта 2019

Вы не можете.

Вы пытаетесь бороться с самим определением того, что такое стековый фрейм, и вы проигрываете.

И ты всегда проиграешь!

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

1 голос
/ 27 марта 2019

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

Я черпал вдохновение из ответа Джаббервоки и привел пример с «рекурсией»хотя в конечном итоге это просто замысловатый цикл.

#include <stdio.h>

void fib(int num, int *arr, int pos);

int main()
{
  int num;
  printf("Enter any number : \n");
  scanf("%d", &num);

  int arr[num];
  if (num > 1) {
    arr[0] = 0 ;
    arr[1] = 1 ;
  }
  int pos = 2;
  fib(num, arr, pos);

  for (int i = 0; i < num; i++)
    printf("%d ", arr[i]);
}

void fib(int num, int *arr, int pos)
{
  if (pos < num && pos > 1)
  {
    arr[pos] = arr[pos - 2] + arr[pos - 1];
    fib(num, arr, pos + 1);
  }  
  else {
      return;
  }
}

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

0 голосов
/ 02 апреля 2019
 #include <stdio.h>       



 int fib ( int *num , int *first , int *second , int count , int *arr ) ;      


 int main() 

 {

 char ch;

 do

 {
    int num = 0;

    printf("Enter any number : \n");

    scanf("%d", &num);

    int first = 0, second = 1, count = 0,size = num;           

if(num < 0)
    {
        size = -(num);                                 
    }
    int arr[size];                                          
    count = fib(&num, &first, &second, count, arr);        
    for (int j = 0; j < count; j++)
    {
        printf("%d ", *(arr + j));                      
    }
    printf("\n");
    printf("Do you want to repeat ? Y / N\n");              
    scanf("\n\n%c", &ch);
  } while (ch == 'y' || ch == 'Y');                             
}                                                                 

int fib(int *num, int *first, int *second, int count, int *arr)   
{

 int temp;
 if (*first == 0)
 {
    printf("%d ", *first);                                  
 }
 if (*num < 0)                                               
 {
    if (*second == 1)                                       
    {
        printf("%d ", *second);
    }
    temp = *first - *second;                                
    *first = *second;
    *second = temp;
    if (*second >= *num && *second <= -*num)
    {
        *(arr + count) = *second;                      
        return fib(num, first, second, count+1, arr);  
    }
 }
  else if(*num > 0)                                        
 {
    temp = *first + *second;
    *first = *second;                                    
    *second = temp;
    if (*second == 1)
    {
        printf("%d ", *second);                        
    }
    if (*second <= *num)
    {
        *(arr + count) = *second;                      
        return fib(num, first, second, count+1, arr);  
    }
  }
  return count;                                           
 }
0 голосов
/ 27 марта 2019

Несколько не по теме, но вы, вероятно, просто хотите это:

#include <stdio.h>

void fib(int num, int *arr);

int main()
{
  int num;
  printf("Enter any number : \n");
  scanf("%d", &num);

  int arr[num] = { 0, 1 } ;
  fib(num, arr);

  for (int i = 0; i < num; i++)
    printf("%d ", arr[i]);
}

void fib(int num, int *arr)
{
  for (int i = 0; i < num; i++)
  {
    arr[i + 2] = arr[i] + arr[i + 1];
  }  
}

Использование рекурсии здесь совершенно бессмысленно. Это непроверенный код, могут быть ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...