vsnprintf() 将可变参数格式化输出到字符数组

vsnprintf{} 将可变参数格式化输出到一个字符数组

  • 1. function `vsnprintf()`
    • 1.1. `const int num_bytes = vsnprintf(NULL, 0, format, arg);`
  • 2. Parameters
  • 3. Return value
  • 4. Example
  • 5. llama.cpp
  • References

1. function vsnprintf()

https://cplusplus.com/reference/cstdio/vsnprintf/

int vsnprintf(char *target_str, size_t n, const char *format, va_list arg);

Write formatted data from variable argument list to sized buffer

Composes a string with the same text that would be printed if format was used on printf, but using the elements in the variable argument list identified by arg instead of additional function arguments and storing the resulting content as a C string in the buffer pointed by target_str (taking n as the maximum buffer capacity to fill).
使用在 printf 上使用 format 时打印的相同文本组成一个字符串,但使用 arg 标识的变量参数列表中的元素而不是额外的函数参数,并将结果内容作为 C 字符串存储在 target_str 指向的缓冲区中 (以 n 作为要填充的最大缓冲区容量)。

If the resulting string would be longer than n - 1 characters, the remaining characters are discarded and not stored, but counted for the value returned by the function.
如果结果字符串长度超过 n - 1 个字符,则剩余字符将被丢弃并且不被存储,但计入函数返回的值。

#include <stdarg.h>
#include <stdio.h>

void formatted_data(char *str, char *fmt, ...);

int main(void) {
	char str[256];

	formatted_data(str, "%s-%s-%s\n", "Yong", "Qiang", "Cheng");
	printf("The string: %s\n", str);

	return 0;
}

void formatted_data(char *str, char *fmt, ...) {
	va_list arg_ptr;
	va_start(arg_ptr, fmt);
	const int num_bytes = vsnprintf(str, 10, fmt, arg_ptr);
	va_end(arg_ptr);

	printf("The number of bytes: %d\n", num_bytes);
}
The number of bytes: 17
The string: Yong-Qian
请按任意键继续. . .

Internally, the function retrieves arguments from the list identified by arg as if va_arg() was used on it, and thus the state of arg is likely to be altered by the call.
在内部,该函数从 arg 标识的列表中检索参数,就好像在其上使用 va_arg() 一样,因此 arg 的状态可能会因调用而改变。

In any case, arg should have been initialized by va_start() at some point before the call, and it is expected to be released by va_end() at some point after the call.
无论如何,arg 应该在调用之前的某个时间点由 va_start() 初始化,并且预计在调用之后的某个时间点由 va_end() 释放。

1.1. const int num_bytes = vsnprintf(NULL, 0, format, arg);

int vsnprintf(char *target_str, size_t n, const char *format, va_list arg);

const int num_bytes = vsnprintf(NULL, 0, format, arg);

At most n - 1 characters are written. The resulting character string will be terminated with a null character, unless n is zero.
最多写入 n - 1 个字符。除非 n 为零,否则生成的字符串将以空字符 (\0) 结尾。

If n is zero, nothing is written and target_str may be a null pointer, however the return value (number of bytes that would be written not including the null terminator) is still calculated and returned.
如果 n 为零,则不会写入任何内容,并且 target_str 可能为空指针,但是仍会计算并返回值 (不包括空终止符的写入字节数)。

#include <iostream>
#include <cstdarg>
#include <vector>

std::string string_format(const char *format, ...) {
	va_list ap1;
	va_list ap2;
	va_start(ap1, format);
	va_copy(ap2, ap1);
	const int size1 = vsnprintf(NULL, 0, format, ap1);

	std::vector<char> buf(size1 + 1);
	const int size2 = vsnprintf(buf.data(), size1 + 1, format, ap2);

	std::cout << "size1=" << size1 << ", size2=" << size2 << std::endl;
	std::cout << "buf: " << buf.data() << std::endl;

	va_end(ap2);
	va_end(ap1);
	return std::string(buf.data(), size1);
}

int main() {
	const std::string batch = string_format("logical maximum batch size (default: %d)", 9);
	std::cout << batch.c_str() << std::endl << std::endl;

	const std::string ubatch = string_format("physical maximum batch size (default: %d)", 16);
	std::cout << ubatch.c_str() << std::endl;

	return 0;
}

在这里插入图片描述

2. Parameters

  • target_str

Pointer to a buffer where the resulting C-string is stored.

The buffer should have a size of at least n characters.

  • n

Maximum number of bytes to be used in the buffer.

The generated string has a length of at most n - 1, leaving space for the additional terminating null character.
生成的字符串的长度最多为 n - 1,为额外的终止空字符留出空间。vsnprintf() 要在结果的末尾追加 \0

size_t is an unsigned integral type.

  • format

C string that contains a format string that follows the same specifications as format in printf (see printf for details).

  • arg

A value identifying a variable arguments list initialized with va_start().

va_list is a special type defined in <cstdarg>.

3. Return value

The vsnprintf() function returns the number of bytes that are written in the array, not counting the ending null character.
vsnprintf() 函数返回写入数组的字节数,不计算结尾的空字符。

The number of characters that would have been written if n had been sufficiently large, not counting the terminating null character.
写入的字符数,不包括终止空字符。

If an encoding error occurs, a negative number is returned.

Notice that only when this returned value is non-negative and less than n, the string has been completely written.
注意,只有当这个返回值非负且小于 n 时,字符串才被完全写入。

#include <stdarg.h>
#include <stdio.h>

void formatted_data(char *str, char *fmt, ...);

int main(void) {
	char str[256];

	formatted_data(str, "%s-%s-%s\n", "Yong", "Qiang", "Cheng");
	printf("The string: %s\n", str);

	return 0;
}

void formatted_data(char *str, char *fmt, ...) {
	va_list arg_ptr;
	va_start(arg_ptr, fmt);
	const int num_bytes = vsnprintf(str, 64, fmt, arg_ptr);
	va_end(arg_ptr);

	printf("The number of bytes: %d\n", num_bytes);
}
The number of bytes: 17
The string: Yong-Qiang-Cheng

请按任意键继续. . .

The number of characters written if successful or negative value if an error occurred. If the resulting string gets truncated due to n limit, function returns the total number of characters (not including the terminating null-byte) which would have been written, if the limit was not imposed.
如果成功则返回写入的字符数,如果发生错误则返回负值。如果结果字符串由于 n 限制而被截断,则函数返回在未施加限制的情况下应写入的总字符数 (不包括终止空字节)。

  • 如果没有截断,则返回成功打印到 target_str 中的字符个数,字符个数不包括末尾追加的 \0
  • 如果发生截断,则返回不限制打印字符数量的情况下可以写入的字符个数,字符个数不包括末尾追加的 \0
  • 如果格式化解析失败,则返回负数。

4. Example

#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <stdio.h>
#include <stdarg.h>

void PrintError(const char *format, ...) {
	char buffer[256];

	va_list args;
	va_start(args, format);
	const int num_bytes = vsnprintf(buffer, 256, format, args);
	printf("The number of bytes: %d\n", num_bytes);
	perror(buffer);
	va_end(args);
}

int main() {
	char FileName[] = "qiang.txt";

	FILE *file_ptr = fopen(FileName, "r");
	if (NULL == file_ptr) {
		PrintError("Open %s", FileName);
	}
	else {
		// file successfully open
		fclose(file_ptr);
	}

	return 0;
}

在这里插入图片描述

5. llama.cpp

https://github.com/ggerganov/llama.cpp

/home/yongqiang/llm_work/llama_cpp_25_01_05/llama.cpp/src/llama-arch.cpp

#include <iostream>
#include <cstdarg>
#include <vector>

std::string format(const char *fmt, ...) {
	va_list ap1;
	va_list ap2;
	va_start(ap1, fmt);
	va_copy(ap2, ap1);
	const int size1 = vsnprintf(NULL, 0, fmt, ap1);

	std::vector<char> buf(size1 + 1);
	const int size2 = vsnprintf(buf.data(), size1 + 1, fmt, ap2);

	std::cout << "size1=" << size1 << ", size2=" << size2 << std::endl;
	std::cout << "buf: " << buf.data() << std::endl;

	va_end(ap2);
	va_end(ap1);

	return std::string(buf.data(), size1);
}

int main() {
	const std::string output_norm = format("output_norm", 1, 2);
	std::cout << output_norm.c_str() << std::endl << std::endl;

	const std::string attn_q = format("blk.%d.attn_q", 3, 4);
	std::cout << attn_q.c_str() << std::endl << std::endl;

	const std::string ffn_down = format("blk.%d.ffn_down.%d", 5, 6);
	std::cout << ffn_down.c_str() << std::endl << std::endl;

	const std::string ffn_up = format("blk.%d.ffn_up.%d", 7, 8);
	std::cout << ffn_up.c_str() << std::endl << std::endl;

	return 0;
}

在这里插入图片描述

References

[1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/
[2] vsnprintf() - Print Argument Data to Buffer, https://www.ibm.com/docs/en/i/7.5?topic=functions-vsnprintf-print-argument-data-buffer

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962766.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins未在第一次登录后设置用户名,第二次登录不进去怎么办?

Jenkins在第一次进行登录的时候&#xff0c;只需要输入Jenkins\secrets\initialAdminPassword中的密码&#xff0c;登录成功后&#xff0c;本次我们没有修改密码&#xff0c;就会导致后面第二次登录&#xff0c;Jenkins需要进行用户名和密码的验证&#xff0c;但是我们根本就没…

【Arxiv 大模型最新进展】TOOLGEN:探索Agent工具调用新范式

【Arxiv 大模型最新进展】TOOLGEN&#xff1a;探索Agent工具调用新范式 文章目录 【Arxiv 大模型最新进展】TOOLGEN&#xff1a;探索Agent工具调用新范式研究框图方法详解 作者&#xff1a;Renxi Wang, Xudong Han 等 单位&#xff1a;LibrAI, Mohamed bin Zayed University o…

数据库内存与Buffer Pool

数据库内存与Buffer Pool 文章目录 数据库内存与Buffer Pool一&#xff1a;MySQL内存结构1&#xff1a;MySQL工作组件2&#xff1a;工作线程的本地内存3&#xff1a;共享内存区域4&#xff1a;存储引擎缓冲区 二&#xff1a;InnoDB的核心&#xff1a;Buffer Pool1&#xff1a;数…

[CVPR 2022]Cross-view Transformers for real-time Map-view Semantic Segmentation

论文网址&#xff1a;Cross-View Transformers for Real-Time Map-View Semantic Segmentation 论文代码&#xff1a;cross_view_transformers/cross_view_transformer at master bradyz/cross_view_transformers GitHub 英文是纯手打的&#xff01;论文原文的summarizing …

Java 中线程的使用

文章目录 Java 线程1 进程2 线程3 线程的基本使用&#xff08;1&#xff09;继承 Thread 类&#xff0c;重写 run 方法&#xff08;2&#xff09;实现 Runnable 接口&#xff0c;重写 run 方法&#xff08;3&#xff09;多线程的使用&#xff08;4&#xff09;线程的理解&#…

手撕Vision Transformer -- Day1 -- 基础原理

手撕Vision Transformer – Day1 – 基础原理 目录 手撕Vision Transformer -- Day1 -- 基础原理Vision Transformer (ViT) 模型原理1. Vit 网络结构图2. 背景3. 模型架构3.1 图像切块&#xff08;Patch Embedding&#xff09;3.2 添加位置编码&#xff08;Positional Encoding…

【AI】DeepSeek 概念/影响/使用/部署

在大年三十那天&#xff0c;不知道你是否留意到&#xff0c;“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注&#xff0c;出于学习的兴趣&#xff0c;我深入研究了一番&#xff0c;才有了这篇文章的诞生。 概念 那么&#xff0c;什么是DeepSeek&#xff1f;首先百…

Java锁自定义实现到aqs的理解

专栏系列文章地址&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标&#xff1a; 理解锁&#xff0c;能自定义实现锁通过自定义锁的实现复习Thread和Object的相关方法开始尝试理解Aqs, 这样后续基于Aqs的的各种实现将能更好的理解 目录 锁的…

html的字符实体和颜色表示

在HTML中&#xff0c;颜色可以通过以下几种方式表示&#xff0c;以下是具体的示例&#xff1a; 1. 十六进制颜色代码 十六进制颜色代码以#开头&#xff0c;后面跟随6个字符&#xff0c;每两个字符分别表示红色、绿色和蓝色的强度。例如&#xff1a; • #FF0000&#xff1a;纯红…

Golang 并发机制-1:Golang并发特性概述

并发是现代软件开发中的一个基本概念&#xff0c;它使程序能够同时执行多个任务&#xff0c;从而提高效率和响应能力。在本文中&#xff0c;我们将探讨并发性在现代软件开发中的重要性&#xff0c;并深入研究Go处理并发任务的独特方法。 并发的重要性 增强性能 并发在提高软…

three.js用粒子使用canvas生成的中文字符位图材质

three.js用粒子使用canvas生成中文字符材质 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Three.…

《逆向工程核心原理》第三~五章知识整理

查看上一章节内容《逆向工程核心原理》第一~二章知识整理 对应《逆向工程核心原理》第三章到第五章内容 小端序标记法 字节序 多字节数据在计算机内存中存放的字节顺序分为小端序和大端序两大类 大端序与小端序 BYTE b 0x12; WORD w 0x1234; DWORD dw 0x12345678; cha…

2025年数学建模美赛 A题分析(4)楼梯使用人数模型

2025年数学建模美赛 A题分析&#xff08;1&#xff09;Testing Time: The Constant Wear On Stairs 2025年数学建模美赛 A题分析&#xff08;2&#xff09;楼梯磨损分析模型 2025年数学建模美赛 A题分析&#xff08;3&#xff09;楼梯使用方向偏好模型 2025年数学建模美赛 A题分…

【cocos creator】【模拟经营】餐厅经营demo

下载&#xff1a;【cocos creator】模拟经营餐厅经营

29.Word:公司本财年的年度报告【13】

目录 NO1.2.3.4 NO5.6.7​ NO8.9.10​ NO1.2.3.4 另存为F12&#xff1a;考生文件夹&#xff1a;Word.docx选中绿色标记的标题文本→样式对话框→单击右键→点击样式对话框→单击右键→修改→所有脚本→颜色/字体/名称→边框&#xff1a;0.5磅、黑色、单线条&#xff1a;点…

高性能消息队列Disruptor

定义一个事件模型 之后创建一个java类来使用这个数据模型。 /* <h1>事件模型工程类&#xff0c;用于生产事件消息</h1> */ no usages public class EventMessageFactory implements EventFactory<EventMessage> { Overridepublic EventMessage newInstance(…

neo4j初识

文章目录 一 图论基础二 柯尼斯堡七桥问题2.1 问题背景2.2 欧拉的解决3.1 核心概念3.2 核心优势3.3 应用场景3.4 技术特性3.5 版本与部署3.6 示例&#xff1a;社交关系查询3.7 限制与考量 四 图论与 Neo4j 的关联4.1 数据建模4.2 高效遍历4.3 应用场景 五 示例&#xff1a;用 N…

吴恩达深度学习——超参数调试

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 超参数调试调试选择范围 Batch归一化公式整合 Softmax 超参数调试 调试 目前学习的一些超参数有学习率 α \alpha α&#xff08;最重要&#xff09;、动量梯度下降法 β \bet…

行业规范要当作业务实体画出来吗

第五元素 总觉得这些没有逻辑的实体&#xff0c;在绘制的时候不应该绘出来&#xff0c;他们没有责任啊。 比如以下:查阅规范 感觉不太对 UMLChina潘加宇 你这个规范是一个电脑系统还是一本书 第五元素 是书 UMLChina潘加宇 书没有智能&#xff0c;唯一暴露的接口是“翻”…

冯·诺依曼体系结构

目录 冯诺依曼体系结构推导 内存提高冯诺依曼体系结构效率的方法 你使用QQ和朋友聊天时&#xff0c;整个数据流是怎么流动的&#xff08;不考虑网络情况&#xff09; 与冯诺依曼体系结构相关的一些知识 冯诺依曼体系结构推导 计算机的存在就是为了解决问题&#xff0c;而解…