我是靠谱客的博主 无情板栗,这篇文章主要介绍881@ snprintf函数使用总结,现在分享给大家,希望可以做个参考。

一:理论分析 snprintf。

参考案例:

https://blog.csdn.net/singledevil0/article/details/126344677?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126344677%22%2C%22source%22%3A%22singledevil0%22%7Dhttps://blog.csdn.net/singledevil0/article/details/126344677?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126344677%22%2C%22source%22%3A%22singledevil0%22%7D

snprintf和sprintf区别分析_喜欢打篮球的普通人的博客-CSDN博客_sprintf和snprintf的区别

【依赖头文件】

#include<stdio.h>

【函数原型】

int snprintf(char *str, size_t size, const char *format, …);

【函数参数】

str:目标字符串;size:拷贝字节数(Bytes); format:源字符串; …格式

【函数功能】

最多从源字符串format中拷贝size字节的内容(含字符串结尾标志’’)到目标字符串

The functions snprintf() write at most size bytes (including the terminating null byte (’’)) to str.

【返回值】

成功返回源串的长度(strlen, 不含’’)

失败返回负值

【例子及理解】

由于最多拷贝size个字节到目标字符串,那么通常目标字符串就设置成size大小就不会有越界问题

下面将目标字符串的长度设置为size大小,分别实验源串长度小于,等于,大于size的情况

【情形一】:源串小于目标字符串

实际上源串为:“123”,所以只将字符’1’,‘2’,‘3’, '’ 拷到了目标串, 返回值为源串的strlen为3

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1 #include <stdio.h> 2 #include <strings.h> 3 #include <string.h> 4 int main(void) 5 { 6 char a[10] = {''}; 7 int i = 0; 8 int ret = 0; 9 memset(a, 1, sizeof(a)); 10 for(i = 0; i < 10; i++) 11 { 12 printf("a[%d] = %dn",i,a[i]); 13 } 14 15 ret = snprintf(a, 10, "%d", 123); 16 printf("ret = %dn",ret); 17 18 for(i = 0; i < 10; i++) 19 { 20 printf("a[%d] = %dn",i,a[i]); 21 } 22 return 0; 23 }
复制代码
1
2
3
root@ubuntu:/shiyan/shiyan265# gcc snprintf.c root@ubuntu:/shiyan/shiyan265# ./a.out
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
a[0] = 1 a[1] = 1 a[2] = 1 a[3] = 1 a[4] = 1 a[5] = 1 a[6] = 1 a[7] = 1 a[8] = 1 a[9] = 1 ret = 3 a[0] = 49 a[1] = 50 a[2] = 51 a[3] = 0 a[4] = 1 a[5] = 1 a[6] = 1 a[7] = 1 a[8] = 1 a[9] = 1 root@ubuntu:/shiyan/shiyan265#

%d 打印格式,所以会把 1/2/3 拆分,最终输出的是 ASCII 码,

十进制的格式,所以1对应49 以此类推: 

【情形二】:源串等于目标字符串

源串为"abcdefghi", 正好将源串拷贝到目标字符串中,返回值为源串的strlen为9

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1 #include <stdio.h> 2 #include <strings.h> 3 #include <string.h> 4 int main(void) 5 { 6 char a[10] = {''}; 7 int i = 0; 8 int ret = 0; 9 memset(a, 1, sizeof(a)); 10 for(i = 0; i < 10; i++) 11 { 12 printf("a[%d] = %dn",i,a[i]); 13 } 14 15 //ret = snprintf(a, 10, "%d", 123); 16 ret = snprintf(a, 10, "%s","abcdefghi"); 17 printf("ret = %dn",ret); 18 19 for(i = 0; i < 10; i++) 20 { 21 printf("a[%d] = %dn",i,a[i]); 22 } 23 return 0;
复制代码
1
2
3
root@ubuntu:/shiyan/shiyan265# gcc snprintf.c root@ubuntu:/shiyan/shiyan265# ./a.out
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a[0] = 1 a[1] = 1 a[2] = 1 a[3] = 1 a[4] = 1 a[5] = 1 a[6] = 1 a[7] = 1 a[8] = 1 a[9] = 1 ret = 9 a[0] = 97 a[1] = 98 a[2] = 99 a[3] = 100 a[4] = 101 a[5] = 102 a[6] = 103 a[7] = 104 a[8] = 105 a[9] = 0 root@ubuntu:/shiyan/shiyan265#

【情形三】源串大于目标字符串

源串为"abcdefghijklmnopq",最多从源串拷贝10个字节(含)到目标串那么就是拷贝源串的9个字节内容(abcdefghi)再加一个到目标串,

目标串的结果和情形二一样,但是ret返回值变成了17, 即strlen(“abcdefghijklmnopq”)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1 #include <stdio.h> 2 #include <strings.h> 3 #include <string.h> 4 int main(void) 5 { 6 char a[10] = {''}; 7 int i = 0; 8 int ret = 0; 9 memset(a, 1, sizeof(a)); 10 for(i = 0; i < 10; i++) 11 { 12 printf("a[%d] = %dn",i,a[i]); 13 } 14 15 //ret = snprintf(a, 10, "%d", 123); 16 //ret = snprintf(a, 10, "%s","abcdefghi"); 17 ret = snprintf(a, 10, "%s", "abcdefghijklmnopq"); 18 printf("ret = %dn",ret); 19 20 for(i = 0; i < 10; i++) 21 { 22 printf("a[%d] = %dn",i,a[i]); 23 } 24 return 0; 25 }

复制代码
1
2
3
root@ubuntu:/shiyan/shiyan265# gcc snprintf.c root@ubuntu:/shiyan/shiyan265# ./a.out
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a[0] = 1 a[1] = 1 a[2] = 1 a[3] = 1 a[4] = 1 a[5] = 1 a[6] = 1 a[7] = 1 a[8] = 1 a[9] = 1 ret = 17 a[0] = 97 a[1] = 98 a[2] = 99 a[3] = 100 a[4] = 101 a[5] = 102 a[6] = 103 a[7] = 104 a[8] = 105 a[9] = 0 root@ubuntu:/shiyan/shiyan265#

=======================================================================

函数原型:int snprintf(char* dest_str,size_t size,const char* format,…);

所需头文件:#include<stdio.h>

函数功能:

先将可变参数 “…” 按照format的格式格式化为字符串,然后再将其拷贝至dest_str中。

注意事项:

如果格式化后的字符串长度小于size,则将字符串全部拷贝至dest_str中,并在字符串结尾处加上‘’;
如果格式化后的字符串长度大于或等于size,则将字符串的(size-1)拷贝至dest_str中,然后在字符串结尾处加上’’.
函数返回值是 格式化字符串的长度。

实例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void){ char dest_str[1024]; memset(dest_str,0,sizeof(dest_str)); char *s1 = "Linux C程序设计"; int size = strlen(s1); int year = 2017; int month = 9; int day = 8; snprintf(dest_str,sizeof(dest_str),"字符串:%sn长度是:%dn今天是:%d年%d月%d日n",s1,size,year,month,day); printf("%s",dest_str); return 0; }
复制代码
1
2
3
4
5
执行结果 字符串:Linux C程序设计 长度是:15 今天是:2017年9月8日

这个函数主要是在android hal 层中广泛用到。

%u 无符号十进制整数
%x 使用十六进制数字0f的无符号十六进制整数
%b 这个在基础阶段用不到,我也没试过,下面是我找的资料

%b 就是boolean的意思 以下是1.5 api中的解释
'b', 'B' 常规 如果参数 arg 为 null,则结果为 "false"。如果 arg 是一个 boolean 值或 Boolean,则结果为 String.valueOf() 返回的字符串。否则结果为 "true"。

二:案例剖析, snprintf 函数在  device_create_file  中的应用。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
DEVICE_ATTR是一个宏,其定义在 include/linux/device.h: #define DEVICE_ATTR(_name, _mode, _show, _store) struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) __ATTR宏定义在include/linux/sysfs.h: #define __ATTR(_name,_mode,_show,_store) { .attr = {.name = __stringify(_name), .mode = _mode }, .show = _show, .store = _store, } struct device_attribute结构定义在include/linux/device.h: /* interface for exporting device attributes */ struct device_attribute { struct attribute attr; ssize_t (*show)(struct device *dev, struct device_attribute *attr,char *buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr,const char *buf, size_t count); }; DEVICE_ATTR宏展开: #define DEVICE_ATTR(_name, _mode, _show, _store) struct device_attribute dev_attr_##_name = { .attr = {.name = __stringify(_name), .mode = _mode }, .show = _show, .store = _store, } 举例说明DEVICE_ATTR使用方法: static DEVICE_ATTR(msm_gpio, 0664, msmgpio_show, msmgpio_store); static ssize_t msmgpio_show(struct device *dev, struct device_attribute *attr, char *buf) { int temp[5]; struct gpio_data *gpio_data_ptr = dev_get_drvdata(dev); temp[0] = gpio_get_value(gpio_data_ptr->gpio0); temp[1] = gpio_get_value(gpio_data_ptr->gpio2); temp[2] = gpio_get_value(gpio_data_ptr->gpio3); temp[3] = gpio_get_value(gpio_data_ptr->gpio10); temp[4] = gpio_get_value(gpio_data_ptr->gpio11); return snprintf(buf, 6, "%d%d%d%d%d", temp[0], temp[1],temp[2], temp[3], temp[4]); } static ssize_t msmgpio_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct gpio_data *gpio_data_ptr = dev_get_drvdata(dev); gpio_set_value(gpio_data_ptr->gpio0, (buf[0] == '1') ? 1 : 0); gpio_set_value(gpio_data_ptr->gpio2, (buf[1] == '1') ? 1 : 0); gpio_set_value(gpio_data_ptr->gpio3, (buf[2] == '1') ? 1 : 0); gpio_set_value(gpio_data_ptr->gpio10, (buf[3] == '1') ? 1 : 0); gpio_set_value(gpio_data_ptr->gpio11, (buf[4] == '1') ? 1 : 0); return size; } static DEVICE_ATTR(msm_gpio, 0664, msmgpio_show, msmgpio_store); 之后在驱动的probe函数中即可调用device_create_file: err = device_create_file(&dev->dev, &dev_attr_msm_gpio); if (err) { dev_err(&dev->dev, "sys file creation failedn"); return -ENODEV; } device_create_file和device_remove_file 定义在drivers/base/core.c中,声明在include/linux/device.h中,device_create_file返回0代表创建成功。 int device_create_file(struct device *dev, const struct device_attribute *attr) { int error = 0; if (dev) { WARN(((attr->attr.mode & S_IWUGO) && !attr->store), "Attribute %s: write permission without 'store'n", attr->attr.name); WARN(((attr->attr.mode & S_IRUGO) && !attr->show), "Attribute %s: read permission without 'show'n", attr->attr.name); error = sysfs_create_file(&dev->kobj, &attr->attr); } return error; } void device_remove_file(struct device *dev, const struct device_attribute *attr) { if (dev) sysfs_remove_file(&dev->kobj, &attr->attr); } 在文件系统/sys/devices/soc.0/gpio_ctrl.72下面生成msm_gpio节点,用cat,echo操作硬件: root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # ls -l msm_gpio -rw-rw-r-- root root 4096 1970-01-01 00:02 msm_gpio root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # cat msm_gpio 00000 root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # echo 11111 > msm_gpio


 

三:案例解析:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
将SN号根据* 进行区分,然后打印出来规范的格式化数据: apaota_test open & init /lib64/libapa_ota.so success usage: apaota_test example: ./apaota_test [568] apa_get_software_version version_apa [full-SN] : CG019028 357 81875*704000604AA*00.02.00_13.00.03*9BJ* [579] apa_get_software_version sn: CG019028 357 81875 [585] apa_get_software_version part_number: 704000604AA [591] apa_get_software_version sf version: 00.02.00 [593] apa_get_software_version hw version: 13.00.03 [600] apa_get_software_version Supplier_number: 9BJ json: {"sn":"CG019028 357 81875","part_no":"704000604AA","vendor_id":"9BJ","calib_version":""} typedef struct { char slot_version[BUF_SIZE]; char boot_version[BUF_SIZE]; char soft_version[BUF_SIZE]; char hard_version[BUF_SIZE]; char vendor_id[BUF_SIZE]; char extra_info[BUF_SIZE]; }ecu_version_info; int main(int argc, char **argv) { char *libpath = "/lib64/libapa_ota.so"; unsigned char status; unsigned short x_axis; unsigned short y_axis; int ret = 0; apa_update_libapi_init_test(libpath); memset(&apa_cur_version, 0, sizeof(ecu_version_info)); if (argc == 1) { printf("usage: %s nexample: ./apaota_testn", argv[0]); if (apa_get_version_api_test != NULL) { ret = apa_get_version_api_test(0, &apa_cur_version); //printf("call apa_get_version_api_test api ret=%dn",ret); printf("json: %s", apa_cur_version.extra_info); } else { printf("call apa_get_version_api_test api = NULLn"); } return 0; } } int apa_get_software_version(int mode, ecu_version_info *version) { if(version == NULL) { printf("[%d] apa_get_software_versionn", __LINE__); return -1; } char sn[256] = { 0 }; char part_number[256] = { 0 }; char Supplier_number[256] = { 0 }; char calib_version[256]=""; unsigned char writebuf[APA_VER_NOTIFY_SIZE] = { 0 }; unsigned char readbuf[1024] = { 0 }; unsigned char version_apa[1024] = { 0 }; // char respbuf[APA_VER_RESP_SIZE] = {0}; int ret = 0; unsigned char crcval; unsigned int fixed_header = UART_FRAME_FIX_HEADER; unsigned short cmd_id = APA_VER_MESG_ID; char i = 0x00; unsigned char *last_pos = NULL, *pos = NULL, *underline_pos = NULL; int count = 0; memset(version, 0, sizeof(ecu_version_info)); ret = apaota_uart_init(); if (ret != 0) { printf("i2c init failn"); return -1; } apa_common_info_configure(&writebuf[0], fixed_header, cmd_id); writebuf[4] = 0x00; //framelen writebuf[5] = 0x0d; //framelen writebuf[6] = 0x01; //msg type writebuf[9] = 0x00; //msg size writebuf[10] = 0x01; //msg size writebuf[11] = 0x00; //msg priorty crcval = crcBBC((unsigned char *)&writebuf[0], sizeof(writebuf)); writebuf[12] = crcval; memset(readbuf, 0, 1024); ret = uart_transmit_msg_with_resp(writebuf, APA_VER_NOTIFY_SIZE, readbuf, 66); if (ret < 0) { printf("read err ret : %dn", ret); } #if 0 LOGE("uart_transmit_msg_with_resp cmd :"); for (i = 0; i < 66; i++) { LOGE("readbuf[%d] : 0x%xn", i, readbuf[i]); } LOGE("uart_transmit_msg_with_resp cmd end"); #endif memcpy(version_apa, &readbuf[12], readbuf[10]); printf("[%d] apa_get_software_versionn", __LINE__); printf("version_apa [full-SN] : %s n", version_apa); last_pos = version_apa; pos = version_apa; while(last_pos && pos) { pos = (unsigned char *)strchr((char*)last_pos, '*'); if(count == 0) //sn { memcpy(sn, last_pos, (pos - last_pos)); printf("[%d] apa_get_software_version sn: %sn", __LINE__, sn); } if(count == 1) //part_number { memcpy(part_number, last_pos, (pos - last_pos)); //memcpy(version->part_number, last_pos, (pos - last_pos)); printf("[%d] apa_get_software_version part_number: %sn", __LINE__, part_number); } else if(count == 2) // hardware/soft ware version { underline_pos = (unsigned char *)strchr((char *)last_pos, '_'); memcpy(version->soft_version, last_pos, (underline_pos - last_pos)); printf("[%d] apa_get_software_version sf version: %sn", __LINE__, version->soft_version); memcpy(version->hard_version, underline_pos + 1, (pos - underline_pos -1)); printf("[%d] apa_get_software_version hw version: %sn", __LINE__, version->hard_version); } else if(count == 3) // Supplier_number { memcpy(Supplier_number, last_pos, (pos - last_pos)); //memcpy(version->Supplier_number, last_pos, (pos - last_pos)); printf("[%d] apa_get_software_version Supplier_number: %sn", __LINE__, Supplier_number); } count++; last_pos = pos + 1; } //格式化串,按照具体的格式打印出来: snprintf(version->extra_info,sizeof(version->extra_info),"{"sn":"%s","part_no":"%s","vendor_id":"%s","calib_version":"%s"}",sn,part_number,Supplier_number,calib_version); // snprintf(version->vendor_id,sizeof(version->vendor_id),"{"sn":"%s","part_no":"%s","vendor_id":"%s","calib_version":"%s"}",sn,part_number,Supplier_number,calib_version); apaota_uart_deinit(); return 0; }

参考1: https://blog.csdn.net/liaojunwu/article/details/80489406
参考2: https://blog.csdn.net/qq_34707315/article/details/77895735

最后

以上就是无情板栗最近收集整理的关于881@ snprintf函数使用总结的全部内容,更多相关881@内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(71)

评论列表共有 0 条评论

立即
投稿
返回
顶部