天天看点

可变参数列表来实现printf函数的输出

#include<stdio.h>

#include<stdarg.h>

void my_printf(const char*str,...)

{va_list arg;//创建变量

   va_start(arg,str);//初始化arg

   while(*str)

   {

   switch(*str)//运用switch case分支结构,将不同的情况输出

   case'c':

   char ch=va_arg(arg,char);//从arg后边读取相应的值

   putchar(ch);//输出字符

   break;

   }

   case's':

   char *pch=va_arg(arg,char*);

   while(*pch)

   putchar(*pch);

   pch++;

   default :

   putchar(*str);

   str++;

   va_end(arg);

}

int mian()

{

my_printf("%sccc","hello",'b','i','t');

return 0;

转载

 我想很多人和我一样,当对c语言有了一定了解之后,一定会对printf函数产生好奇,因为它可以接受不确定数目的参数。这是怎么实现的呢?看下它的声明:

    int printf(const char *fmt, ...);

    这个...表示的是什么,在c语言里面,这个叫做可变参数的声明,...就是说它有不确定个参数,专业术语叫可变参数。我们去看看它的源代码:

    int printf(const char *fmt, ...)

    {

        int res;

        va_list arg;

        va_start(arg, fmt);

        res = vprintf(fmt, arg);

        va_end(arg);

        return res;

    }

    原来它只是简单的调用vprintf,为了弄清什么是可变参数列表,是不是有必要去深究vprintf的代码呢,完全没有必要。下面我们来写一个求最小值的函数min,不过我们要做的当然与简单的#define min(a, b) (a < b? a: b)又所不同,我们来实现一个求任意个数的最小值的函数:

    int min(int n, int m, ...)

        int tmp;

        int res = m;

        va_start(arg, m);

        while (--n > 1)

        {

             tmp = va_arg(arg,int);

             if (tmp < res)

                 res = tmp;

        }

    是不是非常的简单。如何用呢,比如说你要求27,18,23,这三个数的最小值,你只需调用min(4,27,18,23,19),是不是很easy,第一个参数指定的是你需要求最小值的数的个数,后面就是具体的值。下面让我们来看看它是怎么工作的:

    在c语言中

   在进行参数调用时,会从右到左把参数压入栈中,对于min(4,27,18,23,19)的调用,其栈内布局如图1所示,

可变参数列表来实现printf函数的输出

     因为我们在min函数中已经设了n,m两个形参,所以最上面的两个参数值也就是4,27可以通过访问n,m直接得到,那么我们如何得到18,23,19这三个参数?这时候就需要va_list,也就是一个指针,我们首先定义一个va_list类型的参数arg,这时候arg指向的内容是不确定的。

     调用va_start(arg,m)将arg(注意arg是一个指针)移动到m的后面,如图2所示,此时arg指向的便是18。因为va_list是系统自定义的,所以我们一般不要直接取值,而是调用va_arg(arg,int),它的返回值是arg指针指向的内容,并且将arg下移一位,int表示的是参数的类型,对于我们来说是int,如图3所示。这样在while循环中我们就可以将所有的参数取出,当然也就可以得到最终的最小值。

    需要注意的时,在退出min函数前,必须调用va_end,否则可能会导致不可预料的结果。

    当然我们的函数只能处理int型的最小值,下面是利用c++中的template写的一个可以处理任意类型的min函数:

    #include <iostream>

    #include <cstdarg>

    using std::cout;

    using std::endl;

    template <typename type >

    type min(int n, type m, ...)

         type tmp;

         type res = m;

         std::va_list arg;

         va_start(arg, m);

         while (--n > 1)

         {

             tmp = va_arg(arg, type);

             res = tmp;

         }

         va_end(arg);