Для реализации буфера фиксированной длины с верхним и конечным указателями

#c #buffer

#c #буфер

Вопрос:

Я реализую буфер фиксированной длины для чтения или записи строки с использованием указателя tail или head соответственно. У меня есть следующий код:

 bool putBuffer(char *sMsz)
{
 int iStrLen;
 iStrLen =  strlen(sMsz);
 if(!iStrLen || iStrLen>MAX_LEN)
 return 0;
  while(iStrLen-->=0)
 {
  //if head crosses tail
   if(iBufHead==iBufTail amp;amp; iBufHead!=0 amp;amp; dFlag)
   {  
     while(cDebugBuf[iBufTail] != '')
     {
       iBufTail=iBufTail 1;
       if (iBufTail>=CBUFF_SIZE)
       iBufTail = 0;
     }
    iBufTail  ;
  }
     if(iBufHead>=CBUFF_SIZE)
    {
     dFlag=1; // Used to know when buffer starts over writing prev data and meets tail on                    way
    iBufHead = 0; 
    }
    cDebugBuf[iBufHead  ] = *(sMsz  );
 }
 return 1;
}

 bool  getBuffer(char *readData)
 {
    int i=0; 
  do
  {
     if(iBufTail==iBufHead)
      return 0;
     if(iBufTail>=CBUFF_SIZE)
     iBufTail = 0;
     readData[i  ] = cDebugBuf[iBufTail  ];
   }while(cDebugBuf[iBufTail]!='');
   iBufTail  ;
   return 1;
}
  

Этот код работает до тех пор, пока не будет достигнут максимальный буфер, когда указатель head запускается снова, указатель tail размещен неправильно.

Есть предложения по улучшению кода, помимо поиска ошибок?

Ответ №1:

При использовании циклического буфера существует по крайней мере два способа отличить полное состояние от пустого ( head == tail в обоих этих случаях).

  1. Добавьте в буфер на один элемент больше, чем вам на самом деле нужно, и никогда не допускайте head перехода к tail при добавлении (вместо этого выдает ошибку «буфер заполнен»). Таким образом, head == tail всегда означает пустой.

  2. Поддерживайте переменную «свободные слоты», а также head и tail, инициализируя ее размером буфера, уменьшая его при добавлении и увеличивая при удалении. Таким образом, вы можете определить заполненность буфера по тому факту, что он равен нулю, или пустоту буфера, если для него установлен исходный размер.


Для варианта 1, что-то вроде:

 def buffInit(sz):
    global buffSz = sz
    global buffData = alloc(buffSz 1)         # allow for extra slot.
    global buffHead = 0
    global buffTail = 0

def buffAdd(item):
    if (buffHead   1) % buffSz == buffTail:   # never fill extra slot.
        return BUFFER_FULL
    buffData[buffHead] = item
    buffHead = (buffHead   1) % buffSz
    return OK

def buffGet():
    if buffHead == buffTail:
        return BUFFER_EMPTY
    item = buffData[buffHead]
    buffHead = (buffHead   1) % buffSz
    return item
  

Для варианта 2, что-то вроде:

 def buffInit(sz):
    global buffSz = sz
    global buffFree = buffSz                  # extra information.
    global buffData = alloc(buffSz)
    global buffHead = 0
    global buffTail = 0

def buffAdd(item):
    if buffFree == 0:                         # zero free slots means full.
        return BUFFER_FULL
    buffData[buffHead] = item
    buffHead = (buffHead   1) % buffSz
    buffFree = buffFree - 1                   # keep in sync.
    return OK

def buffGet():
    if buffFree == buffSz:
        return BUFFER_EMPTY
    item = buffData[buffHead]
    buffHead = (buffHead   1) % buffSz
    buffFree = buffFree   1                   # keep in sync.
    return item