[c]可变参数函数

#include <stdio.h>

#include <stdarg.h>

void logMessage(const char *pFormat, ...) {

// 定义一个 va_list 类型的变量 args 用于存储参数信息

va_list args;

// 初始化 args 指向第一个未命名参数

va_start(args, pFormat);

// 创建一个足够大的缓冲区来保存格式化后的字符串

char buffer1024;

// 使用 vsnprintf 格式化字符串并写入到 buffer 中

int len = vsnprintf(buffer, sizeof(buffer), pFormat, args);

if (len > -1 && len < sizeof(buffer)) {

// 如果 vsnprintf 成功并且没有被截断,则输出结果

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

} else {

// 处理错误情况(例如,缓冲区太小)

printf("Buffer too small or formatting error.\n");

}

// 清理工作

va_end(args);

}

int main() {

// 调用 logMessage 函数,它支持类似于 printf 的语法

logMessage("User %s logged in from IP: %s", "Alice", "192.168.1.1");

logMessage("Error code: %d, Message: %s", 404, "Not Found");

return 0;

}

  • **logMessage 函数**: 这是一个接受可变数量参数的函数,首先通过`va_start`初始化`args`,然后调用`vsnprintf`根据提供的格式化字符串和参数生成最终的消息。如果格式化成功且结果没有超出缓冲区大小限制,则使用`printf`输出结果。最后,通过`va_end`完成清理工作。

`vsnprintf` 是 C 标准库中的一个函数,用于格式化字符串并将其输出到一个指定的缓冲区。它与 `snprintf` 类似,但接收的是一个 `va_list` 类型的参数列表而不是直接使用省略号(...)。这使得它非常适合在实现支持可变参数列表的函数时使用。

函数原型

```c

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

```

参数解释

  1. **char *str**

目标缓冲区的指针,格式化后的字符串将被写入该缓冲区。如果 `size` 为零,则可以传递一个空指针,因为在这种情况下不会尝试写入数据,仅返回所需缓冲区大小。

  1. **size_t size**

指定目标缓冲区的最大字节数(包括结尾的空字符 `\0`)。这意味着函数最多会写入 `size - 1` 个字符到 `str` 中,并确保 `str` 以空字符结束。如果格式化后的字符串长度超过了 `size - 1`,则会被截断。

  1. **const char *format**

格式化字符串,包含文本和嵌入的格式说明符(如 `%d` 表示整数,`%s` 表示字符串等)。这些说明符将被后续提供的参数替换。

  1. **va_list ap**

这是一个指向参数列表的指针,包含了所有按照 `format` 中的说明符顺序排列的额外参数。这个参数通常通过 `va_start` 初始化,并且在调用 `vsnprintf` 后应该调用 `va_end` 来清理。

返回值

  • 如果成功并且没有发生截断,则返回写入到 `str` 的字符数(不包括结尾的空字符)。

  • 如果由于缓冲区大小不足而发生截断,则返回将会写入的字符总数(假设没有大小限制),以便你可以知道需要多大的缓冲区来存储完整的格式化字符串。

  • 如果发生错误,返回负值。

使用场景

`vsnprintf` 常用于实现自定义的格式化输出函数,特别是那些需要处理不确定数量参数的情况。例如,构建自己的日志记录函数或调试信息打印函数时非常有用。

示例代码片段

以下是一个简单的例子,演示了如何使用 `vsnprintf`:

```c

#include <stdio.h>

#include <stdarg.h>

void logMessage(const char *format, ...) {

char buffer1024;

va_list args;

va_start(args, format);

int len = vsnprintf(buffer, sizeof(buffer), format, args);

va_end(args);

if (len > -1 && len < sizeof(buffer)) {

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

} else {

printf("Error: Buffer too small or formatting error.\n");

}

}

int main() {

logMessage("User %s logged in from IP: %s", "Alice", "192.168.1.1");

logMessage("Error code: %d, Message: %s", 404, "Not Found");

return 0;

}

```

相关推荐
Tri_Function2 分钟前
简单图论大学习
c++
lqqjuly28 分钟前
C++ 完整知识体系—从基础语法到现代 C++23 的系统性总结
c++·c++23
王老师青少年编程1 小时前
信奥赛C++提高组csp-s之FHQ Treap
c++·csp·平衡树·信奥赛·csp-s·提高组·fhq treap
QiLinkOS3 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
Irissgwe3 小时前
c++STL--string类
c++·stl·string
Irissgwe3 小时前
c++类型转换
c++·类型转换·explicit·static_cast·const_cast·dynamic_cast·rtti
智者知已应修善业3 小时前
【51单片机用T0定时器方式1,实现0.5S的时间间隔实现第一次一个灯亮、第二次二个灯亮,直到全部灯亮,然后重复整个过程】2023-12-29
c++·经验分享·笔记·算法·51单片机
社交怪人4 小时前
【范围判断】信息学奥赛一本通C语言解法(题号2052)
c语言
智者知已应修善业4 小时前
【51单片机4位静态数码管显示1234】2023-11-14
c++·经验分享·笔记·算法·51单片机
抓虾爪4 小时前
ST意法代理商粤科源兴丨LSM6DS3全系列现货库存,LSM6DS3TR-C当天可发
c++