當(dāng)前位置:首頁 > 公眾號(hào)精選 > 嵌入式微處理器
[導(dǎo)讀]一、沉浸式學(xué)習(xí) 以學(xué)習(xí)一門語言為例: 大多數(shù)人都持有一種觀念,要真正學(xué)好一門語言必須得去所學(xué)語言當(dāng)?shù)貙W(xué)習(xí)或生活一段時(shí)間。 而事實(shí)上,大多數(shù)人都沒有這樣的學(xué)習(xí)條件。 解決問題的方法是: 自行改造環(huán)境,為自己創(chuàng)造沉浸式的學(xué)習(xí)環(huán)境。 例如: 看新語言的


一、沉浸式學(xué)習(xí)

以學(xué)習(xí)一門語言為例:
大多數(shù)人都持有一種觀念,要真正學(xué)好一門語言必須得去所學(xué)語言當(dāng)?shù)貙W(xué)習(xí)或生活一段時(shí)間。

而事實(shí)上,大多數(shù)人都沒有這樣的學(xué)習(xí)條件。

解決問題的方法是:
自行改造環(huán)境,為自己創(chuàng)造沉浸式的學(xué)習(xí)環(huán)境。

例如:

  • 看新語言的電影;

  • 更改手機(jī)、電腦的語言設(shè)置;

  • 看新語言的文檔和書籍;

  • 用新語言寫 todo list;

  • 用新語言來學(xué)習(xí)自己需要的專業(yè)知識(shí);

  • 翻譯新語言的文檔并分享;

  • 逛所學(xué)語言的論壇和網(wǎng)站;

  • 用新語言寫代碼注釋 / commit message / README / issue;

  • ...

對了,我作為英文的愛好者,一直想重啟我的英文學(xué)習(xí)之路,后續(xù)想在公眾號(hào)里記錄一些英文相關(guān)的知識(shí),請你們不要笑話我~~~


二、字符串函數(shù)庫:Simple Dynamic Strings

1. 簡介

Simple Dynamic Strings (簡稱 SDS) 是一個(gè) C 語言字符串庫,它增強(qiáng)了 C 語言字符串處理的能力。

設(shè)計(jì) SDS 原本是為了滿足設(shè)計(jì)者自身日常的 C 編程,后來又被轉(zhuǎn)移到 Redis 中,在 Redis 中被廣泛使用并對其進(jìn)行了修改以適合于高性能操作。現(xiàn)在,它又被從 Redis 中提取出來的,并 fork 為一個(gè)獨(dú)立項(xiàng)目。

只有 1500 行不到的代碼,就能做到 3.2K 個(gè) star,牛牛牛~~~

它有什么優(yōu)點(diǎn)?

  • 使用更簡單;

  • 二進(jìn)制安全;

  • 效率更高;

  • 與 C 字符串函數(shù)兼容;

源碼鏈接:

https://github.com/antirez/sds

源碼文件:

sds.c
sdsalloc.h
sds.h
testhelp.h

相關(guān) API:

sds sdsnewlen(const void *init, size_t initlen) 
sds sdsempty(void) 
sds sdsnew(const char *init) 
sds sdsdup(const sds s) 
void sdsfree(sds s) 
void sdsupdatelen(sds s) 
void sdsclear(sds s) 
sds sdsMakeRoomFor(sds s, size_t addlen) 
sds sdsRemoveFreeSpace(sds s) 
size_t sdsAllocSize(sds s) 
void *sdsAllocPtr(sds s) 
void sdsIncrLen(sds s, ssize_t incr) 
sds sdsgrowzero(sds s, size_t len) 
sds sdscatlen(sds s, const void *t, size_t len) 
sds sdscat(sds s, const char *t) 
sds sdscatsds(sds s, const sds t) 
sds sdscpylen(sds s, const char *t, size_t len) 
sds sdscpy(sds s, const char *t) 
int sdsll2str(char *s, long long value) 
int sdsull2str(char *s, unsigned long long v) 
sds sdsfromlonglong(long long value) 
sds sdscatvprintf(sds s, const char *fmt, va_list ap) 
sds sdscatprintf(sds s, const char *fmt, ...) 
sds sdscatfmt(sds s, char const *fmt, ...) 
sds sdstrim(sds s, const char *cset) 
void sdsrange(sds s, ssize_t start, ssize_t end) 
void sdstolower(sds s) 
void sdstoupper(sds s) 
int sdscmp(const sds s1, const sds s2) 
sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count) 
void sdsfreesplitres(sds *tokens, int count) 
sds sdscatrepr(sds s, const char *p, size_t len) 
int is_hex_digit(char c) 
int hex_digit_to_int(char c) 
sds *sdssplitargs(const char *line, int *argc) 
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) 
sds sdsjoin(char **argv, int argc, char *sep) 
sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen)

2. 比較常用的功能

2.1 創(chuàng)建字符串

sdsnew() 和 sdsfree():

#include <stdio.h>
#include "sds.h"
#include "sdsalloc.h"

int main(void)
{
    sds mystr = sdsnew("Hello World!");
    printf("%s\n", mystr);
    sdsfree(mystr);
}

運(yùn)行效果:

$ gcc -o sdsdemo sds.c sdsdemo.c
$ ./sdsdemo
Hello World!

看到了嗎?

printf 直接就可以打印 sds,這就是說 sds 本身就是 C 語言的字符串類型。

sds 的定義如下:

typedef char *sds;

也就是說,sds 是能兼容 libc 里字符串處理函數(shù) (例如strcpy, strcat...)的。

當(dāng)不再使用 sds 字符串時(shí),就算是空串,也要通過 sdsfree 銷毀字符串。

2.2 獲取字符串長度

sdsnewlen():

int main(void)
{
    char buf[3];
    sds mystring;

    buf[0] = 'A';
    buf[1] = 'B';
    buf[2] = 'C';
    mystring = sdsnewlen(buf,3);
    printf("%s of len %d\n", mystring, (int) sdslen(mystring));
}

運(yùn)行效果:

$ ./sdsdemo
ABC of len 3

和 strlen() 有 2 點(diǎn)不同

  • 運(yùn)行時(shí)長固定,sds 內(nèi)部有數(shù)據(jù)結(jié)構(gòu)保存著字符串的長度;

  • 長度與字符串內(nèi)是否有 NULL 無關(guān);

2.3 拼接字符串

sdscat():

int main(void)
{
    sds s = sdsempty();
    s = sdscat(s, "Hello ");
    s = sdscat(s, "World!");
    printf("%s\n", s);
}

運(yùn)行效果:

$ ./sdsdemo
Hello World!

sdscat 接受的參數(shù)是以 NULL 結(jié)尾的字符串,如果想擺脫這個(gè)限制,可以用 sdscatsds()。

sdscatsds():

int main(void)
{
    sds s1 = sdsnew("aaa");
    sds s2 = sdsnew("bbb");
    s1 = sdscatsds(s1,s2);
    sdsfree(s2);
    printf("%s\n", s1);
}

運(yùn)行效果:

$ ./sdsdemo
aaabbb

2.4 擴(kuò)展字符串長度

sdsgrowzero():

int main(void)
{
    sds s = sdsnew("Hello");
    s = sdsgrowzero(s,6);
    s[5] = '!'/* We are sure this is safe*/
    printf("%s\n", s);
}

運(yùn)行效果:

$ ./sdsdemo
Hello!

2.5 格式化字符串

sdscatprintf():

int main(void)
{
    sds s;
    int a = 10, b = 20;
    s = sdsnew("The sum is: ");
    s = sdscatprintf(s,"%d+%d = %d",a,b,a+b);
    printf("%s\n", s);
}

運(yùn)行效果:

$ ./sdsdemo
The sum is: 10+20 = 30

2.6 截取字符串

sdstrim():去掉指定字符

int main(void)
{
    sds s = sdsnew("         my string\n\n  ");
    sdstrim(s," \n");
    printf("-%s-\n",s);
}

運(yùn)行效果:

$ ./sdsdemo
-my string-

去掉了空格和換行符。

sdsrange():截取指定范圍內(nèi)的字符串

int main(void)
{
    sds s = sdsnew("Hello World!");
    sdsrange(s,1,4);
    printf("-%s-\n", s);
}

運(yùn)行效果:

$ ./sdsdemo
-ello-

2.7 字符串分割 (Tokenization)

sdssplitlen() 和 sdsfreesplitres():

int main(void)
{
    sds *tokens;
    int count, j;

    sds line = sdsnew("Hello World!");
    tokens = sdssplitlen(line, sdslen(line)," ",1,&count);

    for (j = 0; j < count; j++)
        printf("%s\n", tokens[j]);
    sdsfreesplitres(tokens,count);
}

sdssplitlen() 第 3和4 個(gè)參數(shù)指定分割符為空格。

運(yùn)行效果:

$ ./sdsdemo
Hello
World!

2.8 字符串合并 (String joining)

sdssplitlen() 和 sdsfreesplitres():

int main(void)
{
    char *tokens[3] = {"foo","bar","zap"};
    sds s = sdsjoin(tokens, 3"|");
    printf("%s\n", s);
}

運(yùn)行效果:

$ ./sdsdemo
foo|bar|zap

還有其他一些功能,用到再研究吧!

3. 簡單了解一下內(nèi)部實(shí)現(xiàn)

在 SDSD 中,使用二進(jìn)制前綴(頭部) 來保存字符串相關(guān)的信息,該頭部存儲(chǔ)在 SDS 返回給用戶的字符串的實(shí)際指針之前:

+--------+-------------------------------+-----------+
| Header | Binary safe C alike string... | Null term |
+--------+-------------------------------+-----------+
         |
         `-> Pointer returned to the user.

這個(gè) Header 在代碼中用結(jié)構(gòu)體來描述,該結(jié)構(gòu)體定義大致如下:

struct sdshdr {
    [...]
    int len;
    char buf[];
};
  • len 存儲(chǔ)的是字符串長度;

  • buf 指向緊隨其后的字符串首地址;

假設(shè)你使用的字符串為 "HELLOWORLD",為了提升效率,SDS 可能會(huì)提前分配多一些空間,所以實(shí)際的內(nèi)存布局如下:

+------------+------------------------+-----------+---------------\
| len | buf | H E L L O W O R L D \n | Null term |  Free space   \
+------------+------------------------+-----------+---------------\
             |
             `-> Pointer returned to the user.

現(xiàn)在,我們來看一下 SDS 分配字符串的大致步驟:

sds sdsnew(const char *init)
    initlen 
= (init == NULL) ? 0 : strlen(init);
    sdsnewlen(init, initlen);
        int hdrlen = sdsHdrSize(type);      // 確定 Header 的長度
        sh = s_malloc(hdrlen+initlen+1);    // 分配 Header + String + 1 個(gè)字節(jié)的空間

        s = (char*)sh+hdrlen;       // 保存 C string 的地址
        SDS_HDR_VAR(8,s);           // 定義 struct sdshdr sh
        sh->len = initlen;          // 初始化 struct sdshdr sh

        if (initlen && init)        // 初始化 C string 
            memcpy(s, init, initlen);
        
        s[initlen] = '\0';          // 總是添加一個(gè) NULL
        return s;                   // 返回 C string

其他的 SDS API 是如何實(shí)現(xiàn)的,就留給大家自行分析了。

4. 相關(guān)參考

-《Linux程序設(shè)計(jì)》,6,7.1 章節(jié)

-《C primer plus》,11,12 章節(jié)

-《C 和指針》,9 章節(jié)

-《Linux 系統(tǒng)編程》,9 章節(jié)

-《C專家編程》,7.5 章節(jié)

-《C和C++程序員面試秘笈》,4 章節(jié)


-END-


本文授權(quán)轉(zhuǎn)載自嵌入式Hacker,作者:吳偉東Jack




推薦閱讀



【01】2020年頂級(jí)編程語言
【02】國內(nèi)為什么寫不出操作系統(tǒng)和編程語言?
【03】單片機(jī)編程技術(shù)學(xué)習(xí)攻略
【04】終于有人講清楚了!關(guān)于編程語言的那些事兒
【05】編程能力的4種境界,你到哪一級(jí)了?


免責(zé)聲明:整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系刪除

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉