简体   繁体   中英

XORing a string in C++11

I am trying to implemnt a simple XOR encoding on a string in C++11 (Visual Studio 2017).However, I am having some problems implementing it. The following code would be my standard (C) approach:

char* encode(char*  input) {
   for (unsigned int i = 0; i < strlen(input); i++) {
        input[i] ^= 0xA; 
   }
   return(input);
 }

 int main(void){
   printf(encode(encode("Hello World!")));
 }

But it is no valid code because the string ("Hello Wolrd!") is of type const char*.

I tried several things to fix the problem:

  1. Cast the string to (char*) (ie, encode( (char*)"Hello World!") ) but it throws an exception when trying to XOR the first byte.

  2. Using a temp char* in my encoding function, which also resulted in stack coruption.

     char* encode(const char* input) { char temp[128]; strncpy(temp, input, 128); for (unsigned int i = 0; i < strlen(temp); i++) { temp[i] ^= 0xA; } return(temp); } 
  3. I tried using std:string but it also did not work out.

     const char* encode(const char* input) { std::string temp(input); for (char& c : temp) { c ^= 0xA; } return(temp.c_str()); } 

What am I missing?

Just use std::string in function signature, and operate on std::string entirely. No C-string involved.

#include <string>
#include <iostream>

std::string encode(std::string input)
{
    for (char& c : input) {
        c  ^= 0xA;
    }
    return input;
}

int main()
{
    std::cout << encode(encode("Hello World!"));
}

I recommend against using C-string because it complicates things in these ways:

  • String literal ( "Hello World" ) is read-only. You can't modify it.
  • If you use local character array ( char[SIZE] ), you can't return it out of the function. The only thing you can do, which is wrong, is to return a dangling pointer to the local array.
  • If you allocate a character array dynamically ( malloc or new[] ), you must manually manage the the allocated memory, which is clumsy.

std::string automatically manages everything for you. Just use it.

Jarod's answer is one of sanest ways to do that. Simply don't pass constants. Or you'll need to create new storage. you can't use local variable for that. Main problem is... that is pure C code.

In C++ you write something like this:

#include <string>
#include <algorithm>
#include <iostream>

template<class T> T encode (const T& s)
{
    using CharT = typename T::value_type;
    T temp;
    for (const CharT& i : s)
    {
        temp += i ^ (CharT)0x0A;
    }
    return temp;
}

template<class T> T encode (T& s)
{
    using CharT = typename T::value_type;
    for (CharT& i : s)
    {
        i = i ^ (CharT)0x0A;
    }
    return s;
}

int main()
{
    using namespace std;
    string str("hello");

    cout << encode(str) << endl;
    cout << encode(string("Hello"))<< endl;
    cout << encode(encode(string("Hello")));
}

One overloaded function reuses supplied storage, another one creates a temporal. Memory management is automatic and confined to std::string , usage of templates allows use for strings with different character type or for classes that have same semantic as std::string . Of course a static_assert can be used to limit usage or specialize template for different types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM