#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
в обоих этих случаях).
-
Добавьте в буфер на один элемент больше, чем вам на самом деле нужно, и никогда не допускайте
head
перехода кtail
при добавлении (вместо этого выдает ошибку «буфер заполнен»). Таким образом,head == tail
всегда означает пустой. -
Поддерживайте переменную «свободные слоты», а также 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