模拟实现printf函数

本文探讨如何模拟实现printf函数,重点分析printf函数的参数存储方式,并通过示例展示如何处理不同类型的参数。通过理解printf函数的工作原理,可以自行构建类似功能的函数。
摘要由CSDN通过智能技术生成

标题 ##模拟实现printf函数,可完成下面的功能

//
//能完成下面函数的调用。
//print(“s ccc d.\n”,”hello”,’b’,’i’,’t’,100);
//函数原型:
//print(char *format, …)
//
1.认识一下printf:
在构建printf()函数之前,需要简单分析printf(),在帮助文档中可以看到,printf()的格式为printf (char * format,…)

2.需要了解这些参数是如何在内存中存储的。从这个栈桢结构图中可以看到print()函数的参数的存放方式,print()中的参数在形成临时变量时是从右往左的,这也就可以解释为什么只传入 char * format 就可以定位后面的不可变参数部分,char* format 作为左后一个传入的参数,可以方便的取出它的地址,那么下一个类型的地址就是第二个参数的地址

这里写图片描述

#define _CRT_SECURE_NO_WARNINGS 1  
#include <stdio.h>  
#include <windows.h>    
# include <stdarg.h>
//模拟实现printf函数,可完成下面的功能
//print("s ccc d\n", "hello", 'b', 'i', 't', 100);
//print("你好 bit\n");//对引号内容的直接输出
//能完成下面函数的调用。 
//函数原型: 
//print(char *format, ...) 
//
int print(char *s, ...)
{
    int i = 0;
    va_list str; //声明一个va_list 类型 str//头文件 # include <stdarg.h>
    va_start(str, s);//初始化
    char* ch = s;//将第一个参数保存,也就是"s ccc d \n",因为不能直接将其存到*ch里
    int a = va_arg(str, char);//这里是为了让va_arg(str,char)指向下一个参数,使用一次   va_arg(str,char),因为va_arg(str,char)每使用一次就会自动指向下一个参数。
    while (*ch)//构建一个循环来打印参数
    {
        if (*ch == 's')//当遇到's'时,说明需要打印字符串
        {
            char *put = *(&s + 1);//取"hello",用指针的原因是直接用va_arg(str,char)存放时放不下。
            while (*put)//循环打印"hello"的每个字符
            {
                putchar(*(put));
                put++;
            }
        }
        else if (*ch == 'c')//打印单个字符
        {
            putchar(va_arg(str, char));
        }
        else if (*ch == 'd')//打印整数
        {
            //因为声明是char*类型,这里的数字也会被认为是char类型的,需要转化一下
            int a = va_arg(str, char);//存整数
            int arr[20] = { 0 };//定义一个数组存放整数的每一位
            int cou = 0;
            int tmp = a;
            while (a > 9)//取每一位
            {
                tmp = a % 10;
                a = a / 10;
                cou++;
                arr[cou] = tmp;
                arr[cou] = tmp;
            }
            arr[cou] = a;//补上最后一次循环的内容
            while (cou)//循环打印每一位
            {
                putchar(arr[cou] + 48);
                cou--;
            }
            putchar(arr[cou] + 48);//补上左后一次循环的打印结果
        }
        else//无特殊条件直接输出
        {
            putchar(*ch);
        }
        ch++;
    }
}
int main()
{
    print("s ccc d\n", "hello", 'b', 'i', 't', 100);
    print("s \n ","你好bit\n");
    system("pause");
    return 0;
}

输出结果为
这里写图片描述
另一种:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<windows.h>
# include <stdio.h>
# include <string.h>
# include <stdarg.h>
void print_num(int x)//递归打印%d的数字打印函数
{
    /*if (x > 9)
    {
    return print_num(x / 10);//发现了我对递归的一种错误用法//发现结果一直为1,不能随便加return
    }
    putchar(x % 10 + '0');*/
    if (x > 9)
    {
        print_num(x / 10);
    }
    putchar(x % 10 + '0');
}
int nprint(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    char * pr = format;//获取第一个元素"%...."
    while (*pr)
    {
        switch (*pr)
        {
        case '%':
        {
            switch (*(++pr))
            {
               case 's':
                {
                    char * str = va_arg(args, char*);//因为是字符串,所以要用char*解引用
                     while (*str)
                     {
                        putchar(*str);
                        str++;
                    }
                }
                break;
                case'c':
                {
                  putchar(va_arg(args, char));//单个字符打印
                }
                break;
                case'd':
                {
                     print_num(va_arg(args, int));//递归打印,注意这里的(args,int)是int,整形,不是全都charcharchar
                }
                break;
                default:
                {
                    putchar(*(pr - 1));//是'%'但后面跟的字符不是要打印的格式化字符,直接输出'%',以及当前字符。
                     putchar(*pr);
                }
                break;
            }
        }
        break;
        default://第一个不是'%'的,直接输出
        {
           putchar(*pr);
        }
        break;
        }
        pr++;
    }
    va_end(args);
    return 0;
}
int main()
{
    nprint("%q%w%e%r%t测试一下会不会有其他%的\n%s %c%c%c %d\n", "hello ", 'b', 'i', 't', 100);
    system("pause");
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值