<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 8531字,需瀏覽 18分鐘

           ·

          2020-10-26 14:59

          又好久沒(méi)更新了,最近程序喵工作實(shí)在是太忙,業(yè)余時(shí)間也在學(xué)習(xí)新知識(shí)醞釀大招,便于后期更新好文,最近先水幾篇吧,大家有想了解的知識(shí)點(diǎn)可以在文末讀者討論中留言哈!

          眾所周知,C++ 中的string使用比較方便,關(guān)于C++ 中的string源碼實(shí)現(xiàn)可以看我的這篇文章:源碼分析C++的string的實(shí)現(xiàn)
          最近工作中使用C語(yǔ)言,但又苦于沒(méi)有高效的字符串實(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í)例

          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í)際長(zhǎng)度
          };

          創(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?len?+?add_len?+?1)?{
          ????????cs->alloced?<<=?1;?//?每次以2倍大小擴(kuò)容
          ????????if?(cs->alloced?==?0)?{
          ????????????//?左移到最后可能會(huì)變?yōu)?,由于alloced是無(wú)符號(hào)型,減一則會(huì)變成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)部有足夠的空間存儲(chǔ)字符串
          ????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';
          }

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

          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)存存儲(chǔ)字符串返回:

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

          測(cè)試代碼如下:

          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?

          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?
          #include?
          #include?
          #include?
          #include?

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

          瀏覽 58
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码在线免费视频 | 天堂网成人在线 | 97超碰碰 | 超级A片在线观看 | 97中文字幕 |