返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言中怎么动态扩容String
  • 224
分享到

C语言中怎么动态扩容String

2023-06-16 02:06:05 224人浏览 安东尼
摘要

这篇文章给大家介绍C语言中怎么动态扩容String,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。首先定义一个string的句柄,相当于c++中的实例struct c_string; typedef&

这篇文章给大家介绍C语言中怎么动态扩容String,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

首先定义一个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 < cs->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 += len;     cs->str[cs->len] = '\0'; }

在尾部追加字符:

void c_string_append_char(c_string_t *cs, char c) {     if (cs == NULL) return;     c_string_ensure_space(cs, 1);     cs->str[cs->len] = c;     cs->len++;     cs->str[cs->len] = '\0'; }

在尾部追加整数:

void c_string_append_int(c_string_t *cs, int val) {     char str[12];      if (cs == NULL) return;      snprintf(str, sizeof(str), "%d", val); // 整数转为字符串     c_string_append_str(cs, str, 0); }

在头部插入字符串:

void c_string_front_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 + len, cs->str, cs->len);     memmove(cs->str, str, len);     cs->len += len;     cs->str[cs->len] = '\0'; }

在头部插入字符:

void c_string_front_char(c_string_t *cs, char c) {     if (cs == NULL) return;     c_string_ensure_space(cs, 1);     memmove(cs->str + 1, cs->str, cs->len);     cs->str[0] = c;     cs->len++;     cs->str[cs->len] = '\0'; }

在头部插入整数:

void c_string_front_int(c_string_t *cs, int val) {     char str[12];      if (cs == NULL) return;      snprintf(str, sizeof(str), "%d", val);     c_string_front_str(cs, str, 0); }

清空字符串:

void c_string_clear(c_string_t *cs) {     if (cs == NULL) return;     c_string_truncate(cs, 0); }

裁剪字符串:

void c_string_truncate(c_string_t *cs, size_t len) {     if (cs == NULL || len >= cs->len) return;      cs->len = len;     cs->str[cs->len] = '\0'; }

删除头部的N个字符:

void c_string_drop_begin(c_string_t *cs, size_t len) {     if (cs == NULL || len == 0) return;      if (len >= cs->len) {         c_string_clear(cs);         return;     }      cs->len -= len;     memmove(cs->str, cs->str + len, cs->len + 1); }

删除尾部的N个字符:

void c_string_drop_end(c_string_t *cs, size_t len) {     if (cs == NULL || len == 0) return;      if (len >= cs->len) {         c_string_clear(cs);         return;     }     cs->len -= len;     cs->str[cs->len] = '\0'; }

获取字符串的长度:

size_t c_string_len(const c_string_t *cs) {     if (cs == NULL) return 0;     return cs->len; }

返回字符串指针,使用的是内部的内存:

const char *c_string_peek(const c_string_t *cs) {     if (cs == NULL) return NULL;     return cs->str; }

重新分配一块内存存储字符串返回:

char *c_string_dump(const c_string_t *cs, size_t *len) {     char *out;      if (cs == NULL) return NULL;      if (len != NULL) *len = cs->len;     out = malloc(cs->len + 1);     memcpy(out, cs->str, cs->len + 1);     return out; }

测试代码如下:

int main() {     c_string_t *cs = c_string_create();     c_string_append_str(cs, "123", 0);     c_string_append_char(cs, '4');     c_string_append_int(cs, 5);     printf("%s \n", c_string_peek(cs));     c_string_front_str(cs, "789", 0);     printf("%s \n", c_string_peek(cs));     c_string_drop_begin(cs, 2);     printf("%s \n", c_string_peek(cs));     c_string_drop_end(cs, 2);     printf("%s \n", c_string_peek(cs));     c_string_destroy(cs);     return 0; }

输出:

12345 78912345 912345 9123

完整代码如下:头文件:

#include <stddef.h>  struct c_string; typedef struct c_string c_string_t;  c_string_t *c_string_create(void);  void c_string_destroy(c_string_t *cs);  void c_string_append_str(c_string_t *cs, const char *str, size_t len);  void c_string_append_char(c_string_t *cs, char c);  void c_string_append_int(c_string_t *cs, int val);  void c_string_front_str(c_string_t *cs, const char *str, size_t len);  void c_string_front_char(c_string_t *cs, char c);  void c_string_front_int(c_string_t *cs, int val);  void c_string_clear(c_string_t *cs);  void c_string_truncate(c_string_t *cs, size_t len);  void c_string_drop_begin(c_string_t *cs, size_t len);  void c_string_drop_end(c_string_t *cs, size_t len);  size_t c_string_len(const c_string_t *cs);  const char *c_string_peek(const c_string_t *cs);  char *c_string_dump(const c_string_t *cs, size_t *len);

源文件:

#include <ctype.h> #include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <string.h>  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';     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 < cs->len + add_len + 1) {         cs->alloced <<= 1;         if (cs->alloced == 0) {             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 += len;     cs->str[cs->len] = '\0'; }  void c_string_append_char(c_string_t *cs, char c) {     if (cs == NULL) return;     c_string_ensure_space(cs, 1);     cs->str[cs->len] = c;     cs->len++;     cs->str[cs->len] = '\0'; }  void c_string_append_int(c_string_t *cs, int val) {     char str[12];      if (cs == NULL) return;      snprintf(str, sizeof(str), "%d", val);     c_string_append_str(cs, str, 0); }  void c_string_front_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 + len, cs->str, cs->len);     memmove(cs->str, str, len);     cs->len += len;     cs->str[cs->len] = '\0'; }  void c_string_front_char(c_string_t *cs, char c) {     if (cs == NULL) return;     c_string_ensure_space(cs, 1);     memmove(cs->str + 1, cs->str, cs->len);     cs->str[0] = c;     cs->len++;     cs->str[cs->len] = '\0'; }  void c_string_front_int(c_string_t *cs, int val) {     char str[12];      if (cs == NULL) return;      snprintf(str, sizeof(str), "%d", val);     c_string_front_str(cs, str, 0); }  void c_string_clear(c_string_t *cs) {     if (cs == NULL) return;     c_string_truncate(cs, 0); }  void c_string_truncate(c_string_t *cs, size_t len) {     if (cs == NULL || len >= cs->len) return;      cs->len = len;     cs->str[cs->len] = '\0'; }  void c_string_drop_begin(c_string_t *cs, size_t len) {     if (cs == NULL || len == 0) return;      if (len >= cs->len) {         c_string_clear(cs);         return;     }      cs->len -= len;          memmove(cs->str, cs->str + len, cs->len + 1); }  void c_string_drop_end(c_string_t *cs, size_t len) {     if (cs == NULL || len == 0) return;      if (len >= cs->len) {         c_string_clear(cs);         return;     }     cs->len -= len;     cs->str[cs->len] = '\0'; }  size_t c_string_len(const c_string_t *cs) {     if (cs == NULL) return 0;     return cs->len; }  const char *c_string_peek(const c_string_t *cs) {     if (cs == NULL) return NULL;     return cs->str; }  char *c_string_dump(const c_string_t *cs, size_t *len) {     char *out;      if (cs == NULL) return NULL;      if (len != NULL) *len = cs->len;     out = malloc(cs->len + 1);     memcpy(out, cs->str, cs->len + 1);     return out; }

关于C语言中怎么动态扩容String就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: C语言中怎么动态扩容String

本文链接: https://lsjlt.com/news/282093.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C语言中怎么动态扩容String
    这篇文章给大家介绍C语言中怎么动态扩容String,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。首先定义一个string的句柄,相当于C++中的实例struct c_string; typedef&...
    99+
    2023-06-16
  • C语言怎么实现动态扩容的string
    这篇文章主要介绍“C语言怎么实现动态扩容的string”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C语言怎么实现动态扩容的string”文章能帮助大家解决问题。一个好的string应该有以下功能?...
    99+
    2023-07-05
  • C语言实现动态扩容的string
    众所周知,C++ 中的string使用比较方便。关于C++ 中的string源码实现,可以参考这篇文章:源码分析C++的string的实现 最近工作中使用C语言,但又苦于没有高效的字...
    99+
    2023-05-14
    C语言实现动态扩容string C语言动态扩容string C语言扩容string
  • c语言中string怎么用
    c语言中,字符串以字符数组表示。定义字符串通过语法char str[] = "this is a string";。字符串操作包括:1. 访问元素(下标访问);2. ...
    99+
    2024-05-09
    c语言
  • string在c语言中怎么用
    字符串(string)在 c 语言中表示为以空字符结尾的字符数组。创建 string 可通过字面量或使用 malloc() 函数;可通过 [] 运算符访问字符,但 string 不可变,...
    99+
    2024-04-29
    c语言
  • 什么是C语言动态库
    这篇文章主要讲解了“什么是C语言动态库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“什么是C语言动态库”吧!什么 这里竟然躺着一个高性能 base64 库我...
    99+
    2024-04-02
  • 在Go语言中如何解决并发任务的动态扩容问题?
    在Go语言中如何解决并发任务的动态扩容问题?当需要处理大量并发任务时,我们可能需要动态调整并发goroutine的数量以实现任务的高效处理。在Go语言中,可以使用goroutine和channel来实现并发编程,通过调整goroutine的...
    99+
    2023-10-22
    Go语言 动态扩容 并发任务
  • c语言怎么动态创建结构体
    在C语言中,可以使用动态内存分配函数`malloc()`来动态创建结构体。首先,需要定义一个结构体类型,如下所示:```ctyped...
    99+
    2023-10-10
    c语言
  • Go语言切片是怎么扩容的
    本篇内容主要讲解“Go语言切片是怎么扩容的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go语言切片是怎么扩容的”吧!在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。切片是一...
    99+
    2023-07-06
  • 在Java项目中怎么对Arraylist进行动态扩容
    本篇文章为大家展示了在Java项目中怎么对Arraylist进行动态扩容,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。ArrayList 概述ArrayList是基于数组实现的,是一个动态数组,其容...
    99+
    2023-05-31
    java arraylist ava
  • C语言动态内存分配怎么使用
    这篇文章主要介绍了C语言动态内存分配怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言动态内存分配怎么使用文章都会有所收获,下面我们一起来看看吧。一、动态内存分配的意义C语言中的一切操作都是基于内存的...
    99+
    2023-06-30
  • c语言怎么建立多个动态链表
    要建立多个动态链表,可以使用结构体和指针来实现。首先,定义一个结构体来表示链表的节点,包含一个数据域和一个指向下一个节点的指针域,如...
    99+
    2023-08-25
    c语言
  • c语言二维动态数组怎么定义
    在C语言中,定义一个二维动态数组可以使用指针的指针来实现。下面是一个示例代码: #include #include int m...
    99+
    2023-10-27
    c语言
  • c语言动态库怎么创建和使用
    要创建一个动态库(也称为共享库),通常需要遵循以下步骤: 编写库的源代码文件,通常是以.c为扩展名的文件,包含库中所需的函数和数...
    99+
    2024-03-02
    c语言
  • c语言怎么创建二维动态数组
    c 语言中创建二维动态数组需要以下步骤:分配行指针数组为每一行分配内存通过指针解引用访问和操作数组元素 C 语言创建二维动态数组 二维动态数组是指在运行时动态分配内存的二维数组。创建二...
    99+
    2024-05-23
    c语言
  • C语言动态数组详解
    目录内存分配函数malloc calloc realloc free内存操作函数 memset memcpy memmove二维动态数组的建立和释放总结内存分配函数malloc ca...
    99+
    2024-04-02
  • 详细谈谈C语言中动态内存
    目录前言1.关于动态内存的函数1.1malloc和free函数1.2calloc函数1.3realloc函数2.常见的动态内存错误2.1对NULL指针解引用2.2对动态内存开辟的空间...
    99+
    2024-04-02
  • C语言中如何使用动态数组
    这篇文章主要介绍“C语言中如何使用动态数组”,在日常操作中,相信很多人在C语言中如何使用动态数组问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言中如何使用动态数组”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-16
  • C语言怎么模拟实现动态通讯录
    本篇内容主要讲解“C语言怎么模拟实现动态通讯录”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言怎么模拟实现动态通讯录”吧!目录模拟实现通讯录总体架构一览图文件执行任务分模块实现 测...
    99+
    2023-06-20
  • c语言动态数组怎么建立和使用
    在C语言中,要使用动态数组,需要使用指针和动态内存分配的函数来实现。下面是建立和使用动态数组的步骤:1. 声明一个指针变量来存储动态...
    99+
    2023-10-10
    c语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作