Recursive function, command after recall

Viewed 109

I am following a pdf to study recursion and string manipulation and I stumbled upon this.. I usually have an understanding of how a recursive function will behave (still not that good) but can't figure this out. This reverses the string. Well, prints it reversed.

void reverse(const char *const sptr);

int main()
{

char sentence[80];
printf("Enter a line of text:\n");
gets(sentence);

printf("\nThe reversed version:\n");
reverse(sentence);
puts("");


return 0;
}

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

I don't really understand how putchar works in this occasion. Can anyone explain it to me? I imagine this isn't just for putchar, how does the function behave when another command line is written "after" the recalling of the function?

4 Answers

It has nothing to do with putchar, it has everything to do with recursion.

Say you give it the string "1234" - or lets call it ['1','2','3','4','\0'] The first time reverse is called, it is called with the argument sptr pointing to ['1','2','3','4','\0'];

Execution reaches the recursive call to reverse and this time uses the offset 1, hence the argument becomes ['2','3','4','\0']

The process is repeated until a '\0' is found and now the function returns to the previous caller which prints the last character, returns to previous caller, which prints the 2:nd last character and so on until top reverse call is reached which prints the first character, and then exists.

Perhaps printing some additional debug info will make it easier to understand.

#include <stdio.h>

void reverse(const char *const sptr);

int recursion_level;

int main()
{
recursion_level=0;
    char sentence[80]="1234";
    // printf("Enter a line of text:\n");
    // gets(sentence);

    printf("\nThe reversed version:\n");
    reverse(sentence);
    puts("");
    return 0;
}

void reverse(const char *const sptr)
{
        recursion_level++;
        printf("reverse entered, recursion level:%d , sptr:%s \n",recursion_level, sptr);
        if(sptr[0] == '\0')
        {   recursion_level--;
            return;
        }
        else{
            reverse(&sptr[1]);
            putchar(sptr[0]);
        }
        printf("\n  reverse exits, recursion level:%d , \n",recursion_level);
        recursion_level--;
}

Which generates the following output

The reversed version:                                                                                                                          
reverse entered, recursion level:1 , sptr:1234                                                                                                 
reverse entered, recursion level:2 , sptr:234                                                                                                  
reverse entered, recursion level:3 , sptr:34                                                                                                   
reverse entered, recursion level:4 , sptr:4                                                                                                    
reverse entered, recursion level:5 , sptr:                                                                                                     
4                                                                                                                                              
  reverse exits, recursion level:4 ,                                                                                                           
3                                                                                                                                              
  reverse exits, recursion level:3 ,                                                                                                           
2                                                                                                                                              
  reverse exits, recursion level:2 ,                                                                                                           
1                                                                                                                                              
  reverse exits, recursion level:1 ,  

this works because of that :

   reverse(&sptr[1]);
   putchar(sptr[0]);

you first call on the next characters then you print the first, so

  • the first printed character will be the last
  • then you come back and write the previous being just before the last
  • ...
  • then you come back and print the first character

&sptr[1] is equivalent of sptr + 1 so that point to the address of the next character


if you reverse the lines and do that :

   putchar(sptr[0]);
   reverse(&sptr[1]);

you print the characters in the initial order


When you don't understand just execute the program into a debugger step by step

It is very simple.

You recursively call the function with the string as a parameter. Every call the the string is one char shorter (as you pass the pointer to the second char in the string . When it is zero length the first return occurs. The string has a length 1 and it is only the last character of the string. You print it (as you print the first character), then you return to the instance where the string was 2 chars long - you print it the first char whicg is the second from the end. Then you return and the string is 3 chars long you print the first char again and this repeats until you print all chars form the string in the reverse order.

You do not need the else statement at all as if the condition is met the control will never reach that statements

void reverse(const char *const sptr)
{
    if(!sptr[0]) return;
    reverse(&sptr[1]);
    putchar(sptr[0]);
}

int main()
{
    reverse("Hello World");

    return 0;
}

You can also add the check if the parameter is not NULL

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

As all others are saying, this is simple.

But the best thing to explain is to see you how that work in adding some log in your C code.

#include "pch.h"
#include <stdio.h>
#include <stdlib.h>

void reverse(const char *const sptr);
void openTraceFile();
void closeTraceFile();
void enterFunction();
void exitFunction();
void writeMessage(const char* s);

int main()
    {
    char sentence[80];
    printf("Enter a line of text:\n");
    //gets(sentence);
    fgets(sentence, 80, stdin);

    openTraceFile();

    printf("\nThe reversed version:\n");
    reverse(sentence);
    puts("");

    closeTraceFile();

    return 0;
    }

static FILE* logfile;
static int iNrSpaces = 0;

void reverse(const char *const sptr)
    {
    enterFunction();

    if (sptr[0] == '\0')
        {
        writeMessage("end of string");
        exitFunction();
        return;
        }

    reverse(&sptr[1]);

    putchar(sptr[0]);

    char s[80];
    sprintf(s,"putchar( %c )", sptr[0]);
    writeMessage(s);

    exitFunction();
    }

void openTraceFile()
    {
    logfile = fopen("reverse.log", "w");

    if (logfile == NULL)
        {
        printf("Error! Could not open file\n");
        exit(-1);
        }


void closeTraceFile()
    {
    fclose(logfile);
    }

void enterFunction()
    {
    writeMessage(">> reverse()");
    iNrSpaces += 4;
    writeMessage("{");
    }

void exitFunction()
    {
    writeMessage("}");
    iNrSpaces -= 4;
    }

void writeMessage(const char* s)
    {
    for (int i = 0; i < iNrSpaces; i++)
        {
        fputc(' ',logfile);
        }
    fprintf(logfile, s);
    fputc('\n', logfile);
    }

When you execute this program in entering "help", you will obtain following lines in reverse.log file.

>> reverse()
    {
    >> reverse()
        {
        >> reverse()
            {
            >> reverse()
                {
                >> reverse()
                    {
                    >> reverse()
                        {
                        end of string
                        }
                    putchar( \0 )
                    }
                putchar( p )
                }
            putchar( l )
            }
        putchar( e )
        }
    putchar( h )
    }

If now, you extract putchar() call without changing order of execution, you will obtain

putchar( p ); 
putchar( l ); 
putchar( e ); 
putchar( h ); 

that is the inversed string !

I hope that this explanation using LOG has helped you to understand this problem.

Little remark: \0 character is returner first in your example !

Related