Почему эта функция рекурсивной суммы работает некорректно?

#c #recursion #cs50

#c #рекурсия #cs50

Вопрос:

В курсе CS50 есть эта проблема с Mario, и с помощью метода рекурсии это легко, за исключением того, что когда я пытаюсь добавить какую-либо арифметическую операцию, она показывает (недопустимые операнды к двоичному выражению (‘void’ и ‘int’)). Это просто для того, чтобы я понял, что я могу сделать, используя рекурсию, а что нет; проблема в этой строке ( sum(n-1) n; )

Вот код:

 #include <cs50.h>
#include <stdio.h>

void sum(int n);

int main ()
{
    int u = get_int("f");
    sum (u);
}

void sum(int n)
{
  if (n==0)
  {
    return;
  }
  sum(n-1) n;
  for(int i = 0 ; i < n; i  )
  {
    printf( "#");
  }
  printf("n");
}
  

Комментарии:

1. Что пытается сделать функция?

Ответ №1:

Ошибка, которую вы видите, из этой строки:

 sum(n-1) n;

  

sum — это функция, которая возвращает void, но вы пытаетесь добавить ее с помощью целого числа n.

Я не совсем уверен, что делает get_int («f»), но я предполагаю, что это запрашивает у пользователя ввод int, и вы пытаетесь суммировать от 0 до этого числа. Вот решение:

 int sum(int n) // Here is the critical change to your code, now it returns an int
{
  if (n == 1) // Root case that will stop the recursion, otherwise, it's endless
    return 1; // 1 = 1   0;

  return sum(n-1)   n; // Recursion
}
  

Подумайте о том, чего мы пытаемся здесь достичь. Мы хотим добавить от 0 до n, или, скажем, от n до 0 в меньшую сторону. Если n равно 3, это будет 3 2 1 0 и вы заметите, что 3 — это просто n, а 2 — это n — 1, 1 — это (n — 1) — 1 и т.д. Чтобы визуализировать это:

  1. прежде чем sum (3) сможет что-либо вернуть, она вызывает sum(2) 3;
  2. прежде чем sum (2) сможет что-либо вернуть, она вызывает sum (1) 2;
  3. 1 — это наш корневой регистр, и больше вызовов нет, поэтому sum (1) вернет 1;
  4. это значение 1 возвращается на шаг 2, поэтому sum (1) 2 становится 1 2, что равно 3, и это значение sum(2), и оно возвращает свой результат на шаг 1, а шаг 1 становится 3 3, что равно 6, и затем завершается первоначальный вызов sum.

Я надеюсь, что это имеет смысл для вас. Рекурсия — непростой метод для освоения. Не торопитесь, но вам нужно понять, как вызовы функций работают в памяти. Вот видео, которое иллюстрирует, как выглядят рекурсивные вызовы в памяти, структуры данных с использованием C : Иллюстрация рекурсивных вызовов функций (Call Stack).

Комментарии:

1. большое вам спасибо за ваш ответ, на самом деле я не совсем понимаю рекурсию и благодарю вас за ссылку, я посмотрю это сейчас на самом деле, я просто хочу добавить, что в этом коде я хочу напечатать (#) несколько раз, что вычисляется из sum (n-1) n; так почему я не могу сохранить функцию void, потому что я не хочу, чтобы возвращалось какое-либо значение int, мне просто нужно его вычислить и напечатать знак #, вот почему я использую void, и даже если я использую int вместо void, я все равно не могу использовать функцию void. получаем ту же ошибку

2. @ahmednabil эй, она возвращает значение int для своего собственного использования, вам действительно не нужно возражать против этого, и вы можете полностью поместить в них инструкции print. Кроме того, функции void в рекурсии встречаются редко, потому что вы не можете ничего вычислить, она просто вызывает себя, не зная результата последнего вызова, если вы не передадите это вычисленное значение вместе или не сохраните его как глобальную переменную. Полезно, когда вы просматриваете связанный список и пытаетесь добраться до последнего элемента, вы можете сделать что-то вроде этого, аннулировать функцию(Node* node) { if (node == nullptr) { сделать что-то нерекурсивное;} else func(node-> next); }

Ответ №2:

Это потому, что возвращаемый тип функции sum() является void .

Вы не можете ничего добавить к void .

В любом случае результат «сложения» выбрасывается, поэтому вам не понадобится сложение.

Это означает, что sum ( n-1) n; следует заменить на sum ( n-1); .

Комментарии:

1. спасибо за ваш ответ, у меня есть вопрос, почему добавление отбрасывается < в моем представлении это для добавления n после нахождения числа из sum (n-1) и для использования этого int для печати # с количеством раз, которое только что оценивалось? можете ли вы проиллюстрировать, пожалуйста?

2. sum Функция должна быть переписана, чтобы возвращать значение.