В чем разница между --i и i - 1 в параметре в C? - PullRequest
0 голосов
/ 07 июля 2019

Я пишу программу, которая печатает первые 10 натуральных чисел в рекурсии. Прежде всего, я ставлю параметр "--num"

int natural_numbers(int num) {
    if (num > 1) // Base case
        natural_numbers(--num);
    printf("%d ", num);
}
Input: 10
Output: 1 1 2 3 4 5 6 7 8 9

А потом я изменил параметр на «num - 1», и он распечатывает то, что я ожидал.

int natural_numbers(int num) {
    if (num > 1) // Base case
        natural_numbers(num - 1);
    printf("%d ", num);
}
Input: 10
Output: 1 2 3 4 5 6 7 8 9 10

Понятия не имею, почему первый выход был неправильным. Мне нужна помощь.

Ответы [ 4 ]

1 голос
/ 07 июля 2019

В первой части вы меняете числовое значение с помощью оператора предварительного уменьшения --.Ваш второй код не меняет значение num (оно передает временное значение num - 1 вызову функции).

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

Если вы первоначально вызываете natural_numbers с num == 10, ниже вы можете отслеживать, как его значение изменяется / не изменяетсяизменить в следующих строках.

                                  //      num (its value)
int natural_numbers(int num) {    //       10
    if (num > 1) // Base case     //       10
        natural_numbers(--num);   //       10 / and 9 (after execution)
    printf("%d ", num);           //        9
}

int natural_numbers(int num) {    //       10
    if (num > 1) // Base case     //       10
        natural_numbers(num - 1); //       10
    printf("%d ", num);           //       10
}

1 голос
/ 07 июля 2019

num - 1 создает новый временный int как копию num и вычитает 1 из этого временного int.

--num вычитает 1 из самого num.

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

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

#include <iostream>
#include <string>

void natural_numbers(int num) {
    static size_t indent = 0;
    std::cout << std::string(indent, ' ') << "num before: " << num << "\n";
    if(num > 1) { // Base case
        ++indent;
        natural_numbers(--num);
        --indent;
    }
    std::cout << std::string(indent, ' ') << "num after: " << num << "\n";
}

int main() {
    natural_numbers(10);
}
0 голосов
/ 07 июля 2019

Вы думаете, что мы хотим вызвать эту функцию по номеру 3

когда вы используете --num его так же, как вы меняете введенный номер в функции natural_function, так что

локальный стек при вызове natural_numbers (3) выглядит как

// =========call natural_number(3)

natural_number(2) // --num (change num itself. its like num = num - 1 then pass it)

// But here in this local stack  block "num" becomes 2 

print 2 // <== here it prints 2 on the backward step

// ========= call natural_number(2)

natural_number(1) // --num (change num itself. its like num = num - 1 then pass it)

// But here in this local stack  block "num" becomes 1

print 1 // <== Here it prints 1 on the backward step

// ========= call natural_number(1)

print 1 // Here we go out of stack by printing 1  

Result: 1 1 2

Теперь, если бы мы вызвали эту функцию с помощью (num - 1) это означает, что вы не хотите изменять переменную «num», входящую в собственный блок локального стека.

Локальный стек для (num - 1) будет выглядеть так:

// ========= call natural_number(3)

natural_number(2) // (num - 1) (num wont change. its like temp = num - 1 then pass temp to it)

print 3 // Here it prints 3 on the backward step

// ========= call natural_number(2)

natural_number(1) // (num - 1) (num wont change. its like temp = num - 1 then pass temp to it)

print 2 // <== Here it prints 2 on the backward step

// ========= call natural_number(1)

print 1 // Here we go out of stack by returning 1  

Result: 1 2 3
0 голосов
/ 07 июля 2019

Если вы хотите передать num - 1 в функцию (как на самом деле вы делаете здесь), способ сделать это - просто вызвать natural_numbers(num - 1). Ничего особенного не нужно. Не случайно так работает.

Специальные операторы

C ++ и -- делают больше - значительно больше - чем просто добавляют или вычитают 1. Они складывают или вычитают 1, и сохраняют увеличенную или уменьшенную переменную обратно в исходное местоположение . Так что --num не просто вычитает 1 из num, оно сохраняет значение num - 1 обратно в num. Но это не то, что вы хотите здесь. Вы не хотите изменять num, потому что при каждом рекурсивном вызове вы хотите распечатать значение num, с которого вы начали, , а не уменьшенную версию, которую вы передали в рекурсию.

...