环形缓冲区实现(C语言)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


要求

完成环形缓冲区函数库封装,生成成静态库和动态库,编写测试程序验证库文件,编写makefile实现编译,要求实现函数:
a、缓冲区初始化
b、往缓冲区写数据;
c、从缓冲区读数据;
d、计算缓冲区数据长度;
e、销毁缓冲区;

需要考虑到多个用户同时读写的情况,用到锁机制(互斥量)。

一、环形缓冲区

关于什么是环形缓冲区,这里就不介绍了,网上大量文章都会介绍,读几篇基本就了解了。
参考:
C语言实现环形缓冲区
环形缓冲区ring_buffer的c语言实现
【数据结构及算法】环形缓冲区(ring buffer)实现原理及代码实现(C语言)

不罗嗦,直接上代码。

二、环形缓冲区实现(C语言)

1. ringBuf.h

#ifndef _RINGBUF_H
#define _RINGBUF_H

#define read    0
#define write   1
#define quit    2
#define length  3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ringBuf
{
    
    
	char *buffer;	/*缓冲区的数据*/
	int  size;		/*缓冲区大小*/
	int  pRead;		/*读指针,名义上的指针,只是为了记录位置而已*/
	int  pWrite;	/*写指针,名义上的指针,只是为了记录位置而已*/
};
/*先不考虑互斥锁*/
/*先不考虑写覆盖和读重复问题,后续设计有效数据记录变量来解决*/

struct ringBuf *ringBufInit(struct ringBuf *ringBuffer,int size);
int ringBufRead(struct ringBuf *ringBuffer,char *readBuf,int readLength);
int ringBufWrite(struct ringBuf *ringBuffer,char *writeBuf,int writeLength);
int ringBufDataLen(struct ringBuf *ringBuffer);
void ringBufFree(struct ringBuf *ringBuffer);
int cmdHand(char *cmd);

#endif

2. ringBufInit.c

#include "ringBuf.h"
#include <stdlib.h>

/*环形缓冲区初始化函数*/
/*不使用全局变量,将环形缓冲区结构体返回*/
struct ringBuf *ringBufInit(struct ringBuf* ringBuffer,int size)
{
    
    
	ringBuffer = (struct ringBuf*)malloc(sizeof(struct ringBuf));
	if(NULL == ringBuffer)
	{
    
    
		printf("ringBuffer malloc error!\n");
		exit(-1);
	}
	memset(ringBuffer,0,sizeof(struct ringBuf));
	
	ringBuffer->buffer = (char*)malloc(size);
	memset(ringBuffer->buffer,0,size);

	ringBuffer->size   = size;
	ringBuffer->pRead  = 0;
	ringBuffer->pWrite = 0;

	return ringBuffer;
}

3. ringBufRead.c

#include "ringBuf.h"

/*从环形缓冲区读数据*/

int ringBufRead(struct ringBuf *ringBuffer,char *readBuf,int readLength)
{
    
    
	int pre  = 0;	//记录read指针到缓冲区尾端数据长度
	int last = 0;	//记录剩余数据长度,也就是缓冲区头部的部分数据

	if(NULL == ringBuffer)
	{
    
    
		printf("ringBuffer is NULL,ringBuffer init error!\n");
		exit(-1);
	}
	if(NULL == readBuf)
	{
    
    
		printf("readBuf is NULL,readBuf init error!\n");
		exit(-1);
	}

	/*readLength超出缓冲区大小*/
	/*可设置只读有效数据或直接报错*/
	/*后续设计有效数据记录变量,防止读重复,同时也解决了readLength超缓冲区的问题*/
	if(readLength > ringBuffer->size)
	{
    
    
		printf("readLength is too long!\n");
		exit(-1);
	}

	if(readLength+ringBuffer->pRead <= ringBuffer->size)
	{
    
    
		/*readLength + pRead < size,要读的数据没有到达尾部*/
		memcpy(readBuf,ringBuffer->buffer+ringBuffer->pRead,readLength);
	}else
	{
    
    
		/*readLength + pRead > size,一部分数据在尾端,一部分在头端*/
		int pre  = ringBuffer->size - ringBuffer->pRead;
		int last = readLength - pre;
		memcpy(readBuf,ringBuffer->buffer+ringBuffer->pRead,pre);
		memcpy(readBuf+pre,ringBuffer->buffer,last); 
	}

	/*移动pRead指针*/
	ringBuffer->pRead = (ringBuffer->pRead + readLength) % (ringBuffer->size);
	
	return readLength;	//后续要返回读有效数据长度
}

4. ringBufWrite.c

#include "ringBuf.h"

/*往环形缓冲区写数据*/
int ringBufWrite(struct ringBuf *ringBuffer,char *writeBuf,int writeLength)
{
    
    
    int pre  = 0;   //记录write指针到缓冲区尾端长度
    int last = 0;   //记录剩余所需空间,也就是要往缓冲区头部写的部分空间

    if(NULL == ringBuffer)
    {
    
    
        printf("ringBuffer is NULL,ringBuffer init error!\n");
        exit(-1);
    }
    if(NULL == writeBuf)
    {
    
    
        printf("writeBuf is NULL,writeBuf init error!\n");
        exit(-1);
    }

    /*writeLength超出缓冲区大小*/
    /*可设置只写有效空间或直接报错*/
	/*后续设计有效数据记录变量,防止写覆盖,同时也解决了writeLength超缓冲区的问题*/
    if(writeLength > ringBuffer->size)
    {
    
    
        printf("writeLength is too long!\n");
        exit(-1);
    }

    if(writeLength+ringBuffer->pWrite <= ringBuffer->size)
    {
    
    
        /*writeLength + pWrite < size	写空间足够,不用回到头部*/
        memcpy(ringBuffer->buffer+ringBuffer->pWrite,writeBuf,writeLength);
    }else
    {
    
    
        /*writeLength + pRead > size	一部分数据写在尾部,一部分数据写在头部*/
        int pre  = ringBuffer->size - ringBuffer->pWrite;
        int last = writeLength - pre;
        memcpy(ringBuffer->buffer+ringBuffer->pWrite,writeBuf,pre);
        memcpy(ringBuffer->buffer,writeBuf+pre,last);
    }

    /*移动pWrite指针*/
    ringBuffer->pWrite = (ringBuffer->pWrite + writeLength) % (ringBuffer->size);

    return writeLength;	//后续要返回写有效数据长度
}

5. ringBufDataLen.c

#include "ringBuf.h"

/*计算环形缓冲区数据长度*/
/*write指针可能在read指针前,也可能在read指针后*/

int ringBufDataLen(struct ringBuf *ringBuffer)
{
    
    
	int dataLen = 0;

	if(NULL == ringBuffer)
	{
    
    
		printf("ringBuffer is NULL!\n");
		exit(-1);
	}

	if(ringBuffer->pWrite >= ringBuffer->pRead)
	{
    
    
		return (ringBuffer->pWrite - ringBuffer->pRead);
	}else
	{
    
    
		return (ringBuffer->size - ringBuffer->pRead + ringBuffer->pWrite);
	}
}

6. ringBufFree.c

#include "ringBuf.h"

/*释放环形缓冲区*/
void ringBufFree(struct ringBuf *ringBuffer)
{
    
    
	if(NULL == ringBuffer)
	{
    
    
		printf("ringBuffer is NULL!\n");
		exit(-1);
	}
	if(ringBuffer->buffer != NULL)
	{
    
    
		free(ringBuffer->buffer);
		ringBuffer->buffer =NULL;
	}
	free(ringBuffer);
	ringBuffer = NULL;
}

7. cmdHand.c

#include "ringBuf.h"

int cmdHand(char *cmd)
{
    
    
	if(NULL == cmd)
	{
    
    
		printf("cmd is NULL!\n");
		exit(-1);
	}
	if(strcmp("read",cmd) == 0)
	{
    
    
		return 0;
	}
	if(strcmp("write",cmd) == 0)
	{
    
    
		return 1;
	}
	if(strcmp("quit",cmd) == 0)
	{
    
    
		return 2;
	}
	if(strcmp("length",cmd) == 0)
	{
    
    
		return 3;
	}
	return 4;
}

8. main.c

#include "ringBuf.h"

int main()
{
    
    

	/*暂时不考虑多用户同时操作的情况*/
	/*暂时不考虑写覆盖和读重复问题,后续设计一个变量
	 * 用来监视有效数据长度*/

	int bufLen = 16;	//缓冲区大小
	char *cmd = NULL;
	int cmdNum = 0;
	int strNum = 0;		//要读取的字符数
	int dataLen = 0;	//缓冲区有效数据长度
	char readBuf[24] = {
    
    0};		//读缓存
	char writeBuf[24] = {
    
    0};	//写缓存

	cmd = (char *)malloc(12);
	memset(cmd,0,12);

	struct ringBuf *ringBuffer = NULL;

	ringBuffer = (struct ringBuf*)malloc(sizeof(struct ringBuf));

	/*环形缓冲区初始化*/
	ringBuffer = ringBufInit(ringBuffer,bufLen);


	while(1)
	{
    
    
		/*输入指令,根据不同指令实现不同功能*/
		printf("请输入指令(不要超过12字符):");
		scanf("%s",cmd);
		//	printf("%s\n",cmd);
		//

		cmdNum = cmdHand(cmd);

		switch(cmdNum)
		{
    
    

			/*从缓冲区读数据*/
			case read:
				printf("请输入需要读取的字符数:");
				scanf("%d",&strNum);

				memset(readBuf,0,sizeof(readBuf));
				ringBufRead(ringBuffer,readBuf,strNum);
				printf("读取结果:%s\n",readBuf);
				break;

			case write:
				/*往缓冲区写数据*/
				memset(writeBuf,0,sizeof(writeBuf));
				printf("请输入要写入内容:");
				scanf("%s",writeBuf);
				ringBufWrite(ringBuffer,writeBuf,strlen(writeBuf));
				printf("%s已写入\n",writeBuf);
				break;

			case quit:
				/*销毁缓冲区*/
				ringBufFree(ringBuffer);
				printf("环形缓冲区已销毁!\n");
				exit(0);
				break;

			case length:
				/*计算缓冲区数据长度*/
				dataLen = ringBufDataLen(ringBuffer);
				printf("缓冲区的有效数据长度为:%d\n",dataLen);
				break;

			default:
				printf("错误命令!\n");
				break;
		}
	}

	return 0;
}

9. Makefile

#main: main.c libringBufInit.a libringBufWrite.a libringBufRead.a libringBufDataLen.a libringBufFree.a libcmdHand.a
#	gcc -o main main.c -L . -lringBufInit -lringBufWrite -lringBufRead -lringBufDataLen -lringBufFree -lcmdHand

#libringBufInit.a:
#	gcc -c ringBufInit.c -o ringBufInit.o
#	ar rcs libringBufInit.a ringBufInit.o

#libringBufWrite.a:
#	gcc -c ringBufWrite.c -o ringBufWrite.o
#	ar rcs libringBufWrite.a ringBufWrite.o

#libringBufRead.a:
#	gcc -c ringBufRead.c -o ringBufRead.o
#	ar rcs libringBufRead.a ringBufRead.o

#libringBufDataLen.a:
#	gcc -c ringBufDataLen.c -o ringBufDataLen.o
#	ar rcs libringBufDataLen.a ringBufDataLen.o

#libringBufFree.a:
#	gcc -c ringBufFree.c -o ringBufFree.o
#	ar rcs libringBufFree.a ringBufFree.o
#
#libcmdHand.a:
#	gcc -c cmdHand.c -o cmdHand.o
#	ar rcs libcmdHand.a cmdHand.o

#clean:
#	rm *.o
#	rm main
#	rm *.a

main: main.c libringBufInit.so libringBufWrite.so libringBufRead.so libringBufDataLen.so libringBufFree.so libcmdHand.so
	gcc -o main main.c -L . -lringBufInit -lringBufWrite -lringBufRead -lringBufDataLen -lringBufFree -lcmdHand

libringBufInit.so:
	gcc -fPIC -shared ringBufInit.c -o libringBufInit.so

libringBufWrite.so:
	gcc -fPIC -shared ringBufWrite.c -o libringBufWrite.so

libringBufRead.so:
	gcc -fPIC -shared ringBufRead.c -o libringBufRead.so

libringBufDataLen.so:
	gcc -fPIC -shared ringBufDataLen.c -o libringBufDataLen.so

libringBufFree.so:
	gcc -fPIC -shared ringBufFree.c -o libringBufFree.so

libcmdHand.so:
	gcc -fPIC -shared cmdHand.c -o libcmdHand.so

clean:
	rm main
	rm *.so
	

猜你喜欢

转载自blog.csdn.net/little_rookie__/article/details/121385854