设计一个C语言的动态扩容缓冲区strbuf

该代码实现了一个C语言的动态缓冲区结构`strbuf`,包括初始化、释放内存、交换、获取原始内存、比较、追加数据、插入数据、去除空白等操作。此外,还包括从文件读取内容到缓冲区以及按指定分隔符切割字符串的功能。
摘要由CSDN通过智能技术生成

设计一个C语言的动态扩容缓冲区

在这里插入图片描述

struct strbuf {
int len; //当前缓冲区(字符串)长度
int alloc; //当前缓冲区(字符串)容量
char *buf; //缓冲区(字符串)
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include "strbuf.h"
/*struct strbuf {
  int len;     //当前缓冲区(字符串)长度
  int alloc;   //当前缓冲区(字符串)容量
  char *buf;   //缓冲区(字符串)
};*/
//初始化sb结构体,容量为alloc
void strbuf_init(struct strbuf* sb, size_t alloc)
{
	sb->len = 0;
	sb->alloc = alloc;
	sb->buf = (char*)malloc(sizeof(char) * alloc);
}
//将字符串填充到sb中,长度为len,容量为alloc
void strbuf_attach(struct strbuf* sb, void* str, size_t len, size_t alloc)
{
	sb->len = len;
	sb->alloc = alloc;
	sb->buf = (char*)str;
}
//释放sb结构体的内存
void strbuf_release(struct strbuf* sb)
{
	free(sb->buf);
	sb->buf = NULL;
}
//交换两个strbuf
void strbuf_swap(struct strbuf* a, struct strbuf* b)
{
	int t1, t2;
	char* t3;
	t1 = a->len;
	a->len = b->len;
	b->len = t1;

	t2 = a->alloc;
	a->alloc = b->alloc;
	b->alloc = t2;

	t3 = a->buf;
	a->buf = b->buf;
	b->buf = t3;
}
//将sb中的原始内存取出,并将sz设置为其alloc大小
char* strbuf_detach(struct strbuf* sb, size_t* sz)
{
	*sz = sb->alloc;
	char* p;
	p = sb->buf;
	return p;
}
//比较两个strbuf的内存是否相同
int strbuf_cmp(const struct strbuf* first, const struct strbuf* second)
{
	if (first->len > second->len || first->len < second->len)
		return 1;
	else
		return 0;
}
//清空sb
void strbuf_reset(struct strbuf* sb)
{
	int i;
	for (i = 0; i < sb->len; i++)
	{
		*((sb->buf) + i) = '\0';
	}
	sb->len = 0;
}
//part 2B
//确保在len之后strbuf中至少有extra个空字节的空闲空间可用
void strbuf_grow(struct strbuf* sb, size_t extra)
{
	sb->buf = (char*)realloc(sb->buf, sb->len + extra);
	sb->alloc = sb->len + extra;
}
//向sb追加长度为len的数据data
void strbuf_add(struct strbuf* sb, const void* data, size_t len)
{
	if (sb->len + len > sb->alloc)
	{
		strbuf_grow(sb, len + 1);
	}
	for (int i = 0; i < len; i++)
	{
		*(sb->buf + (sb->len + i)) = *((char*)data + i);
	}
	sb->len += len;
	*(sb->buf + (sb->len)) = '\0';
}
//向sb追加一个字符c
void  strbuf_addch(struct strbuf* sb, int c)
{
	if (sb->len + 2 > sb->alloc)
	{
		strbuf_grow(sb, 2);
	}
	sb->len += 1;
	*(sb->buf + (sb->len - 1)) = c;
	*(sb->buf + (sb->len)) = '\0';
}
//向sb追加一个字符串s
void strbuf_addstr(struct strbuf* sb, const char* s)
{
	int a = strlen(s);
	if (s == NULL)
	{
		return;
	}
	if (sb->len + a >= sb->alloc)
	{
		strbuf_grow(sb, a + 1);
	}
	memcpy(sb->buf + sb->len, s, a);//memcpy(目标空间地址,传递数据地址,拷贝数据的字节数)拷贝数据到目标地址
	sb->len += a;
	sb->buf[sb->len] = '\0';
}
//向一个sb追加另一个strbuf的数据
void strbuf_addbuf(struct strbuf* sb, const struct strbuf* sb2)
{
	strbuf_add(sb, sb2->buf, sb2->len);
}
//设置sb的长度len
void strbuf_setlen(struct strbuf* sb, size_t len)
{
	sb->len = len;
	sb->buf[sb->len] = '\0';
}
//计算sb仍可以向后追加的字符串长度

size_t strbuf_avail(const struct strbuf* sb)
{
	return sb->alloc - sb->len - 1;
}
//向sb内存坐标为pos位置插入长度为len的数据data
void strbuf_insert(struct strbuf* sb, size_t pos, const void* data, size_t len)
{
	int new_len = len + sb->len;
	int new_alloc = sb->alloc;
	if (new_alloc < sizeof(char) * new_len)
	{
		strbuf_grow(sb, sizeof(char*) * len);
	}
	for (int i = sb->len; i >= pos; i--)
	{
		sb->buf[i + len] = sb->buf[i];
	}
	for (int k = pos, j = 0; j < len; k++, j++)
	{
		sb->buf[k] = *((char*)data + j);
	}
	sb->len = new_len;
}
//Part 2C
//去除sb缓冲区左端的所有空格,tab,'\t'
void strbuf_ltrim(struct strbuf* sb)
{
	for (int i = sb->len; i > 0; i--)
		if (sb->buf[0] == ' ' || sb->buf[0] == '\t')
		{
			memmove(sb->buf, sb->buf + 1, sb->len - 1);//memmove(目标地址,源地址,要拷贝的内容大小)移动内存块
			sb->len--;
		}

}
//去除sb缓存区右端的所有空格,tab,'\t'
void strbuf_rtrim(struct strbuf* sb)
{
	for (int i = sb->len; i > 0; i--)

		if (*(sb->buf + (sb->len - 1)) == ' ' || *(sb->buf + (sb->len - 1)) == '\t')
		{
			*(sb->buf + (sb->len - 1)) = '\0';
			sb->len--;
		}
}
//删除sb缓冲区从pos坐标长度为len的内容
void strbuf_remove(struct strbuf* sb, size_t pos, size_t len)
{
	memmove(sb->buf + pos, sb->buf + pos + len, sb->len - pos - len);
	sb->len -= len;
}
//PART 2D
//sb增长hint?hint:8192大小,然后将文件描述符为fd的所有文件内容追加到sb中
ssize_t strbuf_read(struct strbuf* sb, int fd, size_t hint)
{
	char c;
	FILE* pf = fdopen(fd, "r");
	int k = 0;
	sb->buf = (char*)realloc(sb->buf, sizeof(char) * (sb->alloc += (hint ? hint : 8192)));
	sb->alloc += (hint ? hint : 8192);
	while ((c = fgetc(pf)) != -1)
	{
		sb->buf[sb->len++] = c;
		k++;
	}
	if (k != 0)
		sb->buf[sb->len] = '\0';
	return 1;
}
//将文件句柄为fp的一行内容(抛弃换行符)读取到sb
int strbuf_getline(struct strbuf* sb, FILE* fp)
{
	char c;
	int k = 0;
	while ((c = fgetc(fp)) != EOF)
	{
		if (c == '\n' || feof(fp) != 0)
			break;
		strbuf_grow(sb, 2);
		sb->buf[sb->len] = c;
		sb->len++;
		k++;
	}
	if (k != 0)
		*(sb->buf + (sb->len)) = '\0';
	return 0;
}
//challenge
//实现判断一个strbuf是否以指定字符串开头的功能
bool strbuf_begin_judge(char* target_str, const char* str, int strnlen)
{
	if (strnlen == 0)
		return true;
	int len = strlen(str);
	int i = memcmp(target_str, str, len);
	if (i == 0)
		return true;
	else
		return false;

}
//获取字符串从坐标[begin,end)的所有内容
char* strbuf_get_mid_buf(char* target_buf, int begin, int end, int len)
{
	if (len <= 0)
		return NULL;
	int lang = end - begin;
	char* p = (char*)malloc(sizeof(char) * (lang + 1));
	memcpy(p, target_buf + begin, lang + 1);//memcpy(目标地址,源地址,数据长度)用于内存复制函数
	p[lang] = '\0';
	return p;
}
//实现字符串的切割
struct strbuf** strbuf_split_buf(const char* str, size_t len, int terminator, int max)
{
	if (str == NULL)
		return 0;
	char s[2] = { 0 };
	s[0] = (char)terminator;
	s[1] = '\0';
	int k = 0;
	struct strbuf** p = NULL;
	p = (struct strbuf**)realloc(p, sizeof(struct strbuf*) * (k + 1));
	char* temp = (char*)malloc(sizeof(char) * (len + 1));

	memcpy(temp, str, len + 1);
	for (int i = 0; i < len; i++)
	{
		if (temp[i] == '\0')
			temp[i] = '?';
	}
	char* arr = strtok(temp, s);//strtok(被分解的字符串,分隔符)字符分割函数
	while (arr != NULL && k < max)
	{
		int lang = strlen(arr);
		for (int i = 0; i < lang; i++)
		{
			if (arr[i] == '?')
				arr[i] = '\0';
		}
		struct strbuf* ps = (struct strbuf*)malloc(sizeof(struct strbuf));
		strbuf_init(ps, lang + 1);
		strbuf_add(ps, arr, lang);
		p = (struct strbuf**)realloc(p, sizeof(struct strbuf*) * (k + 2));
		p[k++] = ps;
		arr = strtok(NULL, s);
		p = (struct strbuf**)realloc(p, sizeof(struct strbuf*) * (k + 2));

	}
	free(temp);
	p[k] = NULL;
	return p;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值