C/C++ 不定参函数

news2024/9/20 7:58:31

C语言不定参函数

函数用法总结

Va_list 

  • 作用:类型定义,生命一个变量,该变量被用来访问传递给不定参函数的可变参数列表
  • 用法:供后续函数进调用,通过该变量访问参数列表
typedefchar* va_list;

 va_start

  • 作用:初始化va_list变量,指向可变参数列表中的第一个参数,这个宏需要知道最后一个固定参数的位置,方便从其后开始读取可变参数
  • 参数:ap(初始化的va_list变量)、last_artg(确定从哪里开始读取可变参数4)
voidva_start(va_list ap, last_arg);

va_arg

  • 作用:va_arg宏用于获取可变参数列表中的下一个参数,并将其转换为指定的类型
  • 参数:ap,type指定要获取的参数类型 
  • 返回值:返回指定类型的下一个参数值,并将va_list 变量指向下一个参数
type va_arg(va_list ap, type);

 va_end

  • 作用:用于清理va_list变量
  • 参数:ap需要清理的va_list变量
voidva_end(va_list ap);

使用事例 

使用事例

  • 至少定义一个固定参数的函数,然后后面的参数使用... 表示
  • va_list args:定义一个变量,用于存储不定参数的列表
  • va_start(args, fixeArg):初始化args,并让其指向可变参数列表的开始;fixeArg则是最后一个固定参数,用于确定从哪里开始寻找可变参数
  • va_arg(args,int):获取当前参数,类型设置为int,并将指针移动到下一个参数
  • va_end(args):清理va_list,结束不定参数的获取

#include<stdarg.h>
#include <stdio.h>
// 定义一个不定参函数
void exampleFunction(int fixedArg, ...)
{
va_list args;
va_start(args, fixedArg);

// 获取不定参
int nextArg;
while ((nextArg = va_arg(args, int)) != 0)
{
    printf("Argument: %d\n", nextArg);
}

va_end(args);
}

int main()
{
    exampleFunction(1, 2, 3, 4, 5, 0); // 0作为终止条件
    return 0;
}

#include<iostream>
#include <cstdarg>
void printNum(int n, ...) 
{
    va_list al;
    va_start(al, n); // 让al指向n参数之后的第一个可变参数
    for (int i = 0; i < n; i++) 
    {
        int num = va_arg(al, int); // 从可变参数中取出一个整形参数
        std::cout << num << std::endl;
    }
    va_end(al); // 清空可变参数列表--其实是将al置空
}

int main() {
    printNum(3, 11, 22, 33); // 输出:11 22 33
    printNum(5, 44, 55, 66, 77, 88); // 输出:44 55 66 77 88
    return 0;
}

vasprintf函数

格式化输出写入一个动态分配字符串

  • char **strp:指向字符指针的指针,用于接收分配的内存的地址,vasprintf 会为存储格式化后的字符串动态分配内存,并将其地址存储在 *strp 中。调用者需要负责在使用完字符串后使用 free() 函数释放这块内存
  • const char *fmt:这是格式化字符串,类似于 printf 函数中的格式化字符串。它可以包含格式说明符(如 %d, %s 等),并且需要与后续的可变参数相匹配
  • va_list ap:这是一个 va_list 类型的变量,用于传递可变参数列表。它通常通过 va_start 宏初始化

返回值

  • 成功:返回生成字符串的长度
  • 失败:返回-1,同时将*strp设置成NULL
intvasprintf(char **strp, constchar *fmt, va_list ap);
  • 函数create_message:初始化变量ap,从fmt之后的参数开始获取可变参数
  • vasprintf:根据fmt中的格式化字符串,以及ap生成最终字符串,动态分配内存存储生成的字符串,并将其存储在strp中(将格式化字符格式和可变参数结合,生成固定格式的消息,存储在strp中)
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

int create_message(char **strp, const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    int result = vasprintf(strp, fmt, ap);
    va_end(ap);
    return result;
}

int main() {
    char *message;
    int length = create_message(&message, "Hello, %s! You have %d new messages.", "Alice", 5);

    if (length != -1) {
        printf("Generated string: %s\n", message);
        printf("String length: %d\n", length);
        free(message);  // 记得释放分配的内存
    } else {
        fprintf(stderr, "Memory allocation failed\n");
    }

    return 0;
}

//
Generated string: Hello, Alice! You have 5 new messages.
String length: 34

C++风格不定参

不定参宏实现日志功能

  • 宏定义:#define Log( fmt , ...):定义一个Log宏,该宏接受一个格式化字符串fmt,以及一个可变数量的附加参数
  • __FILE__和 __LINE__:预定义宏,当前源文件的文件名和行号
  • ##__VA_ARGS:宏的可变参数部分为空的时候,可以自动取出前面的逗号,避免语法错误

#include<iostream>
#include <cstdarg>
#define LOG(fmt, ...) printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)

int main()
{
	LOG("%s-%s", "hello", "世界");
	LOG("%s-%s", "hello", "中国");
	return 0;
}

实现C风格的不定参函数

基本与C语言风格相同

#include<iostream>
#include <cstdarg>
void printNumbers(int count, ...) 
{
    va_list args;
    va_start(args, count);  // 初始化 va_list 并将其指向 count 之后的第一个可变参数
    for (int i = 0; i < count; ++i) 
    {
        int num = va_arg(args, int);  // 逐个获取参数
        std::cout << num << " ";
    }
    va_end(args);  // 清理 va_list
    std::cout << std::endl;
}

int main() {
    printNumbers(3, 10, 20, 30);  // 输出: 10 20 30
    printNumbers(5, 1, 2, 3, 4, 5);  // 输出: 1 2 3 4 5
    return 0;
}

 C++11可变模版

通过递归模版展开

#include<iostream>
void print() {
std::cout << std::endl;  // 递归基例:什么都不做,只是结束递归
}

template<typename T, typename... Args>
    void print(T first, Args... args) {
    std::cout << first << " ";  // 打印第一个参数
    print(args...);  // 递归调用 print 处理剩余参数
}

int main() {
    print(1, 2.5, "Hello", 'c');  // 输出: 1 2.5 Hello c
    return 0;
}

C++17折叠表达式

#include<iostream>
template<typename... Args>
void print(Args... args) {
    (std::cout << ... << args) << std::endl;  // 使用折叠表达式展开参数包
}

int main() {
    print(1, 2.5, "Hello", 'c');  // 输出: 1 2.5 Hello c
    return 0;
}

ofstream

 专门用于文件输出操作,就是将数据写入文件fstreamstd::basic_ofstream 的一个实例化,std::basic_ofstream 是一个模板类,用于处理各种字符类型的文件输出。ofstream 专门处理 char 类型的文件

基本使用总结

文件打开关闭

  • ofstream对象可以利用自身构造或者open方法打开文件,文件只要被打开,程序就可以将数据写入文件
  • 程序结束或者该对象销毁的到时候,文件会自动关闭,也可以手动关闭文件,即调用close()方法
std::ofstream file("example.txt");
if (file.is_open()) {
    // 文件已成功打开,可以进行写入操作
}

写入数据

  • 支持向文件写入多种类型的数据
std::ofstream file("example.txt");
if (file.is_open()) {
    file << "Hello, World!" << std::endl;
    file << 123 << std::endl;
    file << 45.67 << std::endl;
}

 检查文件状态

  • is_open():检查文件是否成功打开
  • good():检查文件流是否处于有效状态
  • fail:检查是否出现了某种错误
std::ofstream file("example.txt");
if (!file) {
    std::cerr << "Failed to open the file." << std::endl;
}

文件模式

  • std::ios::out:默认模式,表示文件用于写入。
  • std::ios::app:追加模式,在文件末尾添加内容而不覆盖已有内容。
  • std::ios::trunc:清空文件内容(默认行为,如果文件已存在)。
  • std::ios::binary:以二进制模式打开文件,而非文本模式
std::ofstream file("example.txt", std::ios::app);

 自动资源管理

  • 内部是RAII模式管理文件资源,只要该对象超出作用域,文件就会自动关闭
{
    std::ofstream file("example.txt");
    file << "This will be written to the file." << std::endl;
} // file 对象超出作用域,文件自动关闭

ifstream

标准库中的一个类,属于 <fstream> 头文件,它用于文件输入操作,即从文件中读取数据ifstreamstd::basic_ifstream 的一个实例化,std::basic_ifstream 是一个模板类,用于处理各种字符类型的文件输入。ifstream 专门处理 char 类型的文件

基本使用总结

 文件打开和关闭,与Ofstream相同,构造函数打开,打开后程序可以从文件中读取数据,程序结束或者对象被销毁的时候,文件自动关闭。手动关闭就是close()

std::ifstream file("example.txt");
if (file.is_open()) {
    // 文件已成功打开,可以进行读取操作
}

读取数据,使用>>提取运算符从文件中读取数据

std::ifstream file("example.txt");
if (file.is_open()) {
    std::string str;
    int num;
    file >> str >> num;
    std::cout << "Read string: " << str << ", number: " << num << std::endl;
}

 检查文件状态,is_open是否成功打开,good()文件流是否处于有效状态,fail检查是否错误

std::ifstream file("example.txt");
if (!file) {
    std::cerr << "Failed to open the file." << std::endl;
}

 文件模式

  • std::ios::in:默认模式,表示文件用于读取。
  • std::ios::binary:以二进制模式打开文件,而非文本模式
std::ifstream file("example.txt", std::ios::binary);

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决MSPM0G3507芯片锁住的问题

编译环境&#xff1a;Windows 开发软件&#xff1a;Keil 开发主控&#xff1a;立创的MSPM0G3507 我们在MSPM0G3507时&#xff0c;常为芯片锁住烦恼&#xff0c;常见的锁死是因为使用了ST-Link&#xff0c;这里展示的是使用ST-Link后芯片锁死的解决步骤。 现象&a…

MySQL数据库入门,pycharm连接数据库—详细讲解

一.安装MySQL 1.常用MySQL5.7&#xff0c;首先安装MySQL&#xff0c; &#xff08;一&#xff09; &#xff08;二&#xff09; &#xff08;三&#xff09; &#xff08;四&#xff09; &#xff08;五&#xff09; 2.配置环境变量 打开MySQL安装路径&#xff0c;在其中找到…

python:画函数积分图

《高等数学》同济大学版 P209 编写 test_diff_area.py 如下 # -*- coding: utf-8 -*- """ 函数积分图 y x^3 -x^2 -x1 """ import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Polygondef func(x):return …

人工智能的普及造成了一场能源危机,但并不是无法解决。

人工智能的普及造成了一场能源危机&#xff0c;但并不是无法解决。 原文链接&#xff1a; 点击访问我的技术博客https://ai.weoknow.comhttps://ai.weoknow.com 人工智能&#xff08;AI&#xff09;的爆炸式增长促使科技巨头&#xff08;包括 Google、Meta、亚马逊和微软等&…

LeetCode刷题笔记第231题:2 的幂

LeetCode刷题笔记第231题&#xff1a;2 的幂 题目&#xff1a; 想法&#xff1a; 对输入的数值循环除以2直至数值小于等于1&#xff0c;如果最终的数值为1则为2的幂&#xff0c;小于1则不是2的幂。 class Solution:def isPowerOfTwo(self, n: int) -> bool:if n 1:retur…

[C#]winform基于opencvsharp结合Diffusion-Low-Light算法实现低光图像增强黑暗图片变亮变清晰

【训练源码】 https://github.com/JianghaiSCU/Diffusion-Low-Light 【参考源码】 https://github.com/hpc203/Diffusion-Low-Light-onnxrun 【论文地址】 https://arxiv.org/pdf/2306.00306.pdf 【算法原理图】 【效果展示】 【测试环境】 vs2019 netframework4.7.2 …

【数据结构】关于优先级队列(堆),你了解内部原理吗?(超详解!!!)

前言&#xff1a; &#x1f31f;&#x1f31f;Hello家人们&#xff0c;这期讲解二叉树的遍历&#xff0c;希望你能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;http://t.csdnimg.cn/EdeWV &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSD…

Iinux脚本bash:对自己的应用程序及其相关目录进行备份和恢复,并可查看备份计划、备份状态、备份大小等

目录 一、要求 1、需求 2、需求分析 二、脚本 1、总述 2、创建备份脚本 &#xff08;1&#xff09;脚本命名 &#xff08;2&#xff09;脚本内容 3、创建恢复脚本 &#xff08;1&#xff09;脚本命名 &#xff08;2&#xff09;脚本内容 4、设置cron作业 5、监控脚…

mybatis、mybatis-plus自定义插件,实现自定义策略数据脱敏功能

背景 mybatis中四大组件的作用,下面开发的插件拦截器会使用 四大组件Executor、StatementHandler、ParameterHandler、ResultSetHandler 需求 1、根据脱敏规则进行查询数据,显示的时候进行展示脱敏 2、根据脱敏规则进行查询数据,将脱敏后的数据批量更新回数据库,进行脱…

【Python系列】 Python打印99乘法表

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Vue+ElementUI技巧分享:创建一个带有进度显示的文件下载和打包组件

在现代前端开发中&#xff0c;用户体验至关重要&#xff0c;尤其是在处理文件下载时。为用户提供实时的下载进度显示和打包功能&#xff0c;不仅能提升用户体验&#xff0c;还能使应用更具专业性。在本文中&#xff0c;我们将创建一个 Vue 组件&#xff0c;用于显示文件下载进度…

视图变化 - 等比例变换防止视图拉伸

文章目录 使用场景等比变换等高填充等宽填充代码进行比目标宽高计算超出部分处理设置负的 marginclip 裁剪 End参考&#xff1a; 使用场景 在日常开发中&#xff0c;经常会遇到的一个需求是将图片/视频从界面的一个位置&#xff0c;变换到另一个位置。在处理这类问题的时候经常…

基于微信小程序的书籍销售预测系统的设计与实现(论文+源码)_kaic

摘 要 随着信息化社会的进步&#xff0c;我们的生活越来越便利。在网上&#xff0c;我们可以轻松地进行各种交易&#xff0c;其中包括图书交易。可以说&#xff0c;图书交易是网络交易的一个重要方面。本系统以面向对象的方式进行开发&#xff0c;使用MySQL作为主要数据存储…

linux centos stream9图形化操作

初学者对图形化操作比较熟悉,对字符界面、命令行比较陌生。本文讨论一下图形化操作的基本技能。希望初学者掌握后尽快使用字符界面,会执行命令,更会编程。 本案例是基于stream9版本,如版本不同,会有差别,注意操作使用。 一、安装图形化界面 Linux操作系统常用的图形用…

Unity URP无光照下Shadow 制作 <二> 合批处理

闲谈 相信大家在日常工作中发现了一个问题 &#xff0c; urp下虽然可以做到3个Pass 去写我们想要的效果&#xff0c;但是&#xff0c;不能合批&#xff08;不能合批&#xff0c;那不是我们CPU要干冒烟~&#xff01;&#xff09; 好家伙&#xff0c;熊猫老师的偏方来了 &#x…

Leetcode JAVA刷刷站(38)外观数列

一、题目概述 二、思路方向 为了解决这个问题&#xff0c;我们可以编写一个Java函数countAndSay&#xff0c;该函数接受一个整数n作为输入&#xff0c;并返回外观数列的第n个元素。这个函数将基于递归公式来构建数列&#xff0c;其中countAndSay(1) "1"&#xff0c;…

vue设置环境变量

1、在根目录地下建立两个文件&#xff0c;.env.development 和 .env.production VUE_APP_BASE_API"" .env.development这个就是开发环境&#xff0c;.env.production这个就是生产环境&#xff0c;也就是这个可以写本地的ip端口 .env.production 这个就是生产环境&…

Verilog刷题笔记51

题目&#xff1a; Now that you have a state machine that will identify three-byte messages in a PS/2 byte stream, add a datapath that will also output the 24-bit (3 byte) message whenever a packet is received (out_bytes[23:16] is the first byte, out_bytes[1…

14、springboot3 vue3开发平台-前端-自定义菜单组件,根据路由动态渲染

文章目录 1. 组件2 . 使用示例 1. 组件 src\components\menuTree\index.vue <template><template v-for"item in menuList"><!-- 分为两种方式渲染&#xff1a;有子菜单和没有子菜单--><!-- 没有子菜单--><el-menu-item :index&qu…

linux cpu问题排查及性能优化

cpu性能 一、cpu啥时候才叫有瓶颈 cpu运行的快还是慢、cpu有没有问题&#xff0c;cpu是不是还需要优化。这些是平常开发和运维中经常遇到的问题。那么我门到底如何去判断机器cpu运行的到底有没有异常呢。 从我排查问题来说&#xff0c;单看系统指标不能完全反应应用运行的状态…