c语言第三方字符串库,【开源共享】拿来即用的C语言字符串函数库

一、字符串函数库:Simple Dynamic Strings

1. 简介

Simple Dynamic Strings (简称 SDS) 是一个 C 语言字符串库,它增强了 C 语言字符串处理的能力。

设计 SDS 原本是为了满足设计者自身日常的 C 编程,后来又被转移到 Redis 中,在 Redis 中被广泛使用并对其进行了修改以适合于高性能操作。现在,它又被从 Redis 中提取出来的,并 fork 为一个独立项目。

只有 1500 行不到的代码,就能做到 3.2K 个 star,牛牛牛~~~

它有什么优点?

使用更简单;

二进制安全;

效率更高;

与 C 字符串函数兼容;

源码链接:

https://github.com/antirez/sds

源码文件:

sds.c

sdsalloc.h

sds.h

testhelp.h

相关 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)

1. 比较常用的功能

1.1 创建字符串

sdsnew() 和 sdsfree():

#include 

#include "sds.h"

#include "sdsalloc.h"

int main(void){

sds mystr = sdsnew("Hello World!");

printf("%s\n", mystr);

sdsfree(mystr);

}

运行效果:

$gcc -o sdsdemo sds.c sdsdemo.c

$./sdsdemo

Hello World!

看到了吗?

printf 直接就可以打印 sds,这就是说 sds 本身就是 C 语言的字符串类型。

sds 的定义如下:

typedef char *sds;

也就是说,sds 是能兼容 libc 里字符串处理函数 (例如strcpy, strcat...)的。

当不再使用 sds 字符串时,就算是空串,也要通过 sdsfree 销毁字符串。

1.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));

}

运行效果:

$./sdsdemo

ABC of len 3

和 strlen() 有 2 点不同:

运行时长固定,sds 内部有数据结构保存着字符串的长度;

长度与字符串内是否有 NULL 无关;

1.3 拼接字符串

sdscat():

int main(void){

sds s = sdsempty();

s = sdscat(s, "Hello ");

s = sdscat(s, "World!");

printf("%s\n", s);

}

运行效果:

$./sdsdemo

Hello World!

sdscat 接受的参数是以 NULL 结尾的字符串,如果想摆脱这个限制,可以用 sdscatsds()。

sdscatsds():

int main(void){

sds s1 = sdsnew("aaa");

sds s2 = sdsnew("bbb");

s1 = sdscatsds(s1,s2);

sdsfree(s2);

printf("%s\n", s1);

}

运行效果:

$./sdsdemo

aaabbb

1.4 扩展字符串长度

sdsgrowzero():

int main(void){

sds s = sdsnew("Hello");

s = sdsgrowzero(s,6);

s[5] = '!'; /* We are sure this is safe*/

printf("%s\n", s);

}

运行效果:

$./sdsdemo

Hello!

1.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);

}

运行效果:

$./sdsdemo

The sum is: 10+20 = 30

1.6 截取字符串

sdstrim():去掉指定字符

int main(void){

sds s = sdsnew("         my string\n\n  ");

sdstrim(s," \n");

printf("-%s-\n",s);

}

运行效果:

$./sdsdemo

-my string-

去掉了空格和换行符。

sdsrange():截取指定范围内的字符串

int main(void){

sds s = sdsnew("Hello World!");

sdsrange(s,1,4);

printf("-%s-\n", s);

}

运行效果:

$./sdsdemo

-ello-

1.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 

printf("%s\n", tokens[j]);

sdsfreesplitres(tokens,count);

}

sdssplitlen() 第 3和4 个参数指定分割符为空格。

运行效果:

$./sdsdemo

Hello

World!

1.8 字符串合并 (String joining)

sdssplitlen() 和 sdsfreesplitres():

int main(void){

char *tokens[3] = {"foo","bar","zap"};

sds s = sdsjoin(tokens, 3, "|");

printf("%s\n", s);

}

运行效果:

$./sdsdemo

foo|bar|zap

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

2. 简单了解一下内部实现

在 SDSD 中,使用二进制前缀(头部) 来保存字符串相关的信息,该头部存储在 SDS 返回给用户的字符串的实际指针之前:

+--------+-------------------------------+-----------+

| Header | Binary safe C alike string... | Null term |

+--------+-------------------------------+-----------+

|

`-> Pointer returned to the user.

这个 Header 在代码中用结构体来描述,该结构体定义大致如下:

struct sdshdr {

[...]

int len;

char buf[];

};

len 存储的是字符串长度;

假设你使用的字符串为 "HELLOWORLD",为了提升效率,SDS 可能会提前分配多一些空间,所以实际的内存布局如下:

+------------+------------------------+-----------+---------------\

| len | buf | H E L L O W O R L D \n | Null term |  Free space   \

+------------+------------------------+-----------+---------------\

|

`-> Pointer returned to the user.

现在,我们来看一下 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 个字节的空间

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';          // 总是添加一个 NULL

return s;                   // 返回 C string

其他的 SDS API 是如何实现的,就留给大家自行分析了。

3. 相关参考

-《Linux程序设计》,6,7.1 章节

-《C primer plus》,11,12 章节

-《C 和指针》,9 章节

-《Linux 系统编程》,9 章节

-《C专家编程》,7.5 章节

-《C和C++程序员面试秘笈》,4 章节

推荐阅读:

wz_5jWbbaHpinM.html

wz_5jWbbaHpinM.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Windows C 语言中使用 MQTT 推送 JSON 字符串,可以使用开源的 mqtt-c 客户端。具体步骤如下: 1. 安装 mqtt-c 可以在 mqtt-c 的 GitHub 页面下载最新的 release 版本,将其中的 `include` 和 `lib` 文件夹拷贝到你的项目中,并在 Visual Studio 中配置 include 路径和链接。 2. 连接 MQTT 服务器 使用 `mqtt_client_new` 函数创建 MQTT 客户端,然后使用 `mqtt_connect` 函数连接 MQTT 服务器。例如: ```c mqtt_client_t* client = mqtt_client_new(); mqtt_connect(client, "localhost", 1883, 60); ``` 其中,`localhost` 和 `1883` 分别为 MQTT 服务器的地址和端口号,`60` 表示连接超时时间(单位为秒)。 3. 发布 JSON 字符串 使用 `mqtt_publish` 函数发布 JSON 字符串。例如: ```c char* json_str = "{\"name\": \"John\", \"age\": 30}"; mqtt_publish(client, "topic", json_str, strlen(json_str), 0, 0); ``` 其中,`"topic"` 为要发布到的主题,`json_str` 为 JSON 字符串的指针,`strlen(json_str)` 为字符串长度,`0` 表示 QoS 等级为 0,`0` 表示不保留消息。 4. 断开 MQTT 连接 使用 `mqtt_disconnect` 函数断开 MQTT 连接,然后使用 `mqtt_client_destroy` 函数销毁 MQTT 客户端。例如: ```c mqtt_disconnect(client); mqtt_client_destroy(&client); ``` 完整的代码如下: ```c #include <stdio.h> #include <string.h> #include "mqtt.h" int main() { mqtt_client_t* client = mqtt_client_new(); mqtt_connect(client, "localhost", 1883, 60); char* json_str = "{\"name\": \"John\", \"age\": 30}"; mqtt_publish(client, "topic", json_str, strlen(json_str), 0, 0); mqtt_disconnect(client); mqtt_client_destroy(&client); return 0; } ``` 注意,在使用 `mqtt_publish` 函数时,需要确保 JSON 字符串的格式正确,否则可能会导致消息无法正常传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值