成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C語言如何實現動態擴容的String

開發 后端
最近工作中使用C語言,但又苦于沒有高效的字符串實現,字符串的拼接和裁剪都比較麻煩,而且每個字符串都需要申請內存,內存的申請和釋放也很容易出bug,怎么高效的實現一個不需要處理內存問題并且可以動態擴容進行拼接和裁剪的string呢?

[[347888]]

本文轉載自微信公眾號「程序喵大人」,作者程序喵大人 。轉載本文請聯系程序喵大人公眾號。

最近工作中使用C語言,但又苦于沒有高效的字符串實現,字符串的拼接和裁剪都比較麻煩,而且每個字符串都需要申請內存,內存的申請和釋放也很容易出bug,怎么高效的實現一個不需要處理內存問題并且可以動態擴容進行拼接和裁剪的string呢?

  • 一個好的string應該有以下功能?
  • 創建字符串
  • 刪除字符串
  • 尾部追加字符串
  • 頭部插入字符串
  • 從尾部刪除N個字符
  • 從頭部刪除N個字符
  • 裁剪字符串
  • 獲取字符串長度
  • 獲取完整字符串

下面來看看各個功能的實現:

首先定義一個string的句柄,相當于C++中的實例

  1. struct c_string; 
  2. typedef struct c_string c_string_t; 

在內部string的實現如下:

  1. // string的初始內存大小 
  2. static const size_t c_string_min_size = 32; 
  3.  
  4. struct c_string { 
  5.     char *str; // 字符串指針 
  6.     size_t alloced; // 已分配的內存大小 
  7.     size_t len; // 字符串的實際長度 
  8. }; 

創建字符串:

  1. c_string_t *c_string_create(void) { 
  2.     c_string_t *cs; 
  3.  
  4.     cs = calloc(1, sizeof(*cs)); 
  5.     cs->str = malloc(c_string_min_size); 
  6.     *cs->str = '\0'
  7.     // 初始分配內存大小是32,之后每次以2倍大小擴容 
  8.     cs->alloced = c_string_min_size;  
  9.     cs->len = 0; 
  10.  
  11.     return cs; 

銷毀字符串:

  1. void c_string_destroy(c_string_t *cs) { 
  2.     if (cs == NULLreturn
  3.     free(cs->str); 
  4.     free(cs); 

內部如何擴容呢:

  1. static void c_string_ensure_space(c_string_t *cs, size_t add_len) { 
  2.     if (cs == NULL || add_len == 0) return
  3.  
  4.     if (cs->alloced >= cs->len + add_len + 1) return
  5.  
  6.     while (cs->alloced < cs->len + add_len + 1) { 
  7.         cs->alloced <<= 1; // 每次以2倍大小擴容 
  8.         if (cs->alloced == 0) { 
  9.             // 左移到最后可能會變為0,由于alloced是無符號型,減一則會變成UINT_MAX 
  10.             cs->alloced--; 
  11.         } 
  12.     } 
  13.     cs->str = realloc(cs->str, cs->alloced); 

在尾部追加字符串:

  1. void c_string_append_str(c_string_t *cs, const char *str, size_t len) { 
  2.     if (cs == NULL || str == NULL || *str == '\0'return
  3.  
  4.     if (len == 0) len = strlen(str); 
  5.  
  6.     c_string_ensure_space(cs, len); // 確保內部有足夠的空間存儲字符串 
  7.     memmove(cs->str + cs->len, str, len); 
  8.     cs->len += len; 
  9.     cs->str[cs->len] = '\0'

在尾部追加字符:

  1. void c_string_append_char(c_string_t *cs, char c) { 
  2.     if (cs == NULLreturn
  3.     c_string_ensure_space(cs, 1); 
  4.     cs->str[cs->len] = c; 
  5.     cs->len++; 
  6.     cs->str[cs->len] = '\0'

在尾部追加整數:

  1. void c_string_append_int(c_string_t *cs, int val) { 
  2.     char str[12]; 
  3.  
  4.     if (cs == NULLreturn
  5.  
  6.     snprintf(str, sizeof(str), "%d", val); // 整數轉為字符串 
  7.     c_string_append_str(cs, str, 0); 

在頭部插入字符串:

  1. void c_string_front_str(c_string_t *cs, const char *str, size_t len) { 
  2.     if (cs == NULL || str == NULL || *str == '\0'return
  3.  
  4.     if (len == 0) len = strlen(str); 
  5.  
  6.     c_string_ensure_space(cs, len); 
  7.     memmove(cs->str + len, cs->str, cs->len); 
  8.     memmove(cs->str, str, len); 
  9.     cs->len += len; 
  10.     cs->str[cs->len] = '\0'

在頭部插入字符:

  1. void c_string_front_char(c_string_t *cs, char c) { 
  2.     if (cs == NULLreturn
  3.     c_string_ensure_space(cs, 1); 
  4.     memmove(cs->str + 1, cs->str, cs->len); 
  5.     cs->str[0] = c; 
  6.     cs->len++; 
  7.     cs->str[cs->len] = '\0'

在頭部插入整數:

  1. void c_string_front_int(c_string_t *cs, int val) { 
  2.     char str[12]; 
  3.  
  4.     if (cs == NULLreturn
  5.  
  6.     snprintf(str, sizeof(str), "%d", val); 
  7.     c_string_front_str(cs, str, 0); 

清空字符串:

  1. void c_string_clear(c_string_t *cs) { 
  2.     if (cs == NULLreturn
  3.     c_string_truncate(cs, 0); 

裁剪字符串:

  1. void c_string_truncate(c_string_t *cs, size_t len) { 
  2.     if (cs == NULL || len >= cs->len) return
  3.  
  4.     cs->len = len; 
  5.     cs->str[cs->len] = '\0'

刪除頭部的N個字符:

  1. void c_string_drop_begin(c_string_t *cs, size_t len) { 
  2.     if (cs == NULL || len == 0) return
  3.  
  4.     if (len >= cs->len) { 
  5.         c_string_clear(cs); 
  6.         return
  7.     } 
  8.  
  9.     cs->len -= len; 
  10.     memmove(cs->str, cs->str + len, cs->len + 1); 

刪除尾部的N個字符:

  1. void c_string_drop_end(c_string_t *cs, size_t len) { 
  2.     if (cs == NULL || len == 0) return
  3.  
  4.     if (len >= cs->len) { 
  5.         c_string_clear(cs); 
  6.         return
  7.     } 
  8.     cs->len -= len; 
  9.     cs->str[cs->len] = '\0'

獲取字符串的長度:

  1. size_t c_string_len(const c_string_t *cs) { 
  2.     if (cs == NULLreturn 0; 
  3.     return cs->len; 

返回字符串指針,使用的是內部的內存:

  1. const char *c_string_peek(const c_string_t *cs) { 
  2.     if (cs == NULLreturn NULL
  3.     return cs->str; 

重新分配一塊內存存儲字符串返回:

  1. char *c_string_dump(const c_string_t *cs, size_t *len) { 
  2.     char *out
  3.  
  4.     if (cs == NULLreturn NULL
  5.  
  6.     if (len != NULL) *len = cs->len; 
  7.     out = malloc(cs->len + 1); 
  8.     memcpy(out, cs->str, cs->len + 1); 
  9.     return out

測試代碼如下:

  1. int main() { 
  2.     c_string_t *cs = c_string_create(); 
  3.     c_string_append_str(cs, "123", 0); 
  4.     c_string_append_char(cs, '4'); 
  5.     c_string_append_int(cs, 5); 
  6.     printf("%s \n", c_string_peek(cs)); 
  7.     c_string_front_str(cs, "789", 0); 
  8.     printf("%s \n", c_string_peek(cs)); 
  9.     c_string_drop_begin(cs, 2); 
  10.     printf("%s \n", c_string_peek(cs)); 
  11.     c_string_drop_end(cs, 2); 
  12.     printf("%s \n", c_string_peek(cs)); 
  13.     c_string_destroy(cs); 
  14.     return 0; 

輸出:

  1. 12345 
  2. 78912345 
  3. 912345 
  4. 9123 

完整代碼如下:頭文件:

  1. #include <stddef.h> 
  2.  
  3. struct c_string; 
  4. typedef struct c_string c_string_t; 
  5.  
  6. c_string_t *c_string_create(void); 
  7.  
  8. void c_string_destroy(c_string_t *cs); 
  9.  
  10. void c_string_append_str(c_string_t *cs, const char *str, size_t len); 
  11.  
  12. void c_string_append_char(c_string_t *cs, char c); 
  13.  
  14. void c_string_append_int(c_string_t *cs, int val); 
  15.  
  16. void c_string_front_str(c_string_t *cs, const char *str, size_t len); 
  17.  
  18. void c_string_front_char(c_string_t *cs, char c); 
  19.  
  20. void c_string_front_int(c_string_t *cs, int val); 
  21.  
  22. void c_string_clear(c_string_t *cs); 
  23.  
  24. void c_string_truncate(c_string_t *cs, size_t len); 
  25.  
  26. void c_string_drop_begin(c_string_t *cs, size_t len); 
  27.  
  28. void c_string_drop_end(c_string_t *cs, size_t len); 
  29.  
  30. size_t c_string_len(const c_string_t *cs); 
  31.  
  32. const char *c_string_peek(const c_string_t *cs); 
  33.  
  34. char *c_string_dump(const c_string_t *cs, size_t *len); 

源文件:

  1. #include <ctype.h> 
  2. #include <stdbool.h> 
  3. #include <stdlib.h> 
  4. #include <stdio.h> 
  5. #include <string.h> 
  6.  
  7. static const size_t c_string_min_size = 32; 
  8.  
  9. struct c_string { 
  10.     char *str; 
  11.     size_t alloced; 
  12.     size_t len; 
  13. }; 
  14.  
  15. c_string_t *c_string_create(void) { 
  16.     c_string_t *cs; 
  17.  
  18.     cs = calloc(1, sizeof(*cs)); 
  19.     cs->str = malloc(c_string_min_size); 
  20.     *cs->str = '\0'
  21.     cs->alloced = c_string_min_size; 
  22.     cs->len = 0; 
  23.  
  24.     return cs; 
  25.  
  26. void c_string_destroy(c_string_t *cs) { 
  27.     if (cs == NULLreturn
  28.     free(cs->str); 
  29.     free(cs); 
  30.  
  31. static void c_string_ensure_space(c_string_t *cs, size_t add_len) { 
  32.     if (cs == NULL || add_len == 0) return
  33.  
  34.     if (cs->alloced >= cs->len + add_len + 1) return
  35.  
  36.     while (cs->alloced < cs->len + add_len + 1) { 
  37.         cs->alloced <<= 1; 
  38.         if (cs->alloced == 0) { 
  39.             cs->alloced--; 
  40.         } 
  41.     } 
  42.     cs->str = realloc(cs->str, cs->alloced); 
  43.  
  44. void c_string_append_str(c_string_t *cs, const char *str, size_t len) { 
  45.     if (cs == NULL || str == NULL || *str == '\0'return
  46.  
  47.     if (len == 0) len = strlen(str); 
  48.  
  49.     c_string_ensure_space(cs, len); 
  50.     memmove(cs->str + cs->len, str, len); 
  51.     cs->len += len; 
  52.     cs->str[cs->len] = '\0'
  53.  
  54. void c_string_append_char(c_string_t *cs, char c) { 
  55.     if (cs == NULLreturn
  56.     c_string_ensure_space(cs, 1); 
  57.     cs->str[cs->len] = c; 
  58.     cs->len++; 
  59.     cs->str[cs->len] = '\0'
  60.  
  61. void c_string_append_int(c_string_t *cs, int val) { 
  62.     char str[12]; 
  63.  
  64.     if (cs == NULLreturn
  65.  
  66.     snprintf(str, sizeof(str), "%d", val); 
  67.     c_string_append_str(cs, str, 0); 
  68.  
  69. void c_string_front_str(c_string_t *cs, const char *str, size_t len) { 
  70.     if (cs == NULL || str == NULL || *str == '\0'return
  71.  
  72.     if (len == 0) len = strlen(str); 
  73.  
  74.     c_string_ensure_space(cs, len); 
  75.     memmove(cs->str + len, cs->str, cs->len); 
  76.     memmove(cs->str, str, len); 
  77.     cs->len += len; 
  78.     cs->str[cs->len] = '\0'
  79.  
  80. void c_string_front_char(c_string_t *cs, char c) { 
  81.     if (cs == NULLreturn
  82.     c_string_ensure_space(cs, 1); 
  83.     memmove(cs->str + 1, cs->str, cs->len); 
  84.     cs->str[0] = c; 
  85.     cs->len++; 
  86.     cs->str[cs->len] = '\0'
  87.  
  88. void c_string_front_int(c_string_t *cs, int val) { 
  89.     char str[12]; 
  90.  
  91.     if (cs == NULLreturn
  92.  
  93.     snprintf(str, sizeof(str), "%d", val); 
  94.     c_string_front_str(cs, str, 0); 
  95.  
  96. void c_string_clear(c_string_t *cs) { 
  97.     if (cs == NULLreturn
  98.     c_string_truncate(cs, 0); 
  99.  
  100. void c_string_truncate(c_string_t *cs, size_t len) { 
  101.     if (cs == NULL || len >= cs->len) return
  102.  
  103.     cs->len = len; 
  104.     cs->str[cs->len] = '\0'
  105.  
  106. void c_string_drop_begin(c_string_t *cs, size_t len) { 
  107.     if (cs == NULL || len == 0) return
  108.  
  109.     if (len >= cs->len) { 
  110.         c_string_clear(cs); 
  111.         return
  112.     } 
  113.  
  114.     cs->len -= len; 
  115.     /* +1 to move the NULL. */ 
  116.     memmove(cs->str, cs->str + len, cs->len + 1); 
  117.  
  118. void c_string_drop_end(c_string_t *cs, size_t len) { 
  119.     if (cs == NULL || len == 0) return
  120.  
  121.     if (len >= cs->len) { 
  122.         c_string_clear(cs); 
  123.         return
  124.     } 
  125.     cs->len -= len; 
  126.     cs->str[cs->len] = '\0'
  127.  
  128. size_t c_string_len(const c_string_t *cs) { 
  129.     if (cs == NULLreturn 0; 
  130.     return cs->len; 
  131.  
  132. const char *c_string_peek(const c_string_t *cs) { 
  133.     if (cs == NULLreturn NULL
  134.     return cs->str; 
  135.  
  136. char *c_string_dump(const c_string_t *cs, size_t *len) { 
  137.     char *out
  138.  
  139.     if (cs == NULLreturn NULL
  140.  
  141.     if (len != NULL) *len = cs->len; 
  142.     out = malloc(cs->len + 1); 
  143.     memcpy(out, cs->str, cs->len + 1); 
  144.     return out

 

責任編輯:武曉燕 來源: 程序喵大人
相關推薦

2021-11-19 11:36:42

語言string字符串

2023-04-03 08:02:16

切片擴容GO

2022-10-21 09:01:41

StudentC++類型

2010-03-11 19:16:32

Python語言

2020-08-26 14:00:37

C++string語言

2022-01-13 10:30:21

C語言內存動態

2011-07-05 17:07:14

C語言

2023-10-26 11:03:50

C語言宏定義

2010-07-07 11:09:36

UDPClient

2021-05-10 20:58:11

數據庫擴容用戶

2014-08-05 13:09:34

Objective-C動態特性

2010-01-14 17:58:41

C++語言

2010-01-04 19:14:46

Silverlight

2010-01-28 15:31:34

學習C++語言

2020-06-19 12:59:33

動態腳本Java

2024-08-13 09:16:30

2010-12-01 15:28:19

ProbeVueJava

2022-09-02 17:07:46

C語言main()

2009-08-28 16:14:26

C#實現加載動態庫

2021-06-26 07:29:42

RedisHashtable數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费成人高清 | 国产精品自拍av | 另类亚洲视频 | 金莲网 | 日韩精品1区2区 | 黄色亚洲 | 亚洲综合大片69999 | 爱爱无遮挡 | 美国一级黄色片 | 国产成人亚洲精品自产在线 | 伊人免费在线观看 | 亚洲久久久| 亚洲一区二区三区免费在线观看 | 中文字幕一区在线 | 欧美国产精品一区二区三区 | 欧美视频区 | 一区二区三区四区在线视频 | 国产美女黄色 | 国产在线视频一区二区 | 国产二区精品视频 | 亚洲精品国产综合区久久久久久久 | 久草在线 | 色啪网| 色橹橹欧美在线观看视频高清 | 午夜黄色影院 | 国产精品极品美女在线观看免费 | 亚洲一区亚洲二区 | xxxxx黄色片 欧美一区免费 | 男女网站视频 | 一区二区三区四区五区在线视频 | 自拍偷拍欧美 | 午夜影院免费体验区 | 日韩欧美在线免费观看 | 久久久久久亚洲精品 | 日韩在线免费视频 | 狠狠入ady亚洲精品经典电影 | 亚洲综合在线视频 | 日韩精品在线看 | 国产精品网址 | 国产免费福利在线 | 久草免费在线 |