这可能是个愚蠢的问题,但是......我尝试实现printf
,但是出现了一些输出结果不符合我的预期的原因。你有什么想法吗?我会很感激你的帮助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
static int print(const char *restrict fmt, ...);
static int getfloat(float *);
static char *itoa(int, char *, int);
static void _strrev(char *);
int
main(void)
{
float i1 = 0.0, i2 = 0.0, noi1 = 0.0, noi2 = 0.0, res = 0.0;
print("weight - item 1: ");
getfloat(&i1);
print("no. of item 1: ");
getfloat(&noi1);
print("weight - item 2: ");
getfloat(&i2);
print("no. of item 2: ");
getfloat(&noi2);
res = ((i1 * noi1) + (i2 * noi2)) / (noi1 + noi2);
print("%f\n", res);
exit(EXIT_SUCCESS);
}
static int
print(const char *restrict fmt, ...)
{
va_list ap;
char buf[BUFSIZ] = {0}, tmp[20] = {0};
char *str_arg;
int i = 0, j = 0;
va_start(ap, fmt);
while (fmt[i] != '\0') {
if (fmt[i] == '%') {
i++;
switch (fmt[i]) {
case 'c':
buf[j] = (char)va_arg(ap, int);
j++;
break;
case 'd':
itoa(va_arg(ap, int), tmp, 10);
strcpy(&buf[j], tmp);
j += strlen(tmp);
break;
case 'f':
gcvt(va_arg(ap, double), 10, tmp);
strcpy(&buf[j], tmp);
j += strlen(tmp);
break;
case 's':
str_arg = va_arg(ap, char *);
strcpy(&buf[j], str_arg);
j += strlen(str_arg);
break;
default:
break;
}
} else { buf[j++ ] = fmt[i]; }
++i;
}
fwrite(buf, j, 1, stdout);
va_end(ap);
return (j);
}
static int
getfloat(float *p)
{
int c, sign = 0;
float pwr = 0.0;
while (c = getc(stdin), c == ' ' || c == '\t' || c == '\n')
; /* ignore white spaces */
sign = 1; /* record sign */
if (c == '+' || c == '-') {
sign = (c == '+') ? 1 : -1;
c = getc(stdin);
}
for (*p = 0.0; isdigit(c); c = getc(stdin))
*p = 10.0 * *p + c - '0';
if (c == '.') { c = getc(stdin); }
for (pwr = 1.0; isdigit(c); c = getc(stdin)) {
*p = 10.0 * *p + c - '0';
pwr *= 10.0;
}
*p *= sign / pwr;
if (c != EOF)
ungetc(c, stdout);
return (float)c;
}
static char *
itoa(int n, char *strout, int base)
{
int i, sign;
if ((sign = n) < 0)
n -= n;
i = 0;
do {
strout[i++] = n % base + '0';
} while ((n /= base) != 0);
if (sign < 0) { strout[i++] = '-'; }
strout[i] = '\0';
_strrev(strout);
return (strout);
}
static void
_strrev(char *str)
{
int i = 0, j = strlen(str) - 1;
for ( ; i < j; ++i, --j) {
int tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
这是我获得的输出结果:
19.44444466而我期望的输出结果如下:(或者说,至少我希望获得以下输出结果,当我使用printf时,我就能得到这样的输出结果)
19.444445
gcvt()
返回8位数字,您会得到什么结果?反之,如果您使用printf("%.8f\n", res);
,您会得到什么结果? - Weather Vanetmp[20]
对于gcvt(-DBL_MAX, 10, tmp)
来说太小了。更像是tmp[320]
。即使是float
类型,也可能需要大约 50 个字符。 - chux - Reinstate Monica