我不仅试图将输出返回到
stdout
,而且还试图返回将要测试的每种数据类型的大小。我正在使用 write()
系统调用将简单输出写入 stdout
(是的,我坚持使用 write()
,因为它在空间 + 时间复杂度方面更有效)在我的 else
声明中,但我不是确定每个变量转换的case
子句的逻辑。此外,对我的代码组织的任何反馈以及任何反馈都将不胜感激。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdint.h>
char *convert(unsigned int, int);
int my_printf(char *format, ...)
{
va_list args;
va_start(args, format);
unsigned int i;
char *input;
char *s;
void *p;
for (input = format; *input != '\0'; input++)
{
if (*input == '%') {
input++;
//FETCH & EXECUTE VARIABLE CONVERSION
switch (*input)
{
case '%': write(1, "%", 1);
break;
case 'd': i = va_arg(args, int);
if (i <= 0)
{
i = -i;
write(1, "-", 1);
}
write(1, convert(i, 10), strlen(convert(i, 10)));
break;
case 'o': i = va_arg(args, unsigned int);
write(1, convert(i, 8), strlen(convert(i, 8)));
break;
case 'u': i = va_arg(args, unsigned int);
write(1, convert(i, 10), strlen(convert(i, 10)));
break;
case 'x': i = va_arg(args, unsigned int);
write(1, convert(i, 16), strlen(convert(i, 16)));
break;
case 'c': i = va_arg(args, int);
write(1, &i, 1);
break;
case 's': s = va_arg(args, char *);
write(1, s, strlen(s));
break;
case 'p': p = va_arg(args, void*);
intptr_t ptr_val = (intptr_t)p;
write(1, convert(ptr_val, 16), strlen(convert(ptr_val, 16)));
break;
default: write(1, input - 1, 2);
break;
}
}
else
{
write(1, input, 1);
}
}
va_end(args);
return 0;
}
char *convert(unsigned int n, int base)
{
static char Rep[] = "0123456789ABCDEF";
static char buffer[50];
char *ptr;
ptr = &buffer[49];
*ptr = '\0';
do
{
*--ptr = Rep[n % base];
n /= base;
}
while (n != 0);
return (ptr);
}
我尝试在每种情况下在
strlen()
内部使用write()
,但我没有取回数据字节大小值,我认为它可以与strlen()
一起使用。我也试过 size_t
和 sizeof
代替 strlen()
没有工作。
如果您希望返回代码中正在测试的每种数据类型的大小,请使用
sizeof()
运算符来确定每个变量类型的大小。例如,要查找整数的大小,请使用 sizeof(int)
。
要检索输出字符串的长度,请使用 strlen()
但是,如果您希望返回每次转换的输出字符串的大小,您还必须包括您正在写入 stdout
的任何其他字符的大小,例如换行符或空格。考虑将转换逻辑分解为不同的函数,以更好地构建代码并使其更易于阅读和维护。
[我]也在尝试返回将要测试的每种数据类型的大小
不清楚你的意思,但你应该返回输出的字符总数
stdout
.
请注意,直接为每个字符使用
write
系统调用和转换可能比使用 putchar()
并利用标准流函数执行的缓冲更有效。
你的代码有一些问题:
对于格式字符串
"%"
:您输出一个 %
和一个空字节并继续迭代超出字符串的末尾,调用未定义的行为。
转换数字两次是低效的。您应该存储
convert
返回的指针,并将其用作 write
和 strlen
的参数。或者,convert
可以返回生成的字符数以避免需要 strlen()
.
对负数的支持不完整:
INT_MIN
将调用未定义的行为,因为计算-i
会导致算术溢出。它产生一个负数,由 convert
计算的大多数数字都是负数,在使用负值索引 Rep[n % base]
时调用未定义的行为。
无符号转换
%u
和 %o
对于将被 convert
接收为负数的大值不正确。
format
%c
不适用于大端架构。您应该将字节值存储到 char
变量并将其传递给 write
.
format
%p
如果 intptr_t
是比 int
更大的类型并且不处理大指针值(负参数问题)。