可变个数参数(...)的使用

        对于某些应用场景,某些函数的功能很相近,但是传入函数的参数个数不一样,使得我们必须使用不同的函数,比如2个数求平均,或者3个数求平均,甚至其他更多参数的情况;
        今天使用可变长的函数来解决这个问题,需要使用标准库中包含的#include <stdio.h>和#include <stdarg.h>头文件,下面简述一下各个参数的意义。

1)  va_list是C语言中的一个宏定义,用于定义一个指向变长参数列表的指针。必须通过宏va_start进行初始化,使指针指向传入的可变数据的列表,通过va_arg访问列表中的元素,和使用va_end释放列表占用空间。在函数中需要接收不定数量的参数时,可以使用va_list来处理这些参数。
2)  va_start:初始化va_list的变量,它是一个宏定义,调用后va_list的变量指针指向传入的可变数据的列表的第一个元素。
        va_start宏需要两个参数,分别是一个va_list类型的变量 和 可变参数(...)前的最后一个固定参数的标识符.
        va_start宏没有返回值.
3)  va_arg:依次获取列表中的元素,每次调用宏后都会自动变更va_list指向的地址。
        va_arg宏需要两个参数,分别是一个va_list类型的变量 和 参数的数据类型.
        va_arg宏的返回值是列表中的元素。
4)  va_end:用于结束使用 va_start 和 va_arg 宏定义的可变参数列表,释放资源。   
        va_end宏需要一个参数,是一个va_list类型的变量。
        va_end宏没有返回值.

看下面的例子(代码):

Case1:求多个数的平均值。

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include <stdio.h>
#include <stdarg.h>

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
float average(int num, ...);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  main routine
  * @param  none
  * @retval none
  */
int main(void)
{
    /* USART initialization,baudrate 115200 8-N-1 , Remap fputc to usart1*/
    Debug_USART_Config();
    
    printf("Average of 255, 9, 16 = %f\r\n", average(3, 255,9,16));
    while (1)
    {}
}

/**
  * @brief  Average the variable amount of data
  * @param  num: Total number of data
  * @param  ...: variable data
  * @retval none
  */
float average(int num, ...)
{
    va_list valist;
    float sum ;
 
    va_start(valist, num);
 
    for (int i = 0; i < num; i++)
    {
       sum += va_arg(valist, int);
    }
    va_end(valist);
 
    return sum/num;
}

输出结果:Average of 255, 9, 16 = 93.333333
在这个case1中,average()函数中包括已固定的参数 num 和可变参数 ... ,在函数内部创建了va_list变量列表来表示可变参数,并用va_start进行初始化;使用va_arg获取列表中的元素,元素的表现方式为int数据类型,最后通过va_end释放资源。

case2: 将变长的输入变长的各种数据打印记录到文件中,此处暂记录到buffer中。

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include <stdio.h>
#include <stdarg.h>

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void my_convert(const char* format, ...);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  main routine
  * @param  none
  * @retval none
  */
int main(void)
{
    char argv0[] = "nice";
    char argv1[] = "to meet";
    char argv2[] = "you";
    /* USART initialization,baudrate 115200 8-N-1 , Remap fputc to usart1*/
    Debug_USART_Config();

    my_convert("\r\n%s %s %s\r\n",argv0,argv1,argv2);
    while (1)
    {}
}

/**
  * @brief  Convert variable strings to one string.
  * @param  format: general a printf format including the escape character.
  * @param  ...: variable strings
  * @retval none
  */
void my_convert(const char* format, ...)
{
  char buffer[256];
  va_list args;
  va_start (args, format);
  vsprintf (buffer,format, args);
  va_end (args);
  printf("%s",buffer);
}

输出结果:nice to meet you
在这个case2中,相比上面的case1,增加了vsprintf()函数,vsprintf函数通常用于把字符串格式化输出。它将数args按照字符串格式指定format进行格式化(包括%d%c%s%x等转义符),将输出果写入到字符串buffer中,并返回字符串长度,通过vsprintf()可以实现字符串的格式化输出,实现文件输出、参数输出和字符串输出等功能。

希望大家跟我交流哈~

遇事不决,可问春风,春风不语,即随本心。

诸君共勉!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值