[c++] How do you reverse a string in place in C or C++?

How do you reverse a string in C or C++ without requiring a separate buffer to hold the reversed string?

This question is related to c++ c string reverse

The answer is


If you are using ATL/MFC CString, simply call CString::MakeReverse().


Non-evil C, assuming the common case where the string is a null-terminated char array:

#include <stddef.h>
#include <string.h>

/* PRE: str must be either NULL or a pointer to a 
 * (possibly empty) null-terminated string. */
void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;
    *end_ptr = temp;
    str++;
    end_ptr--;
  }
}

If you're looking for reversing NULL terminated buffers, most solutions posted here are OK. But, as Tim Farley already pointed out, these algorithms will work only if it's valid to assume that a string is semantically an array of bytes (i.e. single-byte strings), which is a wrong assumption, I think.

Take for example, the string "año" (year in Spanish).

The Unicode code points are 0x61, 0xf1, 0x6f.

Consider some of the most used encodings:

Latin1 / iso-8859-1 (single byte encoding, 1 character is 1 byte and vice versa):

Original:

0x61, 0xf1, 0x6f, 0x00

Reverse:

0x6f, 0xf1, 0x61, 0x00

The result is OK

UTF-8:

Original:

0x61, 0xc3, 0xb1, 0x6f, 0x00

Reverse:

0x6f, 0xb1, 0xc3, 0x61, 0x00

The result is gibberish and an illegal UTF-8 sequence

UTF-16 Big Endian:

Original:

0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00

The first byte will be treated as a NUL-terminator. No reversing will take place.

UTF-16 Little Endian:

Original:

0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00

The second byte will be treated as a NUL-terminator. The result will be 0x61, 0x00, a string containing the 'a' character.


In the interest of completeness, it should be pointed out that there are representations of strings on various platforms in which the number of bytes per character varies depending on the character. Old-school programmers would refer to this as DBCS (Double Byte Character Set). Modern programmers more commonly encounter this in UTF-8 (as well as UTF-16 and others). There are other such encodings as well.

In any of these variable-width encoding schemes, the simple algorithms posted here (evil, non-evil or otherwise) would not work correctly at all! In fact, they could even cause the string to become illegible or even an illegal string in that encoding scheme. See Juan Pablo Califano's answer for some good examples.

std::reverse() potentially would still work in this case, as long as your platform's implementation of the Standard C++ Library (in particular, string iterators) properly took this into account.


void reverseString(vector<char>& s) {
        int l = s.size();
        char ch ;
        int i = 0 ;
        int j = l-1;
        while(i < j){
                s[i] = s[i]^s[j];
                s[j] = s[i]^s[j];
                s[i] = s[i]^s[j];
                i++;
                j--;
        }
        for(char c : s)
                cout <<c ;
        cout<< endl;
}

If you don't need to store it, you can reduce the time spent like this:

void showReverse(char s[], int length)
{
    printf("Reversed String without storing is ");
    //could use another variable to test for length, keeping length whole.
    //assumes contiguous memory
    for (; length > 0; length--)
    {
        printf("%c", *(s+ length-1) );
    }
    printf("\n");
}

In case you are using GLib, it has two functions for that, g_strreverse() and g_utf8_strreverse()


Read Kernighan and Ritchie

#include <string.h>

void reverse(char s[])
{
    int length = strlen(s) ;
    int c, i, j;

    for (i = 0, j = length - 1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

Yet another:

#include <stdio.h>
#include <strings.h>

int main(int argc, char **argv) {

  char *reverse = argv[argc-1];
  char *left = reverse;
  int length = strlen(reverse);
  char *right = reverse+length-1;
  char temp;

  while(right-left>=1){

    temp=*left;
    *left=*right;
    *right=temp;
    ++left;
    --right;

  }

  printf("%s\n", reverse);

}

#include <cstdio>
#include <cstdlib>
#include <string>

void strrev(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

int main(int argc, char *argv[])
{
        char buffer[32];

        strcpy(buffer, "testing");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "a");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "abc");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "");
        strrev(buffer);
        printf("%s\n", buffer);

        strrev(NULL);

        return 0;
}

This code produces this output:

gnitset
a
cba

Note that the beauty of std::reverse is that it works with char * strings and std::wstrings just as well as std::strings

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}

Non-evil C, assuming the common case where the string is a null-terminated char array:

#include <stddef.h>
#include <string.h>

/* PRE: str must be either NULL or a pointer to a 
 * (possibly empty) null-terminated string. */
void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;
    *end_ptr = temp;
    str++;
    end_ptr--;
  }
}

C++ multi-byte UTF-8 reverser

My thought is that you can never just swap ends, you must always move from beginning-to-end, move through the string and look for "how many bytes will this character require?" I attach the character starting at the original end position, and remove the character from the front of the string.

void StringReverser(std::string *original)
{
  int eos = original->length() - 1;
  while (eos > 0) {
    char c = (*original)[0];
    int characterBytes;
    switch( (c & 0xF0) >> 4 ) {
    case 0xC:
    case 0xD: /* U+000080-U+0007FF: two bytes. */
      characterBytes = 2;
      break;
    case 0xE: /* U+000800-U+00FFFF: three bytes. */
      characterBytes = 3;
      break;
    case 0xF: /* U+010000-U+10FFFF: four bytes. */
      characterBytes = 4;
      break;
    default:
      characterBytes = 1;
      break;
    }

    for (int i = 0; i < characterBytes; i++) {
      original->insert(eos+i, 1, (*original)[i]);
    }
    original->erase(0, characterBytes);
    eos -= characterBytes;
  }
}

If you don't need to store it, you can reduce the time spent like this:

void showReverse(char s[], int length)
{
    printf("Reversed String without storing is ");
    //could use another variable to test for length, keeping length whole.
    //assumes contiguous memory
    for (; length > 0; length--)
    {
        printf("%c", *(s+ length-1) );
    }
    printf("\n");
}

I like Evgeny's K&R answer. However, it is nice to see a version using pointers. Otherwise, it's essentially the same:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *reverse(char *str) {
    if( str == NULL || !(*str) ) return NULL;
    int i, j = strlen(str)-1;
    char *sallocd;
    sallocd = malloc(sizeof(char) * (j+1));
    for(i=0; j>=0; i++, j--) {
        *(sallocd+i) = *(str+j);
    }
    return sallocd;
}

int main(void) {
    char *s = "a man a plan a canal panama";
    char *sret = reverse(s);
    printf("%s\n", reverse(sret));
    free(sret);
    return 0;
}

C++ multi-byte UTF-8 reverser

My thought is that you can never just swap ends, you must always move from beginning-to-end, move through the string and look for "how many bytes will this character require?" I attach the character starting at the original end position, and remove the character from the front of the string.

void StringReverser(std::string *original)
{
  int eos = original->length() - 1;
  while (eos > 0) {
    char c = (*original)[0];
    int characterBytes;
    switch( (c & 0xF0) >> 4 ) {
    case 0xC:
    case 0xD: /* U+000080-U+0007FF: two bytes. */
      characterBytes = 2;
      break;
    case 0xE: /* U+000800-U+00FFFF: three bytes. */
      characterBytes = 3;
      break;
    case 0xF: /* U+010000-U+10FFFF: four bytes. */
      characterBytes = 4;
      break;
    default:
      characterBytes = 1;
      break;
    }

    for (int i = 0; i < characterBytes; i++) {
      original->insert(eos+i, 1, (*original)[i]);
    }
    original->erase(0, characterBytes);
    eos -= characterBytes;
  }
}

#include <algorithm>
std::reverse(str.begin(), str.end());

This is the simplest way in C++.


If you're looking for reversing NULL terminated buffers, most solutions posted here are OK. But, as Tim Farley already pointed out, these algorithms will work only if it's valid to assume that a string is semantically an array of bytes (i.e. single-byte strings), which is a wrong assumption, I think.

Take for example, the string "año" (year in Spanish).

The Unicode code points are 0x61, 0xf1, 0x6f.

Consider some of the most used encodings:

Latin1 / iso-8859-1 (single byte encoding, 1 character is 1 byte and vice versa):

Original:

0x61, 0xf1, 0x6f, 0x00

Reverse:

0x6f, 0xf1, 0x61, 0x00

The result is OK

UTF-8:

Original:

0x61, 0xc3, 0xb1, 0x6f, 0x00

Reverse:

0x6f, 0xb1, 0xc3, 0x61, 0x00

The result is gibberish and an illegal UTF-8 sequence

UTF-16 Big Endian:

Original:

0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00

The first byte will be treated as a NUL-terminator. No reversing will take place.

UTF-16 Little Endian:

Original:

0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00

The second byte will be treated as a NUL-terminator. The result will be 0x61, 0x00, a string containing the 'a' character.


#include <algorithm>
std::reverse(str.begin(), str.end());

This is the simplest way in C++.


In the interest of completeness, it should be pointed out that there are representations of strings on various platforms in which the number of bytes per character varies depending on the character. Old-school programmers would refer to this as DBCS (Double Byte Character Set). Modern programmers more commonly encounter this in UTF-8 (as well as UTF-16 and others). There are other such encodings as well.

In any of these variable-width encoding schemes, the simple algorithms posted here (evil, non-evil or otherwise) would not work correctly at all! In fact, they could even cause the string to become illegible or even an illegal string in that encoding scheme. See Juan Pablo Califano's answer for some good examples.

std::reverse() potentially would still work in this case, as long as your platform's implementation of the Standard C++ Library (in particular, string iterators) properly took this into account.


#include <algorithm>
std::reverse(str.begin(), str.end());

This is the simplest way in C++.


#include <cstdio>
#include <cstdlib>
#include <string>

void strrev(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

int main(int argc, char *argv[])
{
        char buffer[32];

        strcpy(buffer, "testing");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "a");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "abc");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "");
        strrev(buffer);
        printf("%s\n", buffer);

        strrev(NULL);

        return 0;
}

This code produces this output:

gnitset
a
cba

#include <algorithm>
std::reverse(str.begin(), str.end());

This is the simplest way in C++.


Non-evil C, assuming the common case where the string is a null-terminated char array:

#include <stddef.h>
#include <string.h>

/* PRE: str must be either NULL or a pointer to a 
 * (possibly empty) null-terminated string. */
void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;
    *end_ptr = temp;
    str++;
    end_ptr--;
  }
}

In the interest of completeness, it should be pointed out that there are representations of strings on various platforms in which the number of bytes per character varies depending on the character. Old-school programmers would refer to this as DBCS (Double Byte Character Set). Modern programmers more commonly encounter this in UTF-8 (as well as UTF-16 and others). There are other such encodings as well.

In any of these variable-width encoding schemes, the simple algorithms posted here (evil, non-evil or otherwise) would not work correctly at all! In fact, they could even cause the string to become illegible or even an illegal string in that encoding scheme. See Juan Pablo Califano's answer for some good examples.

std::reverse() potentially would still work in this case, as long as your platform's implementation of the Standard C++ Library (in particular, string iterators) properly took this into account.


Note that the beauty of std::reverse is that it works with char * strings and std::wstrings just as well as std::strings

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}

I like Evgeny's K&R answer. However, it is nice to see a version using pointers. Otherwise, it's essentially the same:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *reverse(char *str) {
    if( str == NULL || !(*str) ) return NULL;
    int i, j = strlen(str)-1;
    char *sallocd;
    sallocd = malloc(sizeof(char) * (j+1));
    for(i=0; j>=0; i++, j--) {
        *(sallocd+i) = *(str+j);
    }
    return sallocd;
}

int main(void) {
    char *s = "a man a plan a canal panama";
    char *sret = reverse(s);
    printf("%s\n", reverse(sret));
    free(sret);
    return 0;
}

#include <cstdio>
#include <cstdlib>
#include <string>

void strrev(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

int main(int argc, char *argv[])
{
        char buffer[32];

        strcpy(buffer, "testing");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "a");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "abc");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "");
        strrev(buffer);
        printf("%s\n", buffer);

        strrev(NULL);

        return 0;
}

This code produces this output:

gnitset
a
cba

In the interest of completeness, it should be pointed out that there are representations of strings on various platforms in which the number of bytes per character varies depending on the character. Old-school programmers would refer to this as DBCS (Double Byte Character Set). Modern programmers more commonly encounter this in UTF-8 (as well as UTF-16 and others). There are other such encodings as well.

In any of these variable-width encoding schemes, the simple algorithms posted here (evil, non-evil or otherwise) would not work correctly at all! In fact, they could even cause the string to become illegible or even an illegal string in that encoding scheme. See Juan Pablo Califano's answer for some good examples.

std::reverse() potentially would still work in this case, as long as your platform's implementation of the Standard C++ Library (in particular, string iterators) properly took this into account.


Read Kernighan and Ritchie

#include <string.h>

void reverse(char s[])
{
    int length = strlen(s) ;
    int c, i, j;

    for (i = 0, j = length - 1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

It's been a while and I don't remember which book taught me this algorithm, but I thought it was quite ingenious and simple to understand:

char input[] = "moc.wolfrevokcats";

int length = strlen(input);
int last_pos = length-1;
for(int i = 0; i < length/2; i++)
{
    char tmp = input[i];
    input[i] = input[last_pos - i];
    input[last_pos - i] = tmp;
}

printf("%s\n", input);

A visualization of this algorithm, courtesy of slashdottir:

Visualization of the algorithm to reverse a string in place


Non-evil C, assuming the common case where the string is a null-terminated char array:

#include <stddef.h>
#include <string.h>

/* PRE: str must be either NULL or a pointer to a 
 * (possibly empty) null-terminated string. */
void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;
    *end_ptr = temp;
    str++;
    end_ptr--;
  }
}

Read Kernighan and Ritchie

#include <string.h>

void reverse(char s[])
{
    int length = strlen(s) ;
    int c, i, j;

    for (i = 0, j = length - 1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

Recursive function to reverse a string in place (no extra buffer, malloc).

Short, sexy code. Bad, bad stack usage.

#include <stdio.h>

/* Store the each value and move to next char going down
 * the stack. Assign value to start ptr and increment 
 * when coming back up the stack (return).
 * Neat code, horrible stack usage.
 *
 * val - value of current pointer.
 * s - start pointer
 * n - next char pointer in string.
 */
char *reverse_r(char val, char *s, char *n)
{
    if (*n)
        s = reverse_r(*n, s, n+1);
   *s = val;
   return s+1;
}

/*
 * expect the string to be passed as argv[1]
 */
int main(int argc, char *argv[])
{
    char *aString;

    if (argc < 2)
    {
        printf("Usage: RSIP <string>\n");
        return 0;
    }

    aString = argv[1];
    printf("String to reverse: %s\n", aString );

    reverse_r(*aString, aString, aString+1); 
    printf("Reversed String:   %s\n", aString );

    return 0;
}

If you're looking for reversing NULL terminated buffers, most solutions posted here are OK. But, as Tim Farley already pointed out, these algorithms will work only if it's valid to assume that a string is semantically an array of bytes (i.e. single-byte strings), which is a wrong assumption, I think.

Take for example, the string "año" (year in Spanish).

The Unicode code points are 0x61, 0xf1, 0x6f.

Consider some of the most used encodings:

Latin1 / iso-8859-1 (single byte encoding, 1 character is 1 byte and vice versa):

Original:

0x61, 0xf1, 0x6f, 0x00

Reverse:

0x6f, 0xf1, 0x61, 0x00

The result is OK

UTF-8:

Original:

0x61, 0xc3, 0xb1, 0x6f, 0x00

Reverse:

0x6f, 0xb1, 0xc3, 0x61, 0x00

The result is gibberish and an illegal UTF-8 sequence

UTF-16 Big Endian:

Original:

0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00

The first byte will be treated as a NUL-terminator. No reversing will take place.

UTF-16 Little Endian:

Original:

0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00

The second byte will be treated as a NUL-terminator. The result will be 0x61, 0x00, a string containing the 'a' character.


Another C++ way (though I would probably use std::reverse() myself :) as being more expressive and faster)

str = std::string(str.rbegin(), str.rend());

The C way (more or less :) ) and please, be careful about XOR trick for swapping, compilers sometimes cannot optimize that.

In such case it is usually much slower.

char* reverse(char* s)
{
    char* beg = s, *end = s, tmp;
    while (*end) end++;
    while (end-- > beg)
    { 
        tmp  = *beg; 
        *beg++ = *end;  
        *end =  tmp;
    }
    return s;
} // fixed: check history for details, as those are interesting ones

In case you are using GLib, it has two functions for that, g_strreverse() and g_utf8_strreverse()


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

unsigned char * utf8_reverse(const unsigned char *, int);
void assert_true(bool);

int main(void)
{
    unsigned char str[] = "mañana man~ana";
    unsigned char *ret = utf8_reverse(str,  strlen((const char *) str) + 1);

    printf("%s\n", ret);
    assert_true(0 == strncmp((const char *) ret, "ana~nam anañam", strlen("ana~nam anañam") + 1));

    free(ret);

    return EXIT_SUCCESS;
}

unsigned char * utf8_reverse(const unsigned char *str, int size)
{
    unsigned char *ret = calloc(size, sizeof(unsigned char*));
    int ret_size = 0;
    int pos = size - 2;
    int char_size = 0;

    if (str ==  NULL) {
        fprintf(stderr, "failed to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    while (pos > -1) {

        if (str[pos] < 0x80) {
            char_size = 1;
        } else if (pos > 0 && str[pos - 1] > 0xC1 && str[pos - 1] < 0xE0) {
            char_size = 2;
        } else if (pos > 1 && str[pos - 2] > 0xDF && str[pos - 2] < 0xF0) {
            char_size = 3;
        } else if (pos > 2 && str[pos - 3] > 0xEF && str[pos - 3] < 0xF5) {
            char_size = 4;
        } else {
            char_size = 1;
        }

        pos -= char_size;
        memcpy(ret + ret_size, str + pos + 1, char_size);
        ret_size += char_size;
    }    

    ret[ret_size] = '\0';

    return ret;
}

void assert_true(bool boolean)
{
    puts(boolean == true ? "true" : "false");
}

If you're looking for reversing NULL terminated buffers, most solutions posted here are OK. But, as Tim Farley already pointed out, these algorithms will work only if it's valid to assume that a string is semantically an array of bytes (i.e. single-byte strings), which is a wrong assumption, I think.

Take for example, the string "año" (year in Spanish).

The Unicode code points are 0x61, 0xf1, 0x6f.

Consider some of the most used encodings:

Latin1 / iso-8859-1 (single byte encoding, 1 character is 1 byte and vice versa):

Original:

0x61, 0xf1, 0x6f, 0x00

Reverse:

0x6f, 0xf1, 0x61, 0x00

The result is OK

UTF-8:

Original:

0x61, 0xc3, 0xb1, 0x6f, 0x00

Reverse:

0x6f, 0xb1, 0xc3, 0x61, 0x00

The result is gibberish and an illegal UTF-8 sequence

UTF-16 Big Endian:

Original:

0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00

The first byte will be treated as a NUL-terminator. No reversing will take place.

UTF-16 Little Endian:

Original:

0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00

The second byte will be treated as a NUL-terminator. The result will be 0x61, 0x00, a string containing the 'a' character.


Recursive function to reverse a string in place (no extra buffer, malloc).

Short, sexy code. Bad, bad stack usage.

#include <stdio.h>

/* Store the each value and move to next char going down
 * the stack. Assign value to start ptr and increment 
 * when coming back up the stack (return).
 * Neat code, horrible stack usage.
 *
 * val - value of current pointer.
 * s - start pointer
 * n - next char pointer in string.
 */
char *reverse_r(char val, char *s, char *n)
{
    if (*n)
        s = reverse_r(*n, s, n+1);
   *s = val;
   return s+1;
}

/*
 * expect the string to be passed as argv[1]
 */
int main(int argc, char *argv[])
{
    char *aString;

    if (argc < 2)
    {
        printf("Usage: RSIP <string>\n");
        return 0;
    }

    aString = argv[1];
    printf("String to reverse: %s\n", aString );

    reverse_r(*aString, aString, aString+1); 
    printf("Reversed String:   %s\n", aString );

    return 0;
}

Note that the beauty of std::reverse is that it works with char * strings and std::wstrings just as well as std::strings

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}

void reverseString(vector<char>& s) {
        int l = s.size();
        char ch ;
        int i = 0 ;
        int j = l-1;
        while(i < j){
                s[i] = s[i]^s[j];
                s[j] = s[i]^s[j];
                s[i] = s[i]^s[j];
                i++;
                j--;
        }
        for(char c : s)
                cout <<c ;
        cout<< endl;
}

#include <cstdio>
#include <cstdlib>
#include <string>

void strrev(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

int main(int argc, char *argv[])
{
        char buffer[32];

        strcpy(buffer, "testing");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "a");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "abc");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "");
        strrev(buffer);
        printf("%s\n", buffer);

        strrev(NULL);

        return 0;
}

This code produces this output:

gnitset
a
cba

If you are using ATL/MFC CString, simply call CString::MakeReverse().


In case you are using GLib, it has two functions for that, g_strreverse() and g_utf8_strreverse()


Another C++ way (though I would probably use std::reverse() myself :) as being more expressive and faster)

str = std::string(str.rbegin(), str.rend());

The C way (more or less :) ) and please, be careful about XOR trick for swapping, compilers sometimes cannot optimize that.

In such case it is usually much slower.

char* reverse(char* s)
{
    char* beg = s, *end = s, tmp;
    while (*end) end++;
    while (end-- > beg)
    { 
        tmp  = *beg; 
        *beg++ = *end;  
        *end =  tmp;
    }
    return s;
} // fixed: check history for details, as those are interesting ones

In case you are using GLib, it has two functions for that, g_strreverse() and g_utf8_strreverse()


Yet another:

#include <stdio.h>
#include <strings.h>

int main(int argc, char **argv) {

  char *reverse = argv[argc-1];
  char *left = reverse;
  int length = strlen(reverse);
  char *right = reverse+length-1;
  char temp;

  while(right-left>=1){

    temp=*left;
    *left=*right;
    *right=temp;
    ++left;
    --right;

  }

  printf("%s\n", reverse);

}

It's been a while and I don't remember which book taught me this algorithm, but I thought it was quite ingenious and simple to understand:

char input[] = "moc.wolfrevokcats";

int length = strlen(input);
int last_pos = length-1;
for(int i = 0; i < length/2; i++)
{
    char tmp = input[i];
    input[i] = input[last_pos - i];
    input[last_pos - i] = tmp;
}

printf("%s\n", input);

A visualization of this algorithm, courtesy of slashdottir:

Visualization of the algorithm to reverse a string in place


Read Kernighan and Ritchie

#include <string.h>

void reverse(char s[])
{
    int length = strlen(s) ;
    int c, i, j;

    for (i = 0, j = length - 1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

Note that the beauty of std::reverse is that it works with char * strings and std::wstrings just as well as std::strings

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

unsigned char * utf8_reverse(const unsigned char *, int);
void assert_true(bool);

int main(void)
{
    unsigned char str[] = "mañana man~ana";
    unsigned char *ret = utf8_reverse(str,  strlen((const char *) str) + 1);

    printf("%s\n", ret);
    assert_true(0 == strncmp((const char *) ret, "ana~nam anañam", strlen("ana~nam anañam") + 1));

    free(ret);

    return EXIT_SUCCESS;
}

unsigned char * utf8_reverse(const unsigned char *str, int size)
{
    unsigned char *ret = calloc(size, sizeof(unsigned char*));
    int ret_size = 0;
    int pos = size - 2;
    int char_size = 0;

    if (str ==  NULL) {
        fprintf(stderr, "failed to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    while (pos > -1) {

        if (str[pos] < 0x80) {
            char_size = 1;
        } else if (pos > 0 && str[pos - 1] > 0xC1 && str[pos - 1] < 0xE0) {
            char_size = 2;
        } else if (pos > 1 && str[pos - 2] > 0xDF && str[pos - 2] < 0xF0) {
            char_size = 3;
        } else if (pos > 2 && str[pos - 3] > 0xEF && str[pos - 3] < 0xF5) {
            char_size = 4;
        } else {
            char_size = 1;
        }

        pos -= char_size;
        memcpy(ret + ret_size, str + pos + 1, char_size);
        ret_size += char_size;
    }    

    ret[ret_size] = '\0';

    return ret;
}

void assert_true(bool boolean)
{
    puts(boolean == true ? "true" : "false");
}

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to reverse

Right way to reverse a pandas DataFrame? Reverse Contents in Array Reverse a string without using reversed() or [::-1]? angular ng-repeat in reverse Reversing an Array in Java Reversing a String with Recursion in Java Print a list in reverse order with range()? How to reverse an std::string? Python list sort in descending order How to get a reversed list view on a list in Java?