在位压缩字符串(C++)

Compress string of bits in place (C++)

本文关键字:C++ 字符串 压缩      更新时间:2023-10-16

我正在尝试制作一个函数来压缩0和1的字符串。也就是说,"00010111100101"变为"30104100101"。这应该是一个非常复杂的程序吗?我的代码看起来很乱。

原型应该看起来像:

static void compress_bitstring(std::string& str) { 
   // compression algorithm
} 

好的,这是我的最终答案,压缩runlengths>9和重构重复代码。

template<typename T>
std::string to_string(T t)
{
    std::ostringstream str;
    str << t;
    return str.str();
}
static void compress_bitstring(std::string& str)
{
    std::string result;
    int count = 0;
    char last = 0;
    auto add_to_result = [&]{
        if (count > 2)
            result += to_string(count) + last;
        else for (auto loop=0; loop<count; ++loop)
            result += last;
    };
    for (char ch : str)
    {
        if ((last == 0  ||  ch == last)  &&  count < 9)
            ++count;
        else {
            add_to_result();
            count = 1;
        }
        last = ch;
    }
    add_to_result();
    swap(result, str);
}
int main()
{
    std::string str("00010111100101");
    compress_bitstring(str);
    assert(str == "30104100101");
    str = "0001011110010100000000000000000000000001";
    compress_bitstring(str);
    assert(str == "301041001019090701");
    return 0;
}

这是我的方法

更新意识到我的答案可以更短、更全面(多亏了Nik Bougalis)

#include <iostream>
#include <sstream>
#include <string>
static void compress_bitstring(std::string& str) { 
  std::stringstream ss;
  std::string cur_num;
  int count = 1;
  for (int i = 0; i < str.size()-1; ++i){
    if (str[i] == str[i+1]){
      ++count;
      cur_num = str[i];
      if (i == str.size()-2){
        ss << count << cur_num;
      } else{
        if (count == 9){
          ss << count << cur_num;
          count = 0;
        }
      }
    } else if (count > 2){
        ss << count << cur_num;
        count = 1;
        if (i == str.size()-2){
          ss << str[i+1];
        }
    } else if (i != str.size()-2){
        for (int j = 0; j < count; ++j){
          ss << str[i];
        }
        count = 1;
    } else{
      ss << str[i] << str[i];
    }
  }
  str = ss.str();
}
static void decode_bitstring(std::string& str){
  int i = 0;
  int count;
  std::stringstream ss;
  while (i < str.size()){
    std::stringstream to_int;
    to_int << str[i];
    to_int >> count;
    if (count > 1){
      for (int j = 0; j < count; ++j){
        ss << str[i+1];
      }
      i = i + 2;
    } else{
      ss << str[i];
      ++i;
    }
  }
  str = ss.str();
}
int main(){
  std::string binary_num =  "0001011110010100000000000000000000000001";
  std::cout << binary_num << 'n';
  compress_bitstring(binary_num);
  std::cout << binary_num << 'n';
  decode_bitstring(binary_num);
  std::cout << binary_num << 'n';
  return 0;
}

编辑2我还提供了一个解码器选项。

输出:

nero@ubuntu:~/learn$ ./lc
0001011110010100000000000000000000000001
301041001019090701
0001011110010100000000000000000000000001
template<typename T>
std::string to_string(T t)
{
    std::ostringstream str;
    str << t;
    return str.str();
}
static void compress_bitstring(std::string& str)
{
    std::string result;
    int count = 0;
    char last = 0;
    for (char ch : str)
    {
        if (last == 0  ||  ch == last)
            ++count;
        else {
            if (count > 2)
                result += to_string(count) + last;
            else for (auto loop=0; loop<count; ++loop)
                result += last;
            count = 1;
        }
        last = ch;
    }
    if (count > 2)
        result += to_string(count) + last;
    else for (auto loop=0; loop<count; ++loop)
            result += last;
    swap(result, str);
}
int main()
{
    std::string str("00010111100101");
    compress_bitstring(str);
    assert(str == "30104100101");
    return 0;
}
std::string compress1(std::string &s) {
    char c = s[0];
    int counter = 1;
    std::stringstream ss;
    for (size_t i = 1; i < s.length(); i++) {
        if (c != s[i]) {
            if (counter > 2) ss << counter;
            if (counter == 2) ss << c;
            ss << c;
            counter = 0;
        }
        c = s[i];
        counter++;
    }
    if (counter > 2) ss << counter;
    if (counter == 2) ss << c;
    ss << c;
    return ss.str();
}

输出:

compress1("00010111100101"): 30104100101
compress1("000101111001011"): 301041001011

在这里我发布了我的逻辑,它可能会对您有所帮助。

 #include<string.h>
int main(){
   char* str ="00010111100101";
   char* result = malloc(strlen(str)+1);
   int i = 0;
   char *q;
   char * p = str;
   result[i++] = str[0];
   do{
      q = strchr(str,str[0]=='0'?'1':'0'); //Searching for the opposite char.
     result[i++] = (q == ''? str+strlen(str) : q ) - p + '0'; // Storing the difference in result 
     str = p = q;   //updating str and p
   }while(q != '');
   result[i] = '';
   printf("Compressed Result = %s",result);
   return 0;
}

http://codepad.org/Qn8NEuB7