又好久没更新了,最近程序喵工作实在是太忙,业余时间也在学习新知识酝酿大招,便于后期更新好文,最近先水几篇吧,大家有想了解的知识点可以在文末读者讨论中留言哈!
众所周知,C++ 中的string使用比较方便,关于C++ 中的string源码实现可以看我的这篇文章:源码分析C++的string的实现
最近工作中使用C语言,但又苦于没有高效的字符串实现,字符串的拼接和裁剪都比较麻烦,而且每个字符串都需要申请内存,内存的申请和释放也很容易出bug,怎么高效的实现一个不需要处理内存问题并且可以动态扩容进行拼接和裁剪的string呢?
一个好的string应该有以下功能?创建字符串
删除字符串
尾部追加字符串
头部插入字符串
从尾部删除N个字符
从头部删除N个字符
裁剪字符串
获取字符串长度
获取完整字符串
下面来看看各个功能的实现:
首先定义一个string的句柄,相当于C++中的实例struct c_string;
typedef struct c_string c_string_t;
在内部string的实现如下:// string的初始内存大小
static const size_t c_string_min_size = 32;
struct c_string {
char *str; // 字符串指针
size_t alloced; // 已分配的内存大小
size_t len; // 字符串的实际长度
};
创建字符串:c_string_t *c_string_create(void) {
c_string_t *cs;
cs = calloc(1, sizeof(*cs));
cs->str = malloc(c_string_min_size);
*cs->str = '\0';
// 初始分配内存大小是32,之后每次以2倍大小扩容
cs->alloced = c_string_min_size;
cs->len = 0;
return cs;
}
销毁字符串:void c_string_destroy(c_string_t *cs) {
if (cs == NULL) return;
free(cs->str);
free(cs);
}
内部如何扩容呢:static void c_string_ensure_space(c_string_t *cs, size_t add_len) {
if (cs == NULL || add_len == 0) return;
if (cs->alloced >= cs->len + add_len + 1) return;
while (cs->alloced len + add_len + 1) {
cs->alloced <<= 1; // 每次以2倍大小扩容
if (cs->alloced == 0) {
// 左移到最后可能会变为0,由于alloced是无符号型,减一则会变成UINT_MAX
cs->alloced--;
}
}
cs->str = realloc(cs->str, cs->alloced);
}
在尾部追加字符串:void c_string_append_str(c_string_t *cs, const char *str, size_t len) {
if (cs == NULL || str == NULL || *str == '\0') return;
if (len == 0) len = strlen(str);
c_string_ensure_space(cs, len); // 确保内部有足够的空间存储字符串
memmove(cs->str + cs->len, str, len);
cs->len +&