我是靠谱客的博主 无情板栗,最近开发中收集的这篇文章主要介绍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 #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 }
root@ubuntu:/shiyan/shiyan265# gcc snprintf.c
root@ubuntu:/shiyan/shiyan265# ./a.out
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 #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;
root@ubuntu:/shiyan/shiyan265# gcc snprintf.c
root@ubuntu:/shiyan/shiyan265# ./a.out

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

root@ubuntu:/shiyan/shiyan265# gcc snprintf.c
root@ubuntu:/shiyan/shiyan265# ./a.out

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中,然后在字符串结尾处加上’’.
函数返回值是 格式化字符串的长度。

实例:

#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;
}
执行结果
字符串: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  中的应用。

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


 

三:案例解析:

将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@ snprintf函数使用总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部