C++ CRC 实现 代码demo

这篇博客介绍了如何使用C++实现CRC码计算,提供了代码示例,并展示了编译和运行结果。文章旨在帮助读者理解CRC码(帧校验序列)的计算及其在数据校验中的应用。

代码如下:

#include<memory>
#include<iostream>
#include<vector>
#include<functional>
#include<cstring>

class DataBlob{
  public:
    DataBlob():length_(0) {}
    const std::unique_ptr<uint8_t[]> & data() const { return data_; }
    size_t length() const { return length_; }
    void set_data(std::unique_ptr<uint8_t[]> data) { data_ = std::move(data); }
    void set_length(size_t len) { length_ = len; }
  private:
    std::unique_ptr<uint8_t[]> data_;
    size_t length_;
};

class CRC {
  public:
    CRC();
    void setData(std::vector<uint8_t> & vec);
    void setDivide(std::vector<uint8_t> & vec);
    bool Check();
    bool AddFCS();
    void print() const;

  private:
    DataBlob data_;
    DataBlob divide_;
};
CRC::CRC()
{
}
void CRC::setData(std::vector<uint8_t> & vec)
{
  data_.set_length(vec.size());
  data_.set_data(std::unique_ptr<uint8_t []>(new uint8_t[vec.size()]));
  uint8_t *data_ptr = data_.data().get();
  std::copy(vec.begin(), vec.end(), data_ptr);
}
void CRC::setDivide(std::vector<uint8_t> & vec)
{
  divide_.set_length(vec.size());
  divide_.set_data(std::unique_ptr<uint8_t []>(new uint8_t[vec.size()]));
  uint8_t *data_ptr = divide_.data().get();
  std::copy(vec.begin(), vec.end(), data_ptr);
}
bool CRC::Check()
{
  if (0 == data_.length() || 0 == divide_.length()) 
  {
    return false;
  }
  uint8_t *data_ptr = data_.data().get();
  uint8_t *divide_ptr = divide_.data().get();
  size_t data_len = data_.length();
  size_t divide_len = divide_.length();

  const uint8_t *data_ptr_end = data_ptr + data_len;
  //进行CRC计算
  while (1)
  {
    //如果剩余长度小于被除数长度
    if (divide_len > data_ptr_end - data_ptr)
    {
      break;
    }

    if (0 == *data_ptr) {
      //忽略前导0
      ++data_ptr;
    } else {
      //模2除法
      for (int i=0; i<divide_len; ++i)
      {
        data_ptr[i] = data_ptr[i] ^ divide_ptr[i];
      }
    }
  }
  while (data_ptr_end != data_ptr)
  {
    //余数不为0,则check失败
    if (*data_ptr == 1) return false;
    ++data_ptr;
  }
  return true;
}

bool CRC::AddFCS()
{
  if (0 == data_.length() || 0 == divide_.length()) 
  {
    return false;
  }
  uint8_t *data_ptr = data_.data().get();
  uint8_t *divide_ptr = divide_.data().get();
  size_t data_len = data_.length();
  size_t divide_len = divide_.length();

  //在要发送的数据后面,填补divide_len-1个0,存放FCS
  std::unique_ptr<uint8_t []> new_data(new uint8_t[data_len + divide_len - 1]);
  memset(new_data.get(), 0, data_len + divide_len - 1);
  memcpy(new_data.get(), data_ptr, data_len);

  uint8_t * new_data_ptr = new_data.get();
  uint8_t * new_data_ptr_end = new_data_ptr + data_len + divide_len -1;
  //进行CRC计算
  while (1)
  {
    //如果剩余长度小于被除数长度
    if (divide_len > new_data_ptr_end - new_data_ptr)
    {
      break;
    }

    if (0 == *new_data_ptr) {
      //忽略前导0
      ++new_data_ptr;
    } else {
      //模2除法
      for (int i=0; i<divide_len; ++i)
      {
        new_data_ptr[i] = new_data_ptr[i] ^ divide_ptr[i];
      }
    }
  }
  //用原数据覆盖前面data_len-1个字节,只保留余数,即FCS
  memcpy(new_data.get(), data_ptr, data_len);

  data_.set_data(std::move(new_data));
  data_.set_length(data_len + divide_len - 1);

  return true;
}

void CRC::print() const
{
  std::cout<<"data:";
  uint8_t *ptr = data_.data().get();
  for (int i=0; i<data_.length(); ++i)
  {
    std::cout<<(int)ptr[i];
  }
  std::cout<<" divider:";
  ptr = divide_.data().get();
  for (int i=0; i<divide_.length(); ++i)
  {
    std::cout<<(int)ptr[i];
  }
  std::cout<<std::endl;
}
void crc_test_1()
{
  CRC crc;
  {
    std::cout<<"test case 1===========================>\n";
    std::vector<uint8_t> data = {1,0,0,1,1,0,1};
    std::vector<uint8_t> divide = {1,1,1,1};

    crc.setData(data);
    crc.setDivide(divide);
    crc.print();
    if (false == crc.AddFCS())
    {
      std::cout<<"CRC::AddFCS failed\n";
      return;
    }
    std::cout<<"After add FCS...\n";
    crc.print();
    if (false == crc.Check())
    {
      std::cout<<"CRC::Check failed\n";
      return;
    }
    std::cout<<"CRC Check ok.\n";
  }
  {
    std::cout<<"test case 2===========================>\n";
    std::vector<uint8_t> data = {1,0,1,0,1,1,0,1,1,1,0,0,1};
    std::vector<uint8_t> divide = {1,0,1,0};

    crc.setData(data);
    crc.setDivide(divide);
    crc.print();
    if (false == crc.AddFCS())
    {
      std::cout<<"CRC::AddFCS failed\n";
      return;
    }
    std::cout<<"After add FCS...\n";
    crc.print();
    if (false == crc.Check())
    {
      std::cout<<"CRC::Check failed\n";
      return;
    }
    std::cout<<"CRC Check ok.\n";
  }
}

int main(int argc, const char** argv) 
{
  crc_test_1();
  return 0;
}

编译:

g++ -o crc crc_test.cc -std=c++14

运行结果:

 

参考博客:

https://www.cnblogs.com/zpchcbd/p/15931308.htmlCRC码计算及原理(FCS帧校验序列生成)_fcs校验_cggwz的博客-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值