tags:

views:

854

answers:

6

I'm looking for a way to rotate a string in c++. I spend all of my time in python, so my c++ is very rusty.

Here is what I want it to do: if I have a string 'abcde' I want it changed to 'bcdea' (first character moved to the end). Here is how I did it in python:

def rotate(s):
    return s[1:] + s[:1]

I'm not sure how to do it in cpp. Maybe use an array of chars?

+5  A: 

Here's a solution that "floats" the first character to the end of the string, kind of like a single iteration of bubble sort.

#include <algorithm>

string rotate(string s) {
  for (int i = 1; i < s.size(); i++)
    swap(s[i-1], s[i]);
  return s;
}

if you want the function to rotate the string in-place:

#include <algorithm>

void rotate(string &s) {
  for (int i = 1; i < s.size(); i++)
    swap(s[i-1], s[i]);
}
marcog
Nice uncommon solution
schnaader
Elegant solution!
Ben Alpert
Be careful of one thing: if s.size() == 0, then s.size()-1 will become 4294...... since s.size() is unsigned.
v3
Good catch, updated it to go from 1 to s.size().
marcog
+4  A: 

Here's a relatively simple way:

void RotateStringInPlace(char buffer[])
{
    // Get the length of the string.

    int len  = strlen(buffer);
    if (len == 0) {
        return;
    }

    // Save the first character, it's going to be overwritten.

    char tmp = buffer[0];

    //  Slide the rest of the string over by one position.

    memmove(&buffer[0], &buffer[1], len - 1);

    // Put the character we saved from the front of the string in place.

    buffer[len - 1] = tmp;
    return;
}

Note that this will modify the buffer in place.

Eric Melski
I would say this is more C than C++, isn't it?
alvatar
+1 for using memmove instead of memcpy (which is not safe when the strings may overlap).
Mikeage
I suppose you could say this is more C than C++, but it's still valid C++, and it's probably more efficient than std::rotate, which is O(n) in the number of characters in the string, while this approach is probably more like O(m) where m is n/(size of a word on your platform).
Eric Melski
@Eric Melski: Your "O(m)" is the same thing as O(n), just faster. Big O notation only measures how well the algorithm scales, not how fast the implementation is.
Zifre
+1  A: 

Is doing it in place a requirement?

If not, you're probably best off taking a substring of all but the first char, and then appending the first char to the end.

patros
+12  A: 

I recommend std::rotate:

std::rotate(s.begin(), s.begin() + 1, s.end());
Johannes Schaub - litb
only available for sgi stl
Schildmeijer
section 25.2.10 in the C++ Standard specifies std::rotate
Johannes Schaub - litb
By the way, if you need a right rotate, use reverse iterators: std::rotate(s.rbegin(), s.rbegin() + 1, s.rend()); and the String becomes "eabcd"
Johannes Schaub - litb
+5  A: 

There is a standard rotate function found in the algorithm header.
If you want to do this yourself, you could try the following:

#include <iostream>
#include <string>

std::string rotate_string( std::string s ) {
    char first = s[0];

    s.assign(s, 1, s.size() - 1);
    s.append(1, first);

    return s;
}

int main() {
    std::string foo("abcde");

    std::cout << foo << "\t" << rotate_string(foo) <<  std::endl;

    return 0;
}

But of course, using the standard library is preferable here, and in most cases.

EDIT: I just saw litb's answer. Beat again!
EDIT #2: I just want to mention that the rotate_string function fails on strings of 0 length. You will get a std::out_of_range error. You can remedy this with a simple try/catch block, or use std::rotate :-)

Nick Presta
+1  A: 

If you don't want these in-place solutions, then your python code can be directly translated to C++, with a bit of extra code to deal with the fact that index out of bounds is bad news in C++.

s[1:] --> s.substr(1);
s[:1] --> s[0]; // s[0] is a char not a string, but that's good enough

So,

std::string rotate(const std::string &s) {
    if (s.size() > 0) return s.substr(1) + s[0];
    return s;
}

This isn't the most efficient: it will almost certainly do more string creation than the minimum possible. But you don't usually need the most efficient, and you have reserve and append if you want to do concatenation without unnecessary allocation.

Steve Jessop