自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C語(yǔ)言如何實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容的String

開發(fā) 后端
最近工作中使用C語(yǔ)言,但又苦于沒有高效的字符串實(shí)現(xiàn),字符串的拼接和裁剪都比較麻煩,而且每個(gè)字符串都需要申請(qǐng)內(nèi)存,內(nèi)存的申請(qǐng)和釋放也很容易出bug,怎么高效的實(shí)現(xiàn)一個(gè)不需要處理內(nèi)存問(wèn)題并且可以動(dòng)態(tài)擴(kuò)容進(jìn)行拼接和裁剪的string呢?

[[347888]]

本文轉(zhuǎn)載自微信公眾號(hào)「程序喵大人」,作者程序喵大人 。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序喵大人公眾號(hào)。

最近工作中使用C語(yǔ)言,但又苦于沒有高效的字符串實(shí)現(xiàn),字符串的拼接和裁剪都比較麻煩,而且每個(gè)字符串都需要申請(qǐng)內(nèi)存,內(nèi)存的申請(qǐng)和釋放也很容易出bug,怎么高效的實(shí)現(xiàn)一個(gè)不需要處理內(nèi)存問(wèn)題并且可以動(dòng)態(tài)擴(kuò)容進(jìn)行拼接和裁剪的string呢?

  • 一個(gè)好的string應(yīng)該有以下功能?
  • 創(chuàng)建字符串
  • 刪除字符串
  • 尾部追加字符串
  • 頭部插入字符串
  • 從尾部刪除N個(gè)字符
  • 從頭部刪除N個(gè)字符
  • 裁剪字符串
  • 獲取字符串長(zhǎng)度
  • 獲取完整字符串

下面來(lái)看看各個(gè)功能的實(shí)現(xiàn):

首先定義一個(gè)string的句柄,相當(dāng)于C++中的實(shí)例

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

在內(nèi)部string的實(shí)現(xiàn)如下:

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

創(chuàng)建字符串:

  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.     // 初始分配內(nèi)存大小是32,之后每次以2倍大小擴(kuò)容 
  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); 

內(nèi)部如何擴(kuò)容呢:

  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倍大小擴(kuò)容 
  8.         if (cs->alloced == 0) { 
  9.             // 左移到最后可能會(huì)變?yōu)?,由于alloced是無(wú)符號(hào)型,減一則會(huì)變成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); // 確保內(nèi)部有足夠的空間存儲(chǔ)字符串 
  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'

在尾部追加整數(shù):

  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); // 整數(shù)轉(zhuǎn)為字符串 
  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'

在頭部插入整數(shù):

  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個(gè)字符:

  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個(gè)字符:

  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'

獲取字符串的長(zhǎng)度:

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

返回字符串指針,使用的是內(nèi)部的內(nèi)存:

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

重新分配一塊內(nèi)存存儲(chǔ)字符串返回:

  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

測(cè)試代碼如下:

  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

 

責(zé)任編輯:武曉燕 來(lái)源: 程序喵大人
相關(guān)推薦

2021-11-19 11:36:42

語(yǔ)言string字符串

2023-04-03 08:02:16

切片擴(kuò)容GO

2022-10-21 09:01:41

StudentC++類型

2010-03-11 19:16:32

Python語(yǔ)言

2020-08-26 14:00:37

C++string語(yǔ)言

2022-01-13 10:30:21

C語(yǔ)言內(nèi)存動(dòng)態(tài)

2023-10-26 11:03:50

C語(yǔ)言宏定義

2011-07-05 17:07:14

C語(yǔ)言

2010-07-07 11:09:36

UDPClient

2021-05-10 20:58:11

數(shù)據(jù)庫(kù)擴(kuò)容用戶

2010-01-14 17:58:41

C++語(yǔ)言

2014-08-05 13:09:34

Objective-C動(dòng)態(tài)特性

2010-01-04 19:14:46

Silverlight

2024-08-13 09:16:30

2010-12-01 15:28:19

ProbeVueJava

2020-06-19 12:59:33

動(dòng)態(tài)腳本Java

2010-01-28 15:31:34

學(xué)習(xí)C++語(yǔ)言

2009-08-28 16:14:26

C#實(shí)現(xiàn)加載動(dòng)態(tài)庫(kù)

2022-09-02 17:07:46

C語(yǔ)言main()

2021-06-26 07:29:42

RedisHashtable數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)