国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

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技術棧公眾號

777电影在线观看| 亚洲国产午夜| 91精品一区二区三区久久久久久| 成人黄色激情网站| 成人网在线播放| 日本一区免费看| 中国精品18videos性欧美| 欧美一级视频一区二区| 成人永久在线| 中文字幕在线成人| 欧美暴力调教| 中文字幕亚洲欧美日韩2019| 松下纱荣子在线观看| 精品久久久久久久久久久院品网| 视频一区二区三区不卡| 欧美性猛片aaaaaaa做受| 日本1级在线| 日本韩国精品在线| 国产一二三区在线视频| 色天使色偷偷av一区二区| 偷拍25位美女撒尿视频在线观看| 亚洲高清在线精品| 在线一二三区| 色综合天天综合狠狠| 深夜福利在线看| 色综合亚洲欧洲| av中文字幕在线| 欧美一区二区成人6969| 成人爽a毛片免费啪啪动漫 | 欧美国产一区二区在线| 中文在线不卡| 亚洲v国产v在线观看| 国产在线播放一区二区三区| 致1999电视剧免费观看策驰影院| 国产精品一区三区| 国产亚洲综合视频| 亚洲狼人国产精品| yw在线观看| 亚洲女人天堂视频| 一区中文字幕电影| 91在线观看免费高清| 久久www成人_看片免费不卡| 欧美国产视频一区| 综合av第一页| av网页在线| 在线日韩欧美视频| 蜜桃一区二区三区| 精品国产一区二区三区四区vr| 蜜臀精品一区二区三区在线观看| 男人日女人视频网站| 日韩一区中文字幕| 国产高清视频免费最新在线| 精品久久久久久久久久久院品网| 欧美国产日韩电影| 国产精品va在线播放我和闺蜜| 欧美久久成人| www.一区二区.com| 中文字幕一区二| 美女av在线播放| 久久九九国产精品怡红院| 不卡中文字幕| 欧美日韩在线免费观看视频| 国产精品久久久爽爽爽麻豆色哟哟| 麻豆av电影在线观看| 亚洲色图偷窥自拍| 久久国产电影| 日韩精品一区二区在线视频 | 一区二区三区四区五区精品| 2024国产精品视频| 成人在线免费视频| 日韩亚洲精品电影| 欧美a级片一区| 中文字幕日本最新乱码视频| 欧美视频第二页| 国产一区2区在线观看| 97视频资源在线观看| www.亚洲国产| 国产小视频在线| 欧美精品福利视频| 日韩专区中文字幕一区二区| 另类小说色综合| 日韩一卡二卡三卡四卡| 亚洲传媒在线| 青青青在线观看视频| 午夜不卡在线视频| 成人国产一区二区三区精品麻豆| 91免费看蜜桃| 中文一区二区在线观看| f2c人成在线观看免费视频| 国产精品www色诱视频| 国产精品资源在线观看| 激情视频在线观看免费| 久久久久久中文字幕| 日韩av中文字幕一区二区三区| 午夜视频99| 欧美丰满老妇厨房牲生活| 日韩精品乱码免费| 欧美日韩在线中文字幕| 97超碰国产精品女人人人爽| 国产美女主播视频一区| av在线免费观看网| 日本久久久久久久久| 26uuu久久天堂性欧美| 91九色国产在线播放| 国产一区二区免费电影| 一区二区三区不卡视频在线观看| 不卡一区视频| 日本一本草久p| 日韩美女主播在线视频一区二区三区 | 91丝袜呻吟高潮美腿白嫩在线观看| 欧美人xxx| 成人网在线免费观看| 中文字幕在线不卡一区二区三区| av有声小说一区二区三区| 日本日本精品二区免费| 欧美在线999| 欧美午夜影院| 免费在线性爱视频| 91麻豆桃色免费看| 欧美日韩激情网| 欧美hd在线| 一级毛片在线| 亚洲一区二区三区久久| 午夜欧美一区二区三区在线播放| 日韩影视高清在线观看| 91制片厂毛片| 高清欧美性猛交| 国产精品进线69影院| 欧美巨大xxxx| 一级毛片免费看| 国产精品久久久久久久久久小说 | 一区二区免费| 国产淫片免费看| 中文字幕亚洲欧美日韩在线不卡 | 91精品国产综合久久香蕉的用户体验 | 2021久久国产精品不只是精品| 成人欧美magnet| 国产卡一卡二在线| 国产午夜精品久久久| 国产精品日韩精品欧美精品| 久热国产在线| 欧美福利精品| 亚洲精品天天看| 国产成人精品免费| 精品久久毛片| 播放灌醉水嫩大学生国内精品| 日韩在线资源网| 国产精品久久久久久福利一牛影视 | 国产高清一区| 清纯唯美亚洲色图| 精品伊人久久大线蕉色首页| 欧美一区二区免费| 国内精品久久久久影院一蜜桃| 精品国产黄a∨片高清在线| 国产又大又黄又粗又爽| 国产精品成av人在线视午夜片| 黑人狂躁日本妞一区二区三区 | 超碰在线网址| 日本美女爱爱视频| 欧美精品在线观看| 亚洲综合免费观看高清完整版在线| 91精品高清| caoporn视频在线观看| 欧美日韩激情视频在线观看| 琪琪第一精品导航| 欧美区在线观看| 成人免费高清视频在线观看| 大奶一区二区三区| 最新在线地址| 在线视频一区观看| 欧美激情视频一区二区| 欧美性xxxxxx| 狠狠色2019综合网| 日本一区影院| 国产鲁鲁视频在线观看免费| 日本亚洲自拍| 久久久久久久久久久久av| 色94色欧美sute亚洲线路一ni | 肥熟一91porny丨九色丨| 亚洲精品97久久| 中文字幕在线不卡一区| 日韩午夜高潮| www.欧美| 最新真实国产在线视频| 欧美在线观看成人| 国产精品裸体一区二区三区| 亚洲视频一区二区| 欧美日韩亚洲一区二区| 成人白浆超碰人人人人| 亚洲精品国产偷自在线观看| **在线精品| 欧美18xxxxx| 欧美成人免费高清视频| 久久久久综合一区二区三区| 国内精品久久久久久| 在线成人午夜影院| 中文字幕国产一区| 另类综合日韩欧美亚洲| 天堂在线精品| 亚洲四虎影院|