|
又好久没更新了,最近程序喵工作实在是太忙,业余时间也在学习新知识酝酿大招,便于后期更新好文,最近先水几篇吧,大家有想了解的知识点可以在文末读者讨论中留言哈! 众所周知,C++ 中的string使用比较方便,关于C++ 中的string源码实现可以看我的这篇文章:源码分析C++的string的实现9 M$ U+ f+ q* n
下面来看看各个功能的实现: typedef struct c_string c_string_t;8 i8 x' ]0 L& ]& N9 c" u6 Y 在内部string的实现如下: // string的初始内存大小static const size_t c_string_min_size = 32;7 M# v" q+ L. w- Y 8 {* V8 D& I. r7 r struct c_string {+ _$ H& I( z; s; ?& l0 b# Q4 l char *str; // 字符串指针9 D& Y7 m |8 d5 n! Q size_t alloced; // 已分配的内存大小 size_t len; // 字符串的实际长度9 M5 g4 B2 c$ Q' N }; 创建字符串: c_string_t *c_string_create(void) {c_string_t *cs;9 }7 E$ {" H& E O+ w - Z8 x3 E/ z0 W8 n4 ]( M cs = calloc(1, sizeof(*cs)); cs->str = malloc(c_string_min_size);. K; J" g& X/ F; Q *cs->str = '\0'; // 初始分配内存大小是32,之后每次以2倍大小扩容- F ?3 Y) X7 s 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);7 l4 s& b" e' X/ K, `/ X: J4 H$ i } 内部如何扩容呢: static void c_string_ensure_space(c_string_t *cs, size_t add_len) {if (cs == NULL || add_len == 0) return; - K7 p# T5 Y/ H+ n H if (cs->alloced >= cs->len + add_len + 1) return; while (cs->alloced < cs->len + add_len + 1) {+ G8 e& Q6 ?! j3 L" f, G cs->alloced <<= 1; // 每次以2倍大小扩容! x$ ^' v$ }$ x1 r% i( P5 M if (cs->alloced == 0) { // 左移到最后可能会变为0,由于alloced是无符号型,减一则会变成UINT_MAX6 K N) J$ ~, a1 p8 P: V( } cs->alloced--;; m, Y5 r! S" t- k" u } } d+ l+ X i" f" A9 M r 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;% Q$ n6 `4 I& Y9 o6 ? if (len == 0) len = strlen(str); c_string_ensure_space(cs, len); // 确保内部有足够的空间存储字符串 memmove(cs->str + cs->len, str, len); cs->len += len;# N6 B% a9 l) c6 B" a) U cs->str[cs->len] = '\0'; } 在尾部追加字符: void c_string_append_char(c_string_t *cs, char c) {) z# R8 s& n4 g( ^" k2 f' z8 {( Zif (cs == NULL) return; c_string_ensure_space(cs, 1); cs->str[cs->len] = c;$ c3 y3 z2 b$ x$ b! t. G cs->len++;, l: |+ t8 d( n cs->str[cs->len] = '\0';! ]# J, n! @, |* i+ j- |7 u f' x }7 d( b( c' l$ }% |2 j @4 F# k 在尾部追加整数: void c_string_append_int(c_string_t *cs, int val) {char str[12];" B* g2 @+ l( j2 c. ~/ }9 l* ] 3 Z% `7 R! D4 o% @2 f7 j if (cs == NULL) return;, a. o: Z* l% O' U* [* V snprintf(str, sizeof(str), "%d", val); // 整数转为字符串 c_string_append_str(cs, str, 0); }* |5 [/ l5 {! ^( u! N1 h4 o6 m- r% b8 S 在头部插入字符串: 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);5 J0 U ?& j5 K3 i9 Q* `( F: k 3 O, x& K& f7 x c_string_ensure_space(cs, len); memmove(cs->str + len, cs->str, cs->len);1 F8 L6 {& x' Y) V/ E memmove(cs->str, str, len); cs->len += len;5 L0 l1 h1 Z' s, P! l cs->str[cs->len] = '\0';; n: h- _- m, g1 S6 _3 B }! A8 c9 ?& O X# p( Y8 M$ N 在头部插入字符: void c_string_front_char(c_string_t *cs, char c) {if (cs == NULL) return;& p+ a: n' K& }; y c_string_ensure_space(cs, 1); memmove(cs->str + 1, cs->str, cs->len); x) ] E) d- p% _3 d- q cs->str[0] = c; cs->len++; cs->str[cs->len] = '\0'; }# m9 C. ~% t' ^5 U) A+ Y 在头部插入整数: void c_string_front_int(c_string_t *cs, int val) {( T+ t6 v0 ?% K4 N0 Jchar str[12]; ! C5 r% O7 F! V 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;3 l& n _6 D- C8 h/ \ cs->str[cs->len] = '\0'; } 删除头部的N个字符: void c_string_drop_begin(c_string_t *cs, size_t len) {if (cs == NULL || len == 0) return; ' ?0 C S1 N) c" ^" s if (len >= cs->len) { c_string_clear(cs);* w! J" w: B* y( U0 w9 B' _ return;% k7 g: a* t" ], B2 m* V9 t0 U } 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) {0 G3 v, J, A$ c* x$ I' Mif (cs == NULL || len == 0) return;' |5 E1 u7 H, V6 r$ \ 6 R! V" T% E( u7 I0 D2 Z" ` if (len >= cs->len) { c_string_clear(cs); return;( b% C% I- b+ [% u } cs->len -= len; cs->str[cs->len] = '\0';- T' ]5 E8 w7 V' ?9 C: R6 P- \ } 获取字符串的长度: size_t c_string_len(const c_string_t *cs) {' [4 |5 o4 H4 w6 H8 Q' Vif (cs == NULL) return 0;" N) b/ S; h3 N1 y return cs->len;: T9 O N0 V8 J } 返回字符串指针,使用的是内部的内存: const char *c_string_peek(const c_string_t *cs) {if (cs == NULL) return NULL;$ r- e: Z0 d, E% b0 U7 q return cs->str;! ]. B+ e2 X6 ^0 ^ } 重新分配一块内存存储字符串返回: char *c_string_dump(const c_string_t *cs, size_t *len) {8 H; F B1 q9 o6 `9 _ kchar *out;7 g. D' X" c2 E5 `& C6 C0 C6 r$ g if (cs == NULL) return NULL;0 L/ m) ~* w0 m% w- i' N if (len != NULL) *len = cs->len; e- y& z. c# O9 v2 i, P out = malloc(cs->len + 1); memcpy(out, cs->str, cs->len + 1); return out; }) C. l# x7 `4 {1 w3 x 测试代码如下: int main() {: a$ o" b4 F, c8 Z+ Gc_string_t *cs = c_string_create();& S% r8 T. ^' q. u% c6 m c_string_append_str(cs, "123", 0);' P8 {' ? }" W# x/ }; z! s c_string_append_char(cs, '4'); c_string_append_int(cs, 5); printf("%s \n", c_string_peek(cs));: z7 [% k- o8 ^9 ?' H' q O c_string_front_str(cs, "789", 0); printf("%s \n", c_string_peek(cs)); c_string_drop_begin(cs, 2); w+ |; i6 F9 P printf("%s \n", c_string_peek(cs)); c_string_drop_end(cs, 2); printf("%s \n", c_string_peek(cs)); c_string_destroy(cs);. ?! t( L5 u, P return 0;' Y% M/ j! j6 i# t }" k8 k H4 f( p, @" ~% F: Q1 j 输出: 12345. W/ n! k$ ?! v9 \: m7 C, Z! L78912345 912345 9123) q- O( I! k* ^6 X 完整代码如下:头文件: #include <stddef.h>! F$ B( T6 }& g6 g- ~/ M$ B! kstruct c_string; typedef struct c_string c_string_t;# K& A- \. P: K) q8 b2 m c_string_t *c_string_create(void);, n* R" ~4 ~, Y s5 [ void c_string_destroy(c_string_t *cs);6 Q+ A, K2 _1 V3 D9 a : l7 j3 w, C+ j" ^7 `1 O) K void c_string_append_str(c_string_t *cs, const char *str, size_t len);, Q2 ^, a; V* i+ d" A, g! ^! E ) w4 ^1 A4 ~' \ void c_string_append_char(c_string_t *cs, char c);9 {3 c5 b- `# b3 L void c_string_append_int(c_string_t *cs, int val);6 ?! Z8 ]+ ]; b4 I6 s 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);2 v! s% _7 b' h q5 W/ Y6 w4 v void c_string_front_int(c_string_t *cs, int val);& H7 z( P: d1 D! D0 [ . J) }: p9 M- q1 { void c_string_clear(c_string_t *cs);3 x k- i4 U" _: R( f1 ? : x l$ B5 F5 t8 I void c_string_truncate(c_string_t *cs, size_t len);1 s# w& D/ a$ S6 ^; u4 U) e1 l ) f* ?& J- p# ^$ e& q void c_string_drop_begin(c_string_t *cs, size_t len);8 f* ~; Z9 l" w' f/ ] V' T) Q5 T9 O+ _ void c_string_drop_end(c_string_t *cs, size_t len);6 }& t$ t9 q! z! \& \6 V size_t c_string_len(const c_string_t *cs);; \, m7 _& W |; M: W1 T ! ?; `2 i5 y4 Z/ ]) d+ ?8 c, K8 Y const char *c_string_peek(const c_string_t *cs);% C2 p; A ~6 ^5 l# x$ T' I G5 ]/ s" c5 r7 x& M char *c_string_dump(const c_string_t *cs, size_t *len); 源文件: #include <ctype.h>#include <stdbool.h>+ {, B& K# W; u* ~/ e #include <stdlib.h> #include <stdio.h> #include <string.h> / o3 o; @( z: X. y5 P& {3 r static const size_t c_string_min_size = 32; . A7 C2 f: ~4 s$ j5 y3 \ struct c_string { char *str; size_t alloced; size_t len;- i3 x9 y. M. V* | };: Q- E1 B9 j) [2 [) e1 g1 h% }0 t$ Z 6 c' a, p) p/ V" r% s) O: ]7 R c_string_t *c_string_create(void) { c_string_t *cs;" a* \1 I- s f! Y) b % v+ N% z& |" Y! ~: v, | cs = calloc(1, sizeof(*cs));' R8 b o* b+ a) {- S1 ~8 ]" \ cs->str = malloc(c_string_min_size);, f3 N {4 N- S+ N/ T* y0 J- k *cs->str = '\0';4 `) _9 A0 v. A. D; \7 r cs->alloced = c_string_min_size;- \( @& M6 \! s$ b cs->len = 0; " X$ | A# a: g4 ~" n- F& r return cs; } 4 f, V2 _5 p U4 r, s, y void c_string_destroy(c_string_t *cs) {6 |! i7 y2 P/ L* R% J5 Q if (cs == NULL) return; free(cs->str); free(cs);" s' j2 w0 I9 z } ( G; j+ g& j- p" ]3 ^ static void c_string_ensure_space(c_string_t *cs, size_t add_len) {" Q2 f. s$ b6 c0 ` if (cs == NULL || add_len == 0) return;/ J+ {+ i0 C( ], }9 C" L 3 a% M' m7 \7 Z* n% ]4 X, y- A if (cs->alloced >= cs->len + add_len + 1) return;& Y. @+ O) B1 x 3 z0 ~7 X8 \8 ]7 h1 X while (cs->alloced < cs->len + add_len + 1) { cs->alloced <<= 1; if (cs->alloced == 0) {/ F6 }! @. J4 M; M2 W" }5 w cs->alloced--;" C& w0 ^' S7 o- s' z! i4 l } } cs->str = realloc(cs->str, cs->alloced);# @3 q; b6 q7 W5 P } void c_string_append_str(c_string_t *cs, const char *str, size_t len) {6 C3 j- W4 M5 B: { if (cs == NULL || str == NULL || *str == '\0') return; if (len == 0) len = strlen(str); 7 a/ I8 c* [$ U- o; w* R c_string_ensure_space(cs, len);1 D0 ?' i% I8 d1 z memmove(cs->str + cs->len, str, len); cs->len += len; cs->str[cs->len] = '\0';2 g1 Y( b, B. R% [5 T- ^$ l- V7 b3 _ }9 U/ ^# C6 [- F0 P2 G# X* C void c_string_append_char(c_string_t *cs, char c) {& l$ r% T9 z" C5 B# q0 d if (cs == NULL) return; c_string_ensure_space(cs, 1);* |3 r) [* I; x, u" J cs->str[cs->len] = c; cs->len++;- b) X' _" q5 f+ \3 n% X% E- t cs->str[cs->len] = '\0';& D9 I# N5 }7 r6 Y6 }8 W( q' O. x$ I } 0 p. A) B4 E) G void c_string_append_int(c_string_t *cs, int val) {! `# `7 x( Q; I1 q8 p char str[12]; / X/ ^. N' |% H5 b& B if (cs == NULL) return;+ a( E5 f% l1 a 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; v6 F! ?* K$ t+ U- ]+ n* Y if (len == 0) len = strlen(str); 8 M; J2 M. z: C4 Z9 I+ C1 ?5 [ c_string_ensure_space(cs, len); memmove(cs->str + len, cs->str, cs->len);( H' Z6 q5 h" [- L2 G, A. ?0 M memmove(cs->str, str, len); cs->len += len;* N `6 {* I, R/ Z8 M; [ cs->str[cs->len] = '\0';( ~: Z% q6 H% ]6 ]; ^* Q: L }+ K8 ^$ b% H& g: ^2 x : P, Y8 C, B1 y( G" F" p! T void c_string_front_char(c_string_t *cs, char c) {8 U2 E3 r/ ^. T2 J( O if (cs == NULL) return;6 a. X% j+ Y4 o% w& f 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];9 [7 r, m8 |9 j0 _0 K5 F 3 n+ C' w4 U L/ @2 S5 g if (cs == NULL) return; snprintf(str, sizeof(str), "%d", val); c_string_front_str(cs, str, 0); }8 y8 o i( n3 X0 Z void c_string_clear(c_string_t *cs) {. R4 i7 l# @1 P: ] if (cs == NULL) return; c_string_truncate(cs, 0);+ _9 _! Y9 {" I! ^8 ]: p } + \ X7 x: Q2 b7 m 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'; } - y: x' D& \9 b- k/ X void c_string_drop_begin(c_string_t *cs, size_t len) { if (cs == NULL || len == 0) return; if (len >= cs->len) {0 ?- _3 O' s0 m c_string_clear(cs);9 G% K( a$ F' r7 r return;' o3 l# ^7 Q, S9 l }; u% f7 n, b4 b( {$ t) E' G cs->len -= len; /* +1 to move the NULL. */ memmove(cs->str, cs->str + len, cs->len + 1); } ; V7 @3 L: E5 L+ G f void c_string_drop_end(c_string_t *cs, size_t len) { if (cs == NULL || len == 0) return;; N; g& g3 O) L6 k* x ; S" V3 n, E# ]0 ?+ h' E if (len >= cs->len) {' a/ R6 S' a& J. w c_string_clear(cs); return; }( T& o" r1 J' x# e# T0 ` cs->len -= len; cs->str[cs->len] = '\0';+ [0 {! Y2 a6 v% D. q& _2 c" W$ K, }0 Z } ( z; m0 U/ j9 i( {5 b, X+ ~ size_t c_string_len(const c_string_t *cs) {( O9 [. x8 C1 T4 l. O if (cs == NULL) return 0; return cs->len;5 c" Q0 W3 E6 X9 ~ }& T7 ^$ ?2 _, S: k Z: R/ b const char *c_string_peek(const c_string_t *cs) { if (cs == NULL) return NULL;5 b: u$ r1 O, h return cs->str;1 `! W+ a* o2 h, T9 K* m& w& e3 B) e } * b' q, R1 B! P% |2 X6 X6 \7 g char *c_string_dump(const c_string_t *cs, size_t *len) {% J; e; y9 S& J. [3 p char *out; if (cs == NULL) return NULL; ; A. d1 Q! F! j7 i$ n8 ^7 R* E if (len != NULL) *len = cs->len; out = malloc(cs->len + 1);! B) e2 c+ k W! t" D$ H% |4 L memcpy(out, cs->str, cs->len + 1);, d0 [: D4 t3 j1 t; K return out; }' `$ a1 @' T/ r$ {0 ? |
微信公众号
手机版