Jad Al-Hamwi
Jad Al-Hamwi

Reputation: 169

Reversing A String in C++ (Using Recursion)

#include <iostream>
#include <string>
using namespace std;
void ReverseString(string &S, int size)
{
    static int start = 0;
    if (start == size - 1 || start == size)
    {
        return;
    }
    else
    {
        swap(S[start++], S[size - 1]);
        ReverseString(S, size - 1);
    }
}
int main()
{
    cout << "enter a string to reverse" << endl;
    string s;
    getline(cin, s);
    cout << "Before Reversing" << endl;
    cout << s << endl;
    ReverseString(s, s.size());
    cout << "After Reversing" << endl;
    cout << s << endl;
    return 0;
}

I am trying to nail recursions as much as i can,and i was trying to reverse a string using recursion i didn't know how to do it at first,tried many different ways to do it,but i saw code samples on string reversing,but none of it made sense to me,so i made my own one,but not quite sure of it,i'm just asking for opinion,is it clean and functional??

Thank You

Upvotes: 0

Views: 2291

Answers (6)

Yash Sarvaiya
Yash Sarvaiya

Reputation: 31

This program can reverse anything... Using recursion and that's all.

#include<iostream>
using namespace std;
int main(){
    char c;
    cin.get(c);
    if(c=='\n')return 0;
    main();
    cout<<c;
    return 0;
}

Upvotes: -1

stark
stark

Reputation: 13189

Anyone can reverse a string one char at a time, but much cooler is to reverse each third of the string and swap the outer thirds. This cuts stack depth as well as sowing confusion amongst the competition. Note that max stack depth of recursion per character is N, whereas this is cube root of N.

#include <iostream>
#include <string>
using namespace std;

void ReverseRegion(string &s, int start, int sz)
{
  // regions < 2 need no action
  if (sz == 2) {
    char tmp = s[start];
    s[start] = s[start+1];
    s[start+1] = tmp;
  } else if (sz > 2) {
    int s3 = sz/3;
    ReverseRegion(s, start, s3);
    string tmp = s.substr(0,start) + s.substr(start+sz-s3,s3) + s.substr(start+s3, sz-2*s3) + s.substr(start,s3) + s.substr(start+sz);
    // cout << "do: " << tmp << "\n";
    s = tmp;
    ReverseRegion(s, start+s3, sz-2*s3);
    ReverseRegion(s, start, s3);
  }
}


void ReverseString(string &S)
{
  ReverseRegion(S, 0, S.size());
}

int main()
{
    cout << "enter a string to reverse" << endl;
    string s;
    getline(cin, s);
    cout << "Before Reversing" << endl;
    cout << s << endl;
    ReverseString(s);
    cout << "After Reversing" << endl;
    cout << s << endl;
    return 0;
}

Upvotes: 0

eerorika
eerorika

Reputation: 238341

is it ... functional??

If by "functional" you mean "does it work", then you tell me.

If you mean "functional" as in "functional" programming style, then no it isn't. In functional style, you don't modify arguments in place, but instead return a new value. Also relying on global state (i.e. static objects) is very anti-functional.

Here is an example:

std::string
ReverseString(std::string_view sv)
{
    if (sv.empty())
        return "";
    std::string_view x  = sv.substr(0, 1)
    std::string_view xs = sv.substr(1);
    return ReverseString(xs) + x;
}

// usage
s = ReverseString(s);

In future, if Pattern matching was introduced to the language, then it could potentially be written like this:

std::string
ReverseString(std::string_view sv)
{
    inspect(sv) {
        "":      return "";
        [x:xs]:  return ReverseString(xs) + x;
    }
}

However, the current proposal does not suggest introducing support for matching ranges like this, so this is highly theoretical.

Upvotes: 3

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

Your function with a static variable can be called only once because after its recursive calls the static variable start will not be equal to 0 as it is required. So the function is not "functional".

Here is a demonstrative program that shows how the function can be written with using a static variable and without using a static variable.

#include <iostream>
#include <string>
#include <utility>

void ReverseString1( std::string &s )
{
    static std::string::size_type i = 0;

    if ( not ( s.size() - 2 * i < 2 ) )
    {
        std::swap( s[i], s[s.size() - i - 1] );

        ++i;
        ReverseString1( s );
        --i;
    }
}

void ReverseString2( std::string &s, std::string::size_type pos = 0 )
{
    if ( not ( s.size() - 2 * pos < 2 ) )
    {
        std::swap( s[pos], s[s.size() - pos - 1] );
        ReverseString2( s, pos + 1 );
    }
}

int main() 
{
    std::string s( "Hello World!" );

    std::cout << s << '\n';

    ReverseString1( s );

    std::cout << s << '\n';

    ReverseString2( s );

    std::cout << s << '\n';

    return 0;
}

The program output is

Hello World!
!dlroW olleH
Hello World!

Upvotes: 0

meth
meth

Reputation: 1885

Local static variables are dangerous. Since their state will remain between function calls. In my approach i used slen as the length of a string and the currentIndex as the last swapped index on the string. Since it is enough to swap till the middle of the string, finish case is when (currentIndex == slen/2). I also added some test cases as an example.(even length, odd length, zero case and palindrome)

#include <iostream>
#include <string>
using namespace std;
void ReverseString(string &S, int currentIndex, int slen)
{
    if (slen / 2 == currentIndex) return;

    swap(S[currentIndex], S[slen - 1 - currentIndex]);
    currentIndex++;

    ReverseString(S, currentIndex, slen);
}

void testReverseString() {
    string s = ""; 
    ReverseString(s, 0, s.length());
    assert(s == "");

    s = "ahmet"; 
    ReverseString(s, 0, s.length());
    assert(s == "temha");

    s = "ahaha"; 
    ReverseString(s, 0, s.length());
    assert(s == "ahaha");

    s = "haha"; 
    ReverseString(s, 0, s.length());
    assert(s == "ahah");
}

int main()
{
    testReverseString();
    return 0;
}

Upvotes: 0

R Sahu
R Sahu

Reputation: 206577

Using a function local static variable in a recursive function is a bad idea. Recursive functions should get all their state as input arguments.

Here's a simplified version that divides the logic into two functions.

void ReverseString(string &S, int start, int end)
{
   if ( start < end )
   {
      swap(S[start], S[end - 1]);
      ReverseString(S, start+1, end - 1);
   }
}

void ReverseString(string &S)
{
   ReverseString(S, 0, S.size());
}

Most of the time, higher level functions would only call the second function. The first function can be called from a higher level function if there is a need to reverse only a subset of a string.

Here's a sample program

#include <iostream>
#include <string>

using namespace std;

void ReverseString(string &S, int start, int end)
{
   if ( start < end )
   {
      swap(S[start], S[end - 1]);
      ReverseString(S, start+1, end - 1);
   }
}

void ReverseString(string &S)
{
   ReverseString(S, 0, S.size());
}

int main()
{
    string s = "The string to reverse" ;

    cout << "Before Reversing" << endl;
    cout << s << endl;

    ReverseString(s);
    cout << "After Reversing" << endl;
    cout << s << endl;

    ReverseString(s, 0, 7);
    cout << "After Reversing a subset" << endl;
    cout << s << endl;
    return 0;
}

and its output

Before Reversing
The string to reverse
After Reversing
esrever ot gnirts ehT
After Reversing a subset
reverse ot gnirts ehT

See it working at https://ideone.com/9nMlsP.

Upvotes: 4

Related Questions