3

Okay, so I'm trying to reverse a C style string in C++ , and I'm coming upon some weird output. Perhaps someone can shed some light?

Here is my code:

 int main(){    

    char str[] = "string";
    int strSize = sizeof(str)/sizeof(char);

    char str2[strSize];

    int n = strSize-1;
    int i =0;


    while (&str+n >= &str){ 
        str2[i] = *(str+n);         
        n--;
        i++;
    }

    int str2size = sizeof(str)/sizeof(char);
    int x;

    for(x=0;x<str2size;x++){
        cout << str2[x];
    }

}

The basic idea here is just making a pointer point to the end of the string, and then reading it in backwards into a new array using pointer arithmetic.

In this particular case, I get an output of: " gnirts" There is an annoying space at the beginning of any output which I'm assuming is the null character? But when I try to get rid of it by decrementing the strSize variable to exclude it, I end up with some other character on the opposite end of the string probably from another memory block.

Any ideas on how to avoid this? PS: (would you guys consider this a good idea of reversing a string?)

volk
  • 1,196
  • 1
  • 12
  • 31
  • Use valgrind (if you're on Linux, other tools on Windows) to check if you are accessing memory improperly. As for whether this is the right approach, it depends on what the context is. If it's not a school assignment, you'd be better off using `std::reverse_copy` or similar. – John Zwinck Jul 11 '11 at 02:44

6 Answers6

7

A valid string should be terminated by a null character. So you need to keep the null character in its original position (at the end of the string) and only reverse the non-null characters. So you would have something like this:

str2[strSize - 1] = str[strSize - 1]; // Copy the null at the end of the string

int n = strSize - 2; // Start from the penultimate character
  • 1
    I would just write `str2[strSize - 1] = 0;` because it is simpler and really guarantees that str2 will end with a null termination character. – David Grayson Jul 11 '11 at 03:09
1

I would let the C++ standard library do more of the work...

#include <cstddef>
#include <algorithm>
#include <iterator>
#include <iostream>

int main()
{
    typedef std::reverse_iterator<char const*> riter_t;

    char const str[] = "string";
    std::size_t const strSize = sizeof(str);
    char str2[strSize] = { };
    std::copy(riter_t(str + strSize - 1), riter_t(str), str2);
    std::cout << str2 << '\n';
}
ildjarn
  • 62,044
  • 9
  • 127
  • 211
1

There is an algorithm in the Standard Library to reverse a sequence. Why reinvent the wheel?

#include <algorithm>
#include <cstring>
#include <iostream>

int main()
{
   char str[] = "string";

   std::reverse(str, str + strlen(str)); // use the Standard Library

   std::cout << str << '\n';
}
Blastfurnace
  • 18,411
  • 56
  • 55
  • 70
1

@ildjarn and @Blastfurnace have already given good ideas, but I think I'd take it a step further and use the iterators to construct the reversed string:

std::string input("string");

std::string reversed(input.rbegin(), input.rend());

std::cout << reversed;
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0
 while (&str+n >= &str){

This is nonsense, you want simply

while (n >= 0) {

and

 str2[i] = *(str+n);

should be the much more readable

str2[i] = str[n];
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

Your while loop condition (&str+n >= &str) is equivalent to (n >= 0).

Your *(str+n) is equivalent to str[n] and I prefer the latter.

As HappyPixel said, your should start n at strSize-2, so the first character copied will be the last actual character of str, not the null termination character of str.

Then after you have copied all the regular characters in the loop, you need to add a null termination character at the end of the str2 using str2[strSize-1] = 0;.

Here is fixed, working code that outputs "gnirts":

#include <iostream>
using namespace std;
int main(int argc, char **argv){    
    char str[] = "string";
    int strSize = sizeof(str)/sizeof(char);

    char str2[strSize];

    int n = strSize-2;  // Start at last non-null character
    int i = 0;

    while (n >= 0){ 
        str2[i] = str[n];         
        n--;
        i++;
    }
    str2[strSize-1] = 0;   // Add the null terminator.

    int str2size = sizeof(str)/sizeof(char);
    int x;

    cout << str2;
}
David Grayson
  • 84,103
  • 24
  • 152
  • 189