标题 ##模拟实现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;
}