    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Sets a-la Pascal</title>
        <link>https://members.accu.org/index.php/articles/719</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + CVu Journal Vol 8, #1 - Feb 1996</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c137/">081</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-137/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+137/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Sets a-la Pascal</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 February 1996 13:15:26 +00:00 or Sat, 03 February 1996 13:15:26 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id="d0e18"></a></h2>
</div>
<div class="sidebar">
<p>John is not a native English speaker. He is currently helping
Cuban programmers learn C++. I think that he may have some pleasant
surprises in store for him when the C++ Standard Library appears.
In the meantime this article shows how easy it is to add a feature
to your working tools in C++. In the interests of compactness I
have edited some of his code. The original is on this issues disk.
Francis</p>
</div>
<p>Many programmers who have been satisfied with Pascal for years
but for some reason want to switch to C++, will miss the Set
facility from Pascal. For a Pascal programmer it may seem strange
that the <tt class="literal">enum</tt> type exists, but not the
Set.</p>
<p>Fortunately C++ is a language which permits easy construction of
new types. The following is my own implementation as I prefer it.
In Pascal there exist operations on sets, such as +, - and *. I've
always found it confusing - I prefer something easier to
remember.</p>
<p>A Set is a string of bits that may be set or removed according
to some state of the program or its data. Sets in Pascal are of
fixed size. In C++ the size may be determined at run-time.</p>
<p>In <tt class="literal">class Set</tt> the bits are stored in a
whole number of bytes, each byte containing 8 bits. Bit
manipulations are performed by the binary operators available in
C++. Bits are numbered 76543210.</p>
<p>Bitwise operations</p>
<p>If for example bit 4 (00010000) has to be added to the byte b
the following operation is performed: <tt class="literal">b = b |
(1 &lt;&lt; 4)</tt>, or shorter:</p>
<pre class="programlisting">
b |= (1 &lt;&lt; 4)
</pre>
<p>If the 4th bit is already set, the Set remains unchanged.</p>
<p>To remove a bit, the operation is a little more tricky. For
example to remove bit 4 the following operation, we cannot just OR
with a zero bit as this would remove other bits in the byte. We
have to AND with 11101111 in order to remove bit 4 and preserve all
other bits. The expression <tt class="literal">b &amp;= ~(1
&lt;&lt; 4)</tt> does it.</p>
<p>When a set contains more than a byte, we must find the byte
number and, within the byte, the bitnumber in order to handle a
single bit. To find the byte to operate on is easy. It is
<tt class="literal">BitNum div 8</tt>. The bit is <tt class=
"literal">BitNum mod 8.</tt></p>
<p>All in all, these operations are (surprisingly?) easily managed
by the bitwise operators in C++.</p>
<p>Almost like Pascal</p>
<p>In <tt class="literal">class Set</tt> the operator &lt;&lt; is
for adding a bit and &gt;&gt; for removing a bit. This is
convenient as I can write:</p>
<pre class="programlisting">
enum Color { Green, Blue, Yellow, Red } ;
Set Colors(10); // define a set with 10 bits
  s &lt;&lt; Red &lt;&lt; Green &lt;&lt; Blue;
  if (Colors[Blue]) print(&quot;Blue was in the Set s&quot;);
</pre>
<p>It is not quite like Pascal, but the same functionality is
there.</p>
<p>I've also made a function that adds one set to another set,
eventually of different size. As far as I remember Pascal, my
function works as in Pascal. As an example like the above may be
found in most Pascal books, I've also found it natural to include
an exercise for the reader. See the SET.CPP file included in this
article. Don't worry - it is not too difficult.</p>
<pre class="programlisting">
// SET.H  -- Set operations a-la Pascal
typedef unsigned int Word;
typedef unsigned char Byte;
const Word ByteSize = 8;
class Set { // Set operations a-la Pascal
  Byte *BitStr;
  Word  BitStrSize;
  Word  BitsInUse;
public:
  Set(Word MaxBits);
  Set(const Set &amp; TheSet);
  virtual ~Set();
  int SetSize(void);
  void ClearSet(void);
  int operator[](Word BitNum);          // test if a bit is present
  Set &amp; operator =(const Set &amp;TheSet);  // assignment of sets
  Set &amp; operator &lt;&lt;(Word BitNum);       // add a bit
  Set &amp; operator &gt;&gt;(Word BitNum);       // remove a bit
  int   operator ==(Set &amp;TheSet);       // compare sets
  int   operator !=(Set &amp;TheSet);       // compare sets
  void AddBitSet(Set &amp;TheSet);
  void RemoveBitSet(Set &amp;TheSet);
}; // class Set
</pre>
<pre class="programlisting">
In SET.CPP
//         SET.CPP  -- Set operations a-la Pascal
//        Written by:  John Plate &lt;plate@infotek.dk&gt;
// Date:        August 1995
// Compiler:    Borland Turbo C++
// Copyright:   The code is in the public domain
#include &quot;set.h&quot;
#include &lt;values.h&gt;
#include &lt;mem.h&gt;
Set::Set(Word MaxBits) { // MaxBits is number of bits in the Set
  BitsInUse = MaxBits;
  if (MaxBits &gt; MAXINT || MaxBits == 0) { // i.e. impossible values  
    BitStr = 0;
    BitStrSize = 0;
  }
  else {
    BitStrSize = (BitsInUse - 1) / ByteSize + 1;
    BitStr = new Byte(BitStrSize);
    ClearSet();
  }
} // constructor
Set::Set(const Set &amp; TheSet){ // Copy constructor
  BitStr = new Byte[BitStrSize = TheSet.BitStrSize];
  BitsInUse = TheSet.BitsInUse;
  if (BitStr) memcpy(BitStr, TheSet.BitStr, BitStrSize);
} // Copy constructor
Set::~Set(){ // De-allocate the BitStr array
  if (BitStr) delete BitStr;
} // destructor
void Set::ClearSet(void){ // Zero fill the whole Set one byte at a time
  for (int i = 0; i &lt; BitStrSize; i++) BitStr[i] = 0;
} // ClearSet
int Set::SetSize(void){ // Return the bits used, i.e. the size of the Set
  return(BitsInUse);
} // SetSize
int Set::operator[](Word BitNum){ // Return the value of bit BitNum. 
                                  // Notice: Zero is returned if BitNum is not within the Set.
  if (BitNum &lt;= BitsInUse) {
    return(BitStr[BitNum / ByteSize] &amp; (1 &lt;&lt; (BitNum % ByteSize)));
  }
  else return(0);
} // operator []
Set &amp; Set::operator =(const Set &amp; TheSet){ //copy assignment 
  if (this != &amp;TheSet) {
    delete(BitStr);
    BitStr = new Byte[BitStrSize = TheSet.BitStrSize];
    BitsInUse = TheSet.BitsInUse;
    if (BitStr) memcpy(BitStr, TheSet.BitStr, BitStrSize);
  }
  return(*this);
} // operator =
int Set::operator ==(Set &amp; TheSet){ // Compare two sets
  int Equal = BitStrSize == TheSet.BitStrSize &amp;&amp;
    BitsInUse == TheSet.BitsInUse &amp;&amp;
    memcmp(BitStr, TheSet.BitStr, BitStrSize) == 0;
  return(Equal);
} // operator ==
int Set::operator !=(Set &amp; TheSet){ // Compare two sets
  return(! (*this == TheSet));
} // operator !=
Set &amp; Set::operator &lt;&lt;(Word BitNum){ // Set the bit, return 'this Set'
  if (BitNum &lt; BitsInUse) {
    BitStr[BitNum / ByteSize] |= (1 &lt;&lt; (BitNum % ByteSize));
  }
  return(*this);
} // operator &lt;&lt;
Set &amp; Set::operator &gt;&gt;(Word BitNum){ // Remove the bit, return 'this Set'
  if (BitNum &lt; BitsInUse) {
    BitStr[BitNum / ByteSize] &amp;= ~(1 &lt;&lt; (BitNum % ByteSize));
  }
  return(*this);
} // operator &gt;&gt;
void Set::AddBitSet(Set &amp;TheSet){ 
    // Add bits from TheSet, i.e. perform an OR operation on both sets.
    // Notice that the sets may be of different size.
  int BitsUsed = min(TheSet.BitsInUse, BitsInUse);
  int Bytes = BitsUsed / ByteSize;     // no of whole bytes
  for (int i = Bytes; i &gt;= 0; i--) BitStr[i] |= TheSet.BitStr[i];
  int Bits = BitsInUse % ByteSize;     // the rest
  if (Bits &gt; 0) { // mask out relevant bits before the OR operation
    BitStr[Bytes+1] |= (~0 &lt;&lt; (ByteSize - Bits)) &amp; TheSet.BitStr[Bytes+1];
  }
} // AddBitSet
void Set::RemoveBitSet(Set &amp;TheSet){
  // This left as an excercise for the reader :-)
  // Hint: See the functions above.
} // RemoveBitSet
</pre>
<p><span class="emphasis"><em>Finally, something to think about.
What operators should be provided (if any) and how would they best
be provided. Perhaps the design experts might like to critique the
design. Any thoughts on the variety of ways that &lt;&lt; and
&gt;&gt; are used in the context of this design? Material such as
this is presented to provoke your thoughts and develop ideas and
understanding, not as recipes for definitive answers.
Francis.</em></span></p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
