Stuart Blackler
Stuart Blackler

Reputation: 3772

Convert C# to C++ Bitwise shift

I have the following code in c# which reverses a string:

char[] charArray = s.ToCharArray();
int len = s.Length - 1;

for (int i = 0; i < len; i++, len--)
{
   charArray[i] ^= charArray[len];
   charArray[len] ^= charArray[i];
   charArray[i] ^= charArray[len];
}

return new string(charArray);

I am trying to convert it to C++ as an intellectual exercise more than anything. Here is what I have so far:

void main(void)
{
    char* str = "testing";
    char* result;
    int len;

    len = strlen(str);

    if (len <= 12)
    {
        result = new char[strlen(str)];
        for (int i = 0; i < len; i++, len--)
        {
             result[i] ^= str[len];
             result[len] ^= str[i];
             result[i] ^= str[len];
        }
    }
    else{
        std::reverse(str, &str[strlen(str)]);
    }

    cout << endl << result << endl;

    // cleanup 
    str = NULL;
    result = NULL;
} 

In .Net if the string is <= 12 (I think it's twelve) xor is faster than array reverse. Source - Sam Saffron I am basically trying to see if it still holds up in C++.

The string comes out in a weird format (════╣¥¿ë²²² to be precise).

Any ideas?

Note: I know the else statement doesn't work, I'll figure that bit out after ;)

Note 2: I am probably doing this completely wrong, so feel free to point absolutely anything out

Update

Thanks to everyone that has participated. I haven't played with c++ in a fair few years (and it shows) and thought it would be quiet easy to convert but obviously not. Think it's best I abandon this idea. Thanks again

Upvotes: 0

Views: 343

Answers (3)

Pubby
Pubby

Reputation: 53017

xor swap is for swapping. If you're copying into a result array then that's assigning, not swapping. Also, you must only iterate half-way through the array, otherwise you swap it twice.

Here is a translation of the C# code:

#include <iostream>
#include <algorithm>

int main(void)
{
    char str[] = "testing"; // arrays have automatic storage - no need to new/delete
    const size_t str_len = sizeof(str)-1; // sizeof(str) returns size of the array

    if (str_len <= 12) // because str_len is a constant expression, the other branch will be compiled-out
    {
        // this should probably use iterators (pointers) but oh well
        for (size_t i = 0, len = str_len-1; i < str_len/2; i++, len--)
        {
             str[i]   ^= str[len];
             str[len] ^= str[i];
             str[i]   ^= str[len];
        }
    }
    else{
        std::reverse(str, str + str_len); // str decays to a pointer
    }

   std::cout << str << '\n'; // don't use endl if you don't need to flush
}

This is pretty bad code. Just use std::string and std::reverse. It is faster than xor and only 2 lines long.

std::string str = "testing"
std::reverse(str.begin(), str.end());

Upvotes: 2

Seth Carnegie
Seth Carnegie

Reputation: 75130

A few things:

result = new char[strlen(str)];

Should be

result = new char[len + 1];

len because you've already calculated the length of str, and + 1 to make room for the NUL terminator.

Secondly, you need to copy the string into result before operating on it, because otherwise your array is full of garbage otherwise:

strcpy(result, str);

Thirdly,

std::reverse(str, &str[strlen(str)]);

Is wrong for two reasons: one, because you can't modify string literals, and two, because you should be using result:

std::reverse(result, result + len);

But if you do that, you also need to copy str into result first.

And lastly, setting a pointer to NULL does not deallocate the memory it points to. You have to

delete[] result; // delete[] because new[]

Note that for this to work even when the else is taken (and therefore result is not made to point to allocated memory), you need to do

char* result = NULL; // delete[] is defined as a nop on NULL pointers

All the above applies if you're sure you want to use C-strings. Once you get the hang of pointers, you can graduate to std::string:

std::string str("testing");

std::reverse(std::begin(str), std::end(str)); // or if you don't want to do it in-place,
                                              // std::string result(str.rbegin(), str.rend());

Upvotes: 2

Tony The Lion
Tony The Lion

Reputation: 63190

A better way of doing it, more C++, less C

std::string mystring = "testing";

std::string reversed;

for(std::string::iterator str_it = mystring.rbegin(); str_it != mystring.rend(); ++str_it)
{
  reversed += *str_it;
}

std::cout << reversed << std::endl;

Upvotes: 1

Related Questions