我试图创建一个类似于printf()的自定义函数,但在精确打印浮点数时遇到错误。当我试图处理格式说明符的精度部分时,例如%.2f,就会出现问题。如何在自定义的类似printf()的函数中实现浮点数的精度处理?
**main函数:**有我想打印的文本:
int main(void)
{
fprint("first I fixed the integer call u can see here I can print an integer %d, I also can print a character: %c and a string: %s, and lastly I can print a float value like: %.2f\n", 567, 'a', "Hey", 65.13);
fprint("I can print this too: %%, without a problem\n");
return (0);
}
字符串
我常用的printf()类函数:
void fprint(char *str, ...)
{
va_list args;
int length = strlen(str);
char pr = '%';
char *s_holder, c_holder;
va_start(args, str);
for (int i = 0 ; i < length ; i++)
if (str[i] != '%')
{
write(1, &str[i], 1);
}
else if (str[i] == '%')
{
switch (str[i+1]){
case 'd':
print_integer(va_arg(args, int));
i += 1;
break;
case 'c':
c_holder = va_arg(args, int);
write(1, &c_holder, 1);
i += 1;
break;
case 's':
s_holder = va_arg(args, char *);
write(1, s_holder, strlen(s_holder));
i += 1;
break;
case 'f':
print_double(va_arg(args, double));
i += 1;
break;
case '.':
if (str[i + 2] >= '0' && str[i + 2] <= '9')
{
print_double2(va_arg(args, double), str[i + 2]);
i += 3;
}
else
{
write(1, &str[i], 1);
}
break;
default:
write(1, &str[i], 1);
break;
}
}
}
型
处理浮点数的函数:
void print_double2(int num, char cprecision)
{
int precision = atoi(cprecision);
//handling the negative numbers
if (num < 0)
{
write(1, "-", 1);
num = -num;
}
//separating the integer part from the fractional part
int int_part = (int)num;
double fract_part = num - int_part;
int int_fract;
char digit;
//printing the integer part of the double number with the print_integer function
print_integer(int_part);
write(1, ".", 1);
//printing the fraction part
while (fract_part > 0 && precision > 0)
{
fract_part *= 10;
int_fract = (int)fract_part; //getting the int part after mult by 10
digit = '0' + (int_fract % 10);
write(1, &digit, 1); //printing the integer part
fract_part -= int_fract; //removing the integer part to start the process again
precision--; //decrementing the precision until it get to 0.
}
}
型
我真的不知道该怎么办,我还是一个初学者,我一个月前才开始学习。我试着用chatgpt,但它没有帮助。😓
2条答案
按热度按时间wn9m85ua1#
字符串
您正在用点打印。你必须在
'f'
上打印,dot只指定 * 下一个数字 * 表示精度。我建议有状态,如果你看到一个点,并看到精度,你存储,然后将所有的状态传递给打印机。您可以在执行流中保留状态(当注意到一个点时,采取不同的路径),但不同状态组合的数量太大,将变得不可读。请考虑:型
然后,当解析时,你在字符到来时填充状态,并根据当前解析状态采取不同的行动:
型
然后在打印时,您必须考虑所有选项:
型
实现你自己的printf,尤其是浮点打印是一项非常艰巨的任务。特别是对于浮点数,你可能想阅读好的旧https://lists.nongnu.org/archive/html/gcl-devel/2012-10/pdfkieTlklRzN.pdf,学习标准的math.h头https://en.cppreference.com/w/c/numeric/math/modf和研究https://en.wikipedia.org/wiki/IEEE_754。
此外,github上有无数的printf用户实现,你可以从中获得灵感。
5vf7fwbs2#
我真的不知道该怎么办
保存时间,开启所有警告
后面的都是小事。启用所有警告。
类型不匹配
下面是错误的代码,因为
atoi()
需要一个指向 string 的指针,但代码提供了char
。字符串
类型错误
print_double2(va_arg(args, double), str[i + 2]);
发送一个doule
作为第一个地址,但void print_double2(int num, char cprecision)
需要一个int
。double fract_part = num - int_part;
总是0,因为num
是int
。它没有分数。溢出
如果
num
是double
,则int int_part = (int)num;
存在溢出风险。研究modf()
。弱方法
while (fract_part > 0 && precision > 0)
尝试一次打印一位小数,但不尝试对结果进行 * 舍入 *。我希望下面打印的是“4.88”而不是“4.87”。
型
好的舍入是困难的。不要将数字分成整数和小数部分,因为接近
xxx.999xxx
的情况将失败。更好的方法取决于您希望代码有多好-边缘情况很多。