C++中用于std::string的位运算符

3
我的问题是关于如何在 C++ 的字符串(std::string)上使用位运算符。可以通过重载或函数来实现。
下面是一个针对 std::string 实现异或(^)功能的示例代码:
std::string XOR(std::string value, std::string key)
{
  std::string retval(value);
  long unsigned int klen = key.length();
  long unsigned int vlen = value.length();
  unsigned long int k = 0;
  unsigned long int v = 0;
  for (; v < vlen; v++) {
    retval[v] = value[v] ^ key[k];
    k = (++k < klen ? k : 0);
  }
  return retval;
}

我现在需要的是NOT/~,AND/&和OR/|的替代品。 以下是C++代码(最后两行需要):

//note: matrix_content[][] holds unsigned, *checked* integers...
//      char(foo) works... 
std::string vertical_master   = "";
for (unsigned short int k = 0; k < axis_max; k++) {
  for (unsigned short int l = 0; l < axis_max; l++) {
    horizontal_master += char(matrix_content[l][k]);
    vertical_master   += char(matrix_content[k][l]);
  }
}

std::string vertical_shift1_0 = vertical_master;
usigned short int bit = "@"; //<- just an example... chatched via
                             //   std::string::substr() and std::string::c_str()
for (unsigned long int x = 0; x < axis_max; x++) {
  vertical_shift1_0 += char(bit);
}
std::string vertical_shift2_0;
for (unsigned long int x = 0; x < axis_max; x++) {
  vertical_shift2_0 += char(0);
}
vertical_shift2_0 += vertical_master;

std::string vertical_or  = ~(vertical_shift1 | vertical_shift2);
std::string vertical_and = ~(vertical_shift1_0 & vertical_shift2_0);

在PHP/Perl中,我可以做一些恶意 :-P 的事情。
$vertical_shift1_0 = $vertical_master.str_repeat(chr(0), $axis_max);
$vertical_shift2_0 = str_repeat(chr(0), $axis_max).$vertical_master;
$vertical_or       = chunk_split(~($vertical_shift1 | $vertical_shift2), $axis_max, chr(170));
$vertical_and      = chunk_split(~($vertical_shift1_0 & $vertical_shift2_0), $axis_max, chr(170));

我想知道如何使用AND/OR/NOT,因为我错过了它们的使用方法;不过XOR是可以使用的。


1
如果“字符串”的长度是固定的,您应该使用std::bitset<N>,它已经为您重载了>><<|&等操作符。 - kennytm
你的异或代码不对称,因为字符串长度的处理方式不同。 - danio
嗨,乔治!也许我之后得为这个新手问题道歉,但是你不应该检查参数的长度吗?或者说:如果值比密钥短,XOR函数会发生什么?那么剩下的符号应该与密钥匹配,对吧?谢谢您提供任何提示! - astriffe
3个回答

5

当你通过[]操作符从字符串中取出一个字符后,你可以使用所有想要的位运算符。C/C++将有符号/无符号字符视为数值类型(不幸的是)。

如果你正在进行大量的位运算,你可以考虑使用专用的位数据结构之一

  • STL中的bitset用于固定长度的位集合
  • boost中的bit_vector用于动态长度的位集合

3

您可以编写一个使用函数参数的通用实现:

template <typename T>
struct or {
   T operator()( T ch1, T ch2 ) {
      return ch1 | ch2;
   }
};
template <typename T>
struct xor {
   T operator()( T ch1, T ch2 ) {
      return ch1 ^ ch2;
   }
};
template <typename InputIterator1, typename InputIterator2, 
          typename OutputIterator, typename Functor>
void apply( InputIterator1 begin1, InputIterator1 end1,
            InputIterator2 begin2, InputIterator2 end2,
            OutputIterator output, Functor f )
{
   if ( (end1-begin1) != (end2-begin2) ) throw std::exception(); // throw some more meaningful exception...
   while ( begin1 != end1 ) 
   {
      *output++ = f( *begin1++, *begin2++ );
   }
}
// usage:
void string_operations( std::string str1, // by value so we can change it
     std::string const & str2 )
{
   // in place modification
   apply( str1.begin(), str1.end(), str2.begin(), str2.end(), 
          str1.begin(), or<char>() );

   // out of place: copy
   std::string and_string;
   apply( str1.begin(), str1.end(), str2.begin(), str2.end(), 
          std::back_inserter(and_string), and<char>() );
}

0

假设我理解了您的需求...

对于AND:

std::string AND(std::string value, std::string key)
{
  uint32_t klen = key.length();
  uint32_t vlen = value.length();
  uint32_t max_len = (klen > vlen) ? klen : vlen;
  char * ret_str = (char *)calloc(max_len, sizeof(char));
  const char * v_str = value.c_str();
  const char * k_str = key.c_str();
  for (uint32_t i = 0; i < max_len; i++)
  {
    if (i >= klen || i >= vlen)
      ret_str[i] = 0x00;
    else
      ret_str[i] = v_str[i] & k_str[i];
  }
  std::string to_return(ret_str);
  free(ret_str);
  return to_return;
}

而不是

std::string NOT(std::string value)
{
  const char v_str = value.c_str();
  char * ret_str = (char *)calloc(value.size(), sizeof(char));
  for (uint32_t i = 0; i < value.size(); i++)
  {
    ret_str[i] = ~(v_str[i]);
  }
  string to_return(ret_str);
  free(ret_str);
  return to_return;
}

and OR:

std::string OR(std::string value, std::string key)
{
  uint32_t klen = key.length();
  uint32_t vlen = value.length();
  uint32_t max_len = (klen > vlen) ? klen : vlen;
  char * ret_str = (char *)calloc(max_len, sizeof(char));
  const char * v_str = value.c_str();
  const char * k_str = key.c_str();
  for (uint32_t i = 0; i < max_len; i++)
  {
    if (i >= klen || i >= vlen)
    {
      ret_str[i] = (klen > vlen) ? k_str[i] : v_str[i];
    }
    else
    {
      ret_str[i] = v_str[i] | k_str[i];
    }
  }
  std::string to_return(ret_str);
  free(ret_str);
  return to_return;
}

提前道歉,如有任何错误。 :-S


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接