#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct circlebuffer
{
int size;//用於判斷環形buffer是否是滿的
int wroffset;
int rdoffser;
char * buf;
int buflen;
}circleBuffer;
circleBuffer * cb_init(int bufLen)
{
if(bufLen==0)return NULL;
circleBuffer* cbBuffer=malloc(sizeof(circleBuffer));
memset(cbBuffer,0,sizeof(circleBuffer));
cbBuffer->buflen=bufLen;
cbBuffer->buf=(char *)malloc(bufLen);
memset(cbBuffer->buf,0,bufLen);
return cbBuffer;
}
//返回讀的數據的數量
int cb_read(circleBuffer * cb_buffer,char * outbuf,int readLen)
{
int canReadLen=0;
if(outbuf==NULL) return 0;
if(cb_buffer->size==0) return 0;//沒有數據可以讀
canReadLen=cb_buffer->wroffset-cb_buffer->rdoffser;
if(canReadLen<0) canReadLen+=cb_buffer->buflen;
if(canReadLen<readLen)
{
readLen=canReadLen;//readLen是能讀到的數量
}
if(readLen<cb_buffer->buflen-cb_buffer->rdoffser)
{
//說明不用不用折回來讀
memcpy(outbuf,&cb_buffer->buf[cb_buffer->rdoffser],readLen);
}else
{
//說明存到最大的地方沒存完,需要繼續折回來讀,第一次讀先讀到數組的結尾
memcpy(outbuf,&cb_buffer->buf[cb_buffer->rdoffser],cb_buffer->buflen-cb_buffer->rdoffser);
memcpy(&outbuf[cb_buffer->buflen-cb_buffer->rdoffser],cb_buffer->buf,readLen-(cb_buffer->buflen-cb_buffer->rdoffser));
}
//更新下實際的數量大小
cb_buffer->size-=readLen;
//更新讀指針
cb_buffer->rdoffser=(readLen+cb_buffer->rdoffser)%cb_buffer->buflen;
return readLen;//返回讀到的數據量
}
//返回是否寫入成功,如果空間不夠就不寫入,失敗返回0
int cb_write(circleBuffer * cb_buffer,char * inbuf,int wrireLen)
{
int canWriteLen=0;
//老樣子,做參數檢查
if(cb_buffer==NULL ||inbuf==NULL ||wrireLen==0 )
{
return 0;
}
//檢查環形buffer是否是滿的
if(cb_buffer->size==cb_buffer->buflen)
{
return 0;
}
//檢查剩餘的空間是否夠寫入
canWriteLen=cb_buffer->rdoffser-cb_buffer->wroffset;
if(canWriteLen<=0) canWriteLen+=cb_buffer->buflen;
if(wrireLen>canWriteLen) return -1;//沒有足夠的空間則不寫入
//開始寫
if(wrireLen<cb_buffer->buflen-cb_buffer->wroffset)
{
//不用折行,直接寫入
memcpy(&cb_buffer->buf[cb_buffer->wroffset],inbuf,wrireLen);
}else
{
//一行寫完以後,需要重新折過來,從開頭在寫入 wrireLen-(cb_buffer->buflen-cb_buffer->wroffset)
memcpy(&cb_buffer->buf[cb_buffer->wroffset],inbuf,cb_buffer->buflen-cb_buffer->wroffset);
memcpy(cb_buffer->buf,&inbuf[cb_buffer->buflen-cb_buffer->wroffset],wrireLen-(cb_buffer->buflen-cb_buffer->wroffset));
}
//更新寫指針
cb_buffer->wroffset=(wrireLen+cb_buffer->wroffset)%cb_buffer->buflen;
//更新size
cb_buffer->size+=wrireLen;
return wrireLen;
}
int main()
{
char writeBuf[15]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
char readBuf[15];
circleBuffer * cb_buffer=NULL;
cb_buffer=cb_init(10);
int a=cb_write(cb_buffer,writeBuf,5);
printf("write length is %d\n",a);
printf("size is %d,buflen is %d,content is %s,writeOffset is %d\n",cb_buffer->size,cb_buffer->buflen,cb_buffer->buf,cb_buffer->wroffset);
a=cb_read(cb_buffer,readBuf,10);
printf("read length is %d\n",a);
printf("size is %d,buflen is %d,content is %s,readOffset is %d\n",cb_buffer->size,cb_buffer->buflen,cb_buffer->buf,cb_buffer->rdoffser);
a=cb_read(cb_buffer,readBuf,10);
printf("read length is %d\n",a);
a=cb_write(cb_buffer,writeBuf,9);
printf("write length is %d\n",a);
printf("size is %d,buflen is %d,content is %s,writeOffset is %d\n",cb_buffer->size,cb_buffer->buflen,cb_buffer->buf,cb_buffer->wroffset);
return 0;
}
實驗效果:
整體思路就是利用size來保存環形buffer中有多少個元素,然後利用
canReadLen=cb_buffer->wroffset-cb_buffer->rdoffser;
if(canReadLen<0) canReadLen+=cb_buffer->buflen;來記錄能讀的長度。如果是寫的話就是cb_buffer->rdoffser-cb_buffer->wroffset,思路是一樣的。
cb_buffer->rdoffser=(readLen+cb_buffer->rdoffser)%cb_buffer->buflen;
利用讀寫的長度和之前讀寫的指針來取餘buffer中數組總的長度來更新,讀寫指針的指向。
程序中有註釋。
此程序沒有釋放動態申請的內存,所以執行一次就會有一次的內存泄漏,所以需要使用者自己寫一個釋放分配內存的函數,這個比較簡單,我就不貼在這裏了。