Пытаясь понять рекурсивную функцию, чтобы перевернуть строку - PullRequest
2 голосов
/ 01 июня 2019

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

 void reverse(const char * const sPtr){
   if('\0' == sPtr[0])
     return;
     else{
       reverse(&sPtr[1]);
       putchar(sPtr[0]);
    }
 }

Ответы [ 4 ]

2 голосов
/ 01 июня 2019

Если вы введете «abc», стек вызовов будет выглядеть примерно так:

reverse("abc")
    reverse("bc")
        reverse("c")
        print("c")
    print("b")
print("a")

Таким образом, каждый обратный вызов вызывает саму себя с одной и той же строкой, но исключая первый символ, и ТО печатает первый символв строке.

Удаляются ли символы в строке, потому что они передаются по ссылке?

В C. нет вызова по ссылке в виде эмуляции указателейэто, но все в C передается по значению.Кроме того, тип указателя const char * const говорит о двух вещах.Во-первых, указатель не будет переназначен, чтобы указывать на что-либо еще, но, что более важно, он также говорит, что строка не будет изменена.Попробуйте добавить строку sPtr[0] = 'a' где-нибудь, и вы получите ошибку компилятора.

2 голосов
/ 01 июня 2019

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

&sPtr[1]

… что эквивалентно

sPtr + 1

Таким образом, каждый рекурсивный вызов увеличивает указатель на единицу, таким образом, рекурсивные вызовы пересекают ваш массив char.

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

1 голос
/ 01 июня 2019

После последнего reverse(&sPtr[1]) будет сложено 3 вызова putchar.

Каждый вызов reverse увеличивает указатель на 1, поэтому составленные вызовы будут - при условии что введена строка вводаиз 3 символов -

CURRENT FRAME -- *(ptr+3) is NULL
putchar(*(ptr+2))
putchar(*(ptr+1))
putchar(*(ptr+0))
1 голос
/ 01 июня 2019

Нет, оно не удаляется.

В каждом рекурсивном вызове вы хотите перейти к следующему символу, что делается здесь:

reverse(&sPtr[1]); // you pass a parameter the 1st character of where you point to now
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...