65.9K
CodeProject 正在变化。 阅读更多。
Home

CABMBitSet 和 CFlexBitSet - 紧凑存储, 易于使用

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (2投票s)

2005 年 3 月 29 日

CPOL

5分钟阅读

viewsIcon

34050

downloadIcon

493

创建用于存储 BOOL、枚举或其他有限值集合的紧凑型存储。

Sample Image

引言

在嵌入式和 GUI 世界中,我经常需要存储大量的 BOOL 标志或具有有限范围(例如 0 到 7)的 enums,但我不想为此占用一个 INT 来存储到磁盘。过去,我遵循了同事们的方法,创建整数和掩码来提取正确的位来存储或检索值。最近,一位同事提出了一个很好的想法,将此抽象化为数组。我决定从头开始尝试这个想法,并创建了 CABMBitSet 模板类。

想法是通过数组“[]”运算符来访问位以设置和检索值,使其接受 BOOL 进行设置,并在检索时返回 BOOL。然后我想更进一步。

为什么只限制接口为 BOOL?我经常存储 enum 值,其中 enum 的范围相当小,肯定不是 32,000(左右)。所以我创建了 CFlexBitSet 模板类。这个类不仅允许您定义数组中有多少个元素,还允许您定义每个元素需要多少位,以及它应该如何(类类型(BOOLint 等))呈现给外部代码。

两者都允许您

  • 使用“[]”运算符设置/获取值。
  • 以字符串格式获取位值(主要用于调试)。
  • 从您自己的 UINT32 值数组(将保存到磁盘)中获取/设置位数组。

背景

大多数人会觉得这段代码是过度设计……没关系。我写它是为了好玩,也是为了让我的生活更轻松。如果您觉得有用,那只是一个奖励。

另外,您会看到代码中使用了 CCDoc 风格的注释。如果您没有该工具(只是一个 EXE)并想重新生成文档,只需快速搜索 CCDoc 即可在 SF 上找到。如果您想查看 HTML 文档,演示项目下载中包含了文档……

使用代码

使用起来相当简单。下面我展示了一般的交互方式,并将保存到文件的部分留给用户。我注意到另一篇文章要求用户代码传入一个 (FILE*) 来保存/检索值。我没有这样做,因为在将数据发送到文件之前,用户可能有很多事情要做,而且用户代码可能不希望使用 (FILE*) 来持久化到磁盘。因此,这部分留给用户代码。

  1. 为您的需求 typedef 模板 - 对于此步骤,您需要知道您正在处理多少个元素。
    typedef CFlexBitSet<10,1,BOOL> CFlexBitSet_10_BOOL;
    typedef CFlexBitSet<17,2,int> CFlexBitSet_17_int2;
    typedef CABMBitSet<17> CBitSetBOOL17;
  2. 声明变量实例以供使用.
    CFlexBitSet_10_BOOL m_BitSet;
    CFlexBitSet_17_int2 m_BitSet2int;
    CBitSetBOOL17 m_BoolSet;
  3. 设置或获取变量的值.
      m_BitSet2int[ m_iElement ] = m_iSetValue;
      m_BitSet[2] = TRUE;
      m_BoolSet[3] = TRUE;
    
    if ( m_BoolSet[2] ) {
      ...
    }
    if ( m_BitSet[2] ) {
      ...
    }
    If(m_BitSet2int[ m_iElement ] == iSomeTestValue){
      ...
    }
  4. 从外部存储获取/设置整个数组值(用于在实例之间持久化数据).
    UINT32* pTest = NULL;
    int SizeArray;
    
    BitSet.GetRawData(pTest, SizeArray);
    
    StoreUINT32ArrayToFile( pTest, SizeArray );
    //some custom code you (user code) write
    
    
         <  ... time passes and we need to get it from the file ... >
    
    GetFileStoredUINTArrayFromFile( pTest, SizeArray );
    //some custom code you (user code) write
    
    
    BitSet.SetRawData(pTest, SizeArray);
    delete[] pTest;

关注点

  • 问:嘿,你为什么把它做成模板类?如果将模板参数作为构造函数的一部分,可以以更灵活的方式完成。

    答:嗯……你说的有道理。不过,我还是把它写成了模板。也许我应该改变它,但就目前而言,这似乎满足了我所有的需求。

  • 问:CCD​​oc 注释是怎么回事?

    答:自从我开始尝试 CCDoc 以来,我就爱上了它。我经常编写以后会用到的代码,但当我需要使用它时,我想要一份可以参考的文档,而无需去翻阅代码。CCDoc 提供了我发现有用的那种文档……只要我充分注释。

  • 问:为什么要两个类?CFlexBitSet 可以同时完成两者的任务。

    答:确实。但我编写 CABMBitSet 是为了立即满足我存储大量 BOOL 标志的需求。但在写完那个之后,我想看看把它改造成处理可能需要 2、3 或更多位(最多 31 位)的元素需要多少工作。

  • 问:在您的示例中,您使用了硬编码的索引号来访问某些元素。这样做明智吗?

    答:当然。在实际应用中,我会用“#define”的值或 enum 来代替。但是,在示例中,我想保持简单。

  • 问:为什么我要使用您的代码?

    答:您不必……除非它满足您的需求,并且您不想重复编写所有内容。知道是一半的战斗,……善待他人……等等。

  • 问:我喜欢您使用内部类来实现“[]”运算符的设置和获取功能。

    答:谢谢,但这主意的功劳我不能全收。这个想法是我从一位朋友 JAS 那里得到的,他也曾在网上某处发现了这个想法。我只是想确保这个想法被正式地公布出来……或者说,在这里。我能称这段代码为我的吗?不能。我也不声称完全拥有这个想法。但是,我不能阻止你,也不会尝试。呵呵,但是,你为什么要这样做呢?

  • 问:嘿,想去喝杯啤酒吗?

    答:好啊,我们走吧!

  • 问:为什么对话框使用 Courier New 字体?

    答:因为字符串表示 GetStrRepresentation(TRUE,FALSE); 使用两行,并且没有等宽字体,这看起来可能很奇怪。如果您想在测试中绕过这一点,那么将其发送到 MessageBox( ... ),然后当框出现时,按 <Ctrl>+C,打开记事本,然后粘贴在那里。我认为记事本默认使用等宽字体。

历史

(2005-03-27) 我的初始发布。

© . All rights reserved.