溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C語言中怎么動態(tài)擴(kuò)容String

發(fā)布時(shí)間:2021-07-02 16:42:21 來源:億速云 閱讀:249 作者:Leah 欄目:編程語言

這篇文章給大家介紹C語言中怎么動態(tài)擴(kuò)容String,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

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

struct c_string; typedef struct c_string c_string_t;

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

// string的初始內(nèi)存大小 static const size_t c_string_min_size = 32;  struct c_string {     char *str; // 字符串指針     size_t alloced; // 已分配的內(nèi)存大小     size_t len; // 字符串的實(shí)際長度 };

創(chuàng)建字符串:

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

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

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倍大小擴(kuò)容         if (cs->alloced == 0) {             // 左移到最后可能會變?yōu)?,由于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); // 確保內(nèi)部有足夠的空間存儲字符串     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'; }

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

void c_string_append_int(c_string_t *cs, int val) {     char str[12];      if (cs == NULL) return;      snprintf(str, sizeof(str), "%d", val); // 整數(shù)轉(zhuǎn)為字符串     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'; }

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

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

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

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; }

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

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

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

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;     /* +1 to move the NULL. */     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; }

關(guān)于C語言中怎么動態(tài)擴(kuò)容String就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI